#include "terrain.h" #include "game/geoData.h" #include "gfx/models/texture.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static constexpr RGB openSurface {-1}; Terrain::Terrain(std::shared_ptr tm) : geoData {std::move(tm)}, grass {std::make_shared("grass.png")} { generateMeshes(); } template<> VertexArrayObject & VertexArrayObject::addAttribsFor(const GLuint arrayBuffer, const GLuint divisor) { return addAttribs( arrayBuffer, divisor); } void Terrain::generateMeshes() { meshes.removeAll(); std::vector indices; indices.reserve(geoData->n_faces() * 3); std::vector vertices; vertices.reserve(geoData->n_vertices()); std::map, size_t> vertexIndex; std::for_each(geoData->vertices_sbegin(), geoData->vertices_end(), [this, &vertexIndex, &vertices](const GeoData::VertexHandle v) { std::for_each(geoData->vf_begin(v), geoData->vf_end(v), [&vertexIndex, v, this, &vertices](const GeoData::FaceHandle f) { const auto surface = geoData->get_surface(f); if (const auto vertexIndexRef = vertexIndex.emplace(std::make_pair(v, surface), 0); vertexIndexRef.second) { vertexIndexRef.first->second = vertices.size(); vertices.emplace_back(geoData->point(v), geoData->normal(v), surface ? surface->colorBias : openSurface); } }); }); std::for_each( geoData->faces_sbegin(), geoData->faces_end(), [this, &vertexIndex, &indices](const GeoData::FaceHandle f) { std::transform(geoData->fv_begin(f), geoData->fv_end(f), std::back_inserter(indices), [&vertexIndex, f, this](const GeoData::VertexHandle v) { return vertexIndex[std::make_pair(v, geoData->get_surface(f))]; }); }); meshes.create>(vertices, indices); } void Terrain::tick(TickDuration) { if (const auto newGeneration = geoData->getGeneration(); newGeneration != geoGeneration) { generateMeshes(); geoGeneration = newGeneration; } } void Terrain::render(const SceneShader & shader) const { shader.landmass.use(); grass->bind(); meshes.apply(&Mesh::Draw); } void Terrain::shadows(const ShadowMapper & shadowMapper) const { shadowMapper.landmess.use(); meshes.apply(&Mesh::Draw); }