diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c5ef4c..fd80075 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ add_executable(asteroidgen src/Application.cpp src/Polygoniser.cpp src/TextureMapper.cpp + src/Mesh.cpp # src/TexturePainter.cpp # src/gen.cpp vendor/stb_impl.cpp diff --git a/src/Application.cpp b/src/Application.cpp index 09236dd..6f247b7 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -1,4 +1,5 @@ #include "Application.h" +#include "Mesh.h" #include #include @@ -25,162 +26,6 @@ using glm::uvec3; using std::map; using std::vector; -void calculateNormals(const vector &vtx, vector &tri, - vector &normals) { - normals.clear(); - normals.resize(vtx.size(), vec3(0)); - for (size_t i = 0; i < tri.size(); i++) { - int a = tri[i].x, b = tri[i].y, c = tri[i].z; - vec3 faceNormal = normalize( - glm::cross(vtx[b] - vtx[a], vtx[c] - vtx[a])); - normals[a] += faceNormal; - normals[b] += faceNormal; - normals[c] += faceNormal; - } - for (size_t i = 0; i < normals.size(); i++) - normals[i] = glm::normalize(normals[i]); - -} - -void moveToMean(vector &vtx) { - vec3 mean(0); - for (size_t i = 0; i < vtx.size(); i++) { - mean += vtx[i]; - } - mean *= vec3(1.f / vtx.size()); - for (size_t i = 0; i < vtx.size(); i++) { - vtx[i] -= mean; - } -} - -void smooth(vector &vtx, const vector &tri) { - vector cogs(vtx.size(), vec3(0.f)); - vector valence(vtx.size(), 0); - - for (size_t iTri = 0; iTri < tri.size(); iTri++) { - const uvec3 &idx = tri[iTri]; - for (size_t iE = 0; iE < 3; iE++) { - valence[idx[iE]] += 2; - cogs[idx[iE]] += vtx[idx[(iE + 1) % 3]]; - cogs[idx[iE]] += vtx[idx[(iE + 2) % 3]]; - } - } - /* - for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it) { - cog[0] = cog[1] = cog[2] = valence = 0.0; - - for (vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) { - cog += mesh.point(*vv_it); - ++valence; - } - cogs.push_back(cog / valence); - } - for (v_it = mesh.vertices_begin(), cog_it = cogs.begin(); v_it != v_end; - ++v_it, ++cog_it) - if (!mesh.is_boundary(*v_it)) - mesh.set_point(*v_it, *cog_it); - - */ - for (size_t i = 0; i < vtx.size(); i++) { -// vtx[i] = vtx[i] * vec3(0.8) -// + cogs[i] * vec3(0.2f / valence[i]); - vtx[i] = cogs[i] * vec3(1.f / valence[i]); - } -} - -void saveAttrib(std::ostream &out, const char *prefix, vector &elements) { - for (size_t i = 0; i < elements.size(); i++) { - out << prefix << elements[i].x << " " << elements[i].y << " " - << elements[i].z << "\n"; - } -} - -void saveAttrib(std::ostream &out, const char *prefix, - vector &elements) { - for (size_t i = 0; i < elements.size(); i++) { - out << prefix << elements[i].x << " " << elements[i].y << "\n"; - } -} - -void saveFaces(std::ostream &out, const vector &tris, size_t attribs) { - for (size_t i = 0; i < tris.size(); i++) { - out << "f"; - - for (size_t j = 0; j < 3; j++) { - int v = tris[i][j] + 1; - out << " " << v; - if (attribs > 1) - out << "/" << v; - if (attribs > 2) - out << "/" << v; - out << " "; - } - - out << "\n"; - } -} - -void calculateEdges(const vector &vtx, vector &tri, - vector &edges) { - edges.clear(); - map, uint32_t> edgeMap; - for (size_t iTri = 0; iTri < tri.size(); iTri++) { - uvec3 idx = tri[iTri]; - for (size_t k = 0; k < 3; k++) { - int a = idx[k]; - int b = idx[(k + 1) % 3]; - glm::uvec4 edge1(std::min(a, b), std::max(a, b), iTri, 0); - auto it1 = edgeMap.find(std::make_pair(edge1.x, edge1.y)); - if (it1 != edgeMap.end()) { - edges[it1->second].z = iTri; - } else { - edges.push_back(edge1); - } - } - } -} - -void computeTangentBasis(vector & vertices, vector & uvs, - vector & normals, vector & tangents, - vector & bitangents) { - - for (size_t i = 0; i < vertices.size(); i += 3) { - - // Shortcuts for vertices - vec3 & v0 = vertices[i + 0]; - vec3 & v1 = vertices[i + 1]; - vec3 & v2 = vertices[i + 2]; - - // Shortcuts for UVs - glm::vec2 & uv0 = uvs[i + 0]; - glm::vec2 & uv1 = uvs[i + 1]; - glm::vec2 & uv2 = uvs[i + 2]; - - // Edges of the triangle : postion delta - vec3 deltaPos1 = v1 - v0; - vec3 deltaPos2 = v2 - v0; - - // UV delta - glm::vec2 deltaUV1 = uv1 - uv0; - glm::vec2 deltaUV2 = uv2 - uv0; - - float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x); - vec3 tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r; - vec3 bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r; - // Set the same tangent for all three vertices of the triangle. - // They will be merged later, in vboindexer.cpp - tangents.push_back(tangent); - tangents.push_back(tangent); - tangents.push_back(tangent); - - // Same thing for binormals - bitangents.push_back(bitangent); - bitangents.push_back(bitangent); - bitangents.push_back(bitangent); - - } -} - static bool glck(const char* call) { int err = glGetError(); if (err == 0) { diff --git a/src/Mesh.cpp b/src/Mesh.cpp new file mode 100644 index 0000000..fa131b9 --- /dev/null +++ b/src/Mesh.cpp @@ -0,0 +1,164 @@ +#include "Mesh.h" + +#include + +#include + +using namespace std; +using namespace glm; + +void calculateNormals(const vector &vtx, vector &tri, + vector &normals) { + normals.clear(); + normals.resize(vtx.size(), vec3(0)); + for (size_t i = 0; i < tri.size(); i++) { + int a = tri[i].x, b = tri[i].y, c = tri[i].z; + vec3 faceNormal = normalize( + cross(vtx[b] - vtx[a], vtx[c] - vtx[a])); + normals[a] += faceNormal; + normals[b] += faceNormal; + normals[c] += faceNormal; + } + for (size_t i = 0; i < normals.size(); i++) + normals[i] = normalize(normals[i]); + +} + +void moveToMean(vector &vtx) { + vec3 mean(0); + for (size_t i = 0; i < vtx.size(); i++) { + mean += vtx[i]; + } + mean *= vec3(1.f / vtx.size()); + for (size_t i = 0; i < vtx.size(); i++) { + vtx[i] -= mean; + } +} + +void smooth(vector &vtx, const vector &tri) { + vector cogs(vtx.size(), vec3(0.f)); + vector valence(vtx.size(), 0); + + for (size_t iTri = 0; iTri < tri.size(); iTri++) { + const uvec3 &idx = tri[iTri]; + for (size_t iE = 0; iE < 3; iE++) { + valence[idx[iE]] += 2; + cogs[idx[iE]] += vtx[idx[(iE + 1) % 3]]; + cogs[idx[iE]] += vtx[idx[(iE + 2) % 3]]; + } + } + /* + for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it) { + cog[0] = cog[1] = cog[2] = valence = 0.0; + + for (vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) { + cog += mesh.point(*vv_it); + ++valence; + } + cogs.push_back(cog / valence); + } + for (v_it = mesh.vertices_begin(), cog_it = cogs.begin(); v_it != v_end; + ++v_it, ++cog_it) + if (!mesh.is_boundary(*v_it)) + mesh.set_point(*v_it, *cog_it); + + */ + for (size_t i = 0; i < vtx.size(); i++) { +// vtx[i] = vtx[i] * vec3(0.8) +// + cogs[i] * vec3(0.2f / valence[i]); + vtx[i] = cogs[i] * vec3(1.f / valence[i]); + } +} + +void saveAttrib(std::ostream &out, const char *prefix, vector &elements) { + for (size_t i = 0; i < elements.size(); i++) { + out << prefix << elements[i].x << " " << elements[i].y << " " + << elements[i].z << "\n"; + } +} + +void saveAttrib(std::ostream &out, const char *prefix, + vector &elements) { + for (size_t i = 0; i < elements.size(); i++) { + out << prefix << elements[i].x << " " << elements[i].y << "\n"; + } +} + +void saveFaces(std::ostream &out, const vector &tris, size_t attribs) { + for (size_t i = 0; i < tris.size(); i++) { + out << "f"; + + for (size_t j = 0; j < 3; j++) { + int v = tris[i][j] + 1; + out << " " << v; + if (attribs > 1) + out << "/" << v; + if (attribs > 2) + out << "/" << v; + out << " "; + } + + out << "\n"; + } +} + +void calculateEdges(const vector &vtx, vector &tri, + vector &edges) { + edges.clear(); + map, uint32_t> edgeMap; + for (size_t iTri = 0; iTri < tri.size(); iTri++) { + uvec3 idx = tri[iTri]; + for (size_t k = 0; k < 3; k++) { + int a = idx[k]; + int b = idx[(k + 1) % 3]; + uvec4 edge1(std::min(a, b), std::max(a, b), iTri, 0); + auto it1 = edgeMap.find(std::make_pair(edge1.x, edge1.y)); + if (it1 != edgeMap.end()) { + edges[it1->second].z = iTri; + } else { + edges.push_back(edge1); + } + } + } +} + +void computeTangentBasis(vector & vertices, vector & uvs, + vector & normals, vector & tangents, + vector & bitangents) { + + for (size_t i = 0; i < vertices.size(); i += 3) { + + // Shortcuts for vertices + vec3 & v0 = vertices[i + 0]; + vec3 & v1 = vertices[i + 1]; + vec3 & v2 = vertices[i + 2]; + + // Shortcuts for UVs + vec2 & uv0 = uvs[i + 0]; + vec2 & uv1 = uvs[i + 1]; + vec2 & uv2 = uvs[i + 2]; + + // Edges of the triangle : postion delta + vec3 deltaPos1 = v1 - v0; + vec3 deltaPos2 = v2 - v0; + + // UV delta + vec2 deltaUV1 = uv1 - uv0; + vec2 deltaUV2 = uv2 - uv0; + + float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x); + vec3 tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r; + vec3 bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r; + // Set the same tangent for all three vertices of the triangle. + // They will be merged later, in vboindexer.cpp + tangents.push_back(tangent); + tangents.push_back(tangent); + tangents.push_back(tangent); + + // Same thing for binormals + bitangents.push_back(bitangent); + bitangents.push_back(bitangent); + bitangents.push_back(bitangent); + + } +} diff --git a/src/Mesh.h b/src/Mesh.h new file mode 100644 index 0000000..8fbea85 --- /dev/null +++ b/src/Mesh.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +#include +#include + +void calculateNormals(const std::vector &vtx, + std::vector &tri, std::vector &normals); + +void moveToMean(std::vector &vtx); + +void smooth(std::vector &vtx, const std::vector &tri); + +void saveAttrib(std::ostream &out, const char *prefix, + std::vector &elements); + +void saveAttrib(std::ostream &out, const char *prefix, + std::vector &elements); + +void saveFaces(std::ostream &out, const std::vector &tris, + size_t attribs); + +void calculateEdges(const std::vector &vtx, + std::vector &tri, std::vector &edges); + +void computeTangentBasis(std::vector & vertices, + std::vector & uvs, std::vector & normals, + std::vector & tangents, std::vector & bitangents);