diff --git a/tests/g3etest.cpp b/tests/g3etest.cpp index dbfa83f..34caccb 100644 --- a/tests/g3etest.cpp +++ b/tests/g3etest.cpp @@ -37,7 +37,7 @@ struct defaults { float lodDropoff = 0.1; PNoise2 noise = PNoise2(42); - int meshResolution = 128; + int meshResolution = 16; float meshIsoLevel = 0.4f; }; @@ -190,8 +190,8 @@ void livePreview(Octree& grid, defaults& config, const Camera& cam) { if (meshNeedsUpdate) { scene.clear(); - std::shared_ptr planetMesh = grid.generateMesh(1, config.meshIsoLevel, config.meshResolution); - std::shared_ptr starMesh = grid.generateMesh(2, config.meshIsoLevel, config.meshResolution / 4); + std::shared_ptr planetMesh = grid.generateMesh(1, config.meshIsoLevel, pow(config.meshResolution, 2)); + std::shared_ptr starMesh = grid.generateMesh(2, config.meshIsoLevel, config.meshResolution); scene.addMesh(planetMesh); scene.addMesh(starMesh); @@ -506,7 +506,7 @@ int main() { ImGui::Separator(); ImGui::Text("Marching Cubes Config"); - if (ImGui::SliderInt("Mesh Resolution", &config.meshResolution, 16, 128)) { + if (ImGui::SliderInt("Mesh Resolution", &config.meshResolution, 1, 64)) { meshNeedsUpdate = true; } if (ImGui::SliderFloat("Iso Level", &config.meshIsoLevel, 0.01f, 1.0f)) { diff --git a/util/grid/mesh.hpp b/util/grid/mesh.hpp index 61ca49e..43a9327 100644 --- a/util/grid/mesh.hpp +++ b/util/grid/mesh.hpp @@ -39,14 +39,19 @@ private: std::vector> _polys; std::vector _colors; mutable std::vector _tris; + mutable std::vector _triNormals; mutable bool _needs_triangulation = true; + mutable bool _needs_norm_calc = true; inline static float edgeFunction(const Vector2f& a, const Vector2f& b, const Vector2f& c) { return (c.x() - a.x()) * (b.y() - a.y()) - (c.y() - a.y()) * (b.x() - a.x()); } public: Mesh(int id, const std::vector& verts, const std::vector>& polys, const std::vector& colors) - : id(id), _vertices(verts), _polys(polys), _colors(colors) {} + : id(id), _vertices(verts), _polys(polys), _colors(colors) { + _needs_triangulation = true; + _needs_norm_calc = true; + } std::vector vertices() { return _vertices; @@ -56,11 +61,13 @@ public: if (verts.size() != _colors.size()) { if (_colors.size() == 1) { _vertices = verts; + _needs_norm_calc = true; return true; } return false; } else { _vertices = verts; + _needs_norm_calc = true; return true; } } @@ -72,6 +79,7 @@ public: void triangulate() { if (!_needs_triangulation) return; std::vector newPols; + newPols.reserve(_polys.size() * 2); for (auto& pol : _polys) { if (pol.size() > 3) { auto v0 = pol[0]; @@ -84,7 +92,33 @@ public: } } _tris = newPols; + + _polys.clear(); + _polys.shrink_to_fit(); + _needs_triangulation = false; + _needs_norm_calc = true; + } + + void calculateNormals() { + if (!_needs_norm_calc) return; + + _triNormals.clear(); + _triNormals.reserve(_tris.size()); + + for (const auto& tri : _tris) { + Vector3f v0 = _vertices[tri.x()]; + Vector3f v1 = _vertices[tri.y()]; + Vector3f v2 = _vertices[tri.z()]; + + Vector3f edge1 = v1 - v0; + Vector3f edge2 = v2 - v0; + + // Normalized cross product gives the face normal + Vector3f normal = edge1.cross(edge2).normalized(); + _triNormals.push_back(normal); + } + _needs_norm_calc = false; } std::vector colors() { @@ -101,8 +135,10 @@ public: std::vector project_2d(Camera cam, int height, int width, float near, float far) { triangulate(); + calculateNormals(); std::vector renderList; + renderList.reserve(_tris.size()); Vector3f forward = cam.forward(); Vector3f right = cam.right(); @@ -160,7 +196,19 @@ public: validVerts[i] = true; } - for (const auto& triIdx : _tris) { + Vector3f camPos = cam.origin; + size_t triCount = _tris.size(); + + for (size_t t = 0; t < triCount; ++t) { + const auto& triIdx = _tris[t]; + + Vector3f p0 = _vertices[triIdx.x()]; + Vector3f viewDir = (p0 - camPos).normalized(); + + if (viewDir.dot(_triNormals[t]) >= 0.0f) { + continue; + } + int i0 = triIdx.x(); int i1 = triIdx.y(); int i2 = triIdx.z(); @@ -250,7 +298,9 @@ public: os << "Structure:\n"; os << " Total Vertices : " << _vertices.size() << "\n"; os << " Total Tris : " << _tris.size() << "\n"; - os << " Total Polys : " << _polys.size() << "\n"; + os << " Tri Normals : " << _triNormals.size() << "\n"; + if (_needs_triangulation) os << " Total Polys : " << _polys.size() << "\n"; + else os << " Polys (Cleared) : " << 0 << "\n"; os << " colors : " << _colors.size() << "\n"; } }; @@ -267,10 +317,12 @@ public: void addMesh(std::shared_ptr mesh) { _meshes.push_back(mesh); + updateStats(); } void clear() { _meshes.clear(); + updateStats(); } frame render(Camera cam, int height, int width, float near, float far, frame::colormap colorformat = frame::colormap::RGB) {