asteroidgen/src/Mesh.cpp

269 lines
7.0 KiB
C++
Raw Normal View History

2017-10-29 05:28:00 +01:00
#include "Mesh.h"
#include <glm/geometric.hpp>
#include <map>
2017-11-02 03:44:44 +01:00
#include <limits>
#include <stack>
2017-10-29 05:28:00 +01:00
using namespace std;
using namespace glm;
2017-11-02 03:44:44 +01:00
static const uvec3::value_type InvalidIndex =
numeric_limits<uvec3::value_type>::max();
void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices,
vec3v_t &normals) {
2017-10-29 05:28:00 +01:00
normals.clear();
2017-11-02 03:44:44 +01:00
normals.resize(positions.size(), vec3(0));
#pragma omp parallel for
for (size_t i = 0; i < indices.size(); i++) {
int a = indices[i].x, b = indices[i].y, c = indices[i].z;
vec3 faceNormal = normalize(
cross(positions[b] - positions[a],
positions[c] - positions[a]));
2017-10-29 05:28:00 +01:00
normals[a] += faceNormal;
normals[b] += faceNormal;
normals[c] += faceNormal;
}
for (size_t i = 0; i < normals.size(); i++)
normals[i] = normalize(normals[i]);
}
2017-11-02 03:44:44 +01:00
void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices,
vec3v_t &normals) {
normals.clear();
normals.resize(indices.size(), vec3(uninitialize));
#pragma omp parallel for
for (size_t i = 0; i < indices.size(); i++) {
int a = indices[i].x, b = indices[i].y, c = indices[i].z;
normals[i] = normalize(
cross(positions[b] - positions[a],
positions[c] - positions[a]));
}
}
void moveToMean(vec3v_t &positions) {
2017-10-29 05:28:00 +01:00
vec3 mean(0);
2017-11-02 03:44:44 +01:00
for (size_t i = 0; i < positions.size(); i++) {
mean += positions[i];
2017-10-29 05:28:00 +01:00
}
2017-11-02 03:44:44 +01:00
mean *= vec3(1.f / positions.size());
for (size_t i = 0; i < positions.size(); i++) {
positions[i] -= mean;
2017-10-29 05:28:00 +01:00
}
}
2017-11-02 03:44:44 +01:00
void smooth(vec3v_t &positions, const uvec3v_t &indices) {
vec3v_t cogs(positions.size(), vec3(0.f));
vector<int> valence(positions.size(), 0);
2017-10-29 05:28:00 +01:00
2017-11-02 03:44:44 +01:00
for (size_t iTri = 0; iTri < indices.size(); iTri++) {
const uvec3 &idx = indices[iTri];
2017-10-29 05:28:00 +01:00
for (size_t iE = 0; iE < 3; iE++) {
valence[idx[iE]] += 2;
2017-11-02 03:44:44 +01:00
cogs[idx[iE]] += positions[idx[(iE + 1) % 3]];
cogs[idx[iE]] += positions[idx[(iE + 2) % 3]];
2017-10-29 05:28:00 +01:00
}
}
/*
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);
*/
2017-11-02 03:44:44 +01:00
#pragma omp parallel for
for (size_t i = 0; i < positions.size(); i++) {
2017-10-29 05:28:00 +01:00
// vtx[i] = vtx[i] * vec3(0.8)
// + cogs[i] * vec3(0.2f / valence[i]);
2017-11-02 03:44:44 +01:00
positions[i] = cogs[i] * vec3(1.f / valence[i]);
2017-10-29 05:28:00 +01:00
}
}
2017-10-29 06:25:04 +01:00
void saveAttrib(std::ostream &out, const char *prefix, vec3v_t &elements) {
2017-10-29 05:28:00 +01:00
for (size_t i = 0; i < elements.size(); i++) {
out << prefix << elements[i].x << " " << elements[i].y << " "
<< elements[i].z << "\n";
}
}
2017-10-29 06:25:04 +01:00
void saveAttrib(std::ostream &out, const char *prefix, vec2v_t &elements) {
2017-10-29 05:28:00 +01:00
for (size_t i = 0; i < elements.size(); i++) {
out << prefix << elements[i].x << " " << elements[i].y << "\n";
}
}
2017-11-02 03:44:44 +01:00
void saveFaces(std::ostream &out, const uvec3v_t &incdices, size_t attribs) {
for (size_t i = 0; i < incdices.size(); i++) {
2017-10-29 05:28:00 +01:00
out << "f";
for (size_t j = 0; j < 3; j++) {
2017-11-02 03:44:44 +01:00
int v = incdices[i][j] + 1;
2017-10-29 05:28:00 +01:00
out << " " << v;
if (attribs > 1)
out << "/" << v;
if (attribs > 2)
out << "/" << v;
out << " ";
}
out << "\n";
}
}
2017-11-02 03:44:44 +01:00
void findEdges(const vec3v_t &positions, const uvec3v_t &indices,
uvec4v_t &edges) {
2017-10-29 05:28:00 +01:00
edges.clear();
map<pair<uint32_t, uint32_t>, uint32_t> edgeMap;
2017-11-02 03:44:44 +01:00
for (size_t iTri = 0; iTri < indices.size(); iTri++) {
uvec3 idx = indices[iTri];
2017-10-29 05:28:00 +01:00
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);
2017-11-02 03:44:44 +01:00
auto key = std::make_pair(edge1.x, edge1.y);
auto it1 = edgeMap.find(key);
2017-10-29 05:28:00 +01:00
if (it1 != edgeMap.end()) {
2017-11-02 03:44:44 +01:00
edges[it1->second].w = iTri;
2017-10-29 05:28:00 +01:00
} else {
2017-11-02 03:44:44 +01:00
size_t idx = edges.size();
2017-10-29 05:28:00 +01:00
edges.push_back(edge1);
2017-11-02 03:44:44 +01:00
edgeMap[key] = idx;
2017-10-29 05:28:00 +01:00
}
}
}
}
2017-11-02 03:44:44 +01:00
void computeTangentBasis(vec3v_t & positions, vec2v_t & texcoords,
vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents) {
2017-10-29 05:28:00 +01:00
2017-11-02 03:44:44 +01:00
for (size_t i = 0; i < positions.size(); i += 3) {
2017-10-29 05:28:00 +01:00
// Shortcuts for vertices
2017-11-02 03:44:44 +01:00
vec3 & v0 = positions[i + 0];
vec3 & v1 = positions[i + 1];
vec3 & v2 = positions[i + 2];
2017-10-29 05:28:00 +01:00
// Shortcuts for UVs
2017-11-02 03:44:44 +01:00
vec2 & uv0 = texcoords[i + 0];
vec2 & uv1 = texcoords[i + 1];
vec2 & uv2 = texcoords[i + 2];
2017-10-29 05:28:00 +01:00
// 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);
}
}
2017-11-02 03:44:44 +01:00
void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents) {
printf("findAdjacent: %lu\n", nFaces);
adjacents.resize(nFaces, uvec3(InvalidIndex));
for (size_t i = 0; i < edges.size(); i++) {
int a = edges[i].z;
int b = edges[i].w;
uvec3 &aa = adjacents[a];
for (size_t j = 0; j < 3; j++) {
if (aa[j] == InvalidIndex) {
aa[j] = b;
break;
}
}
uvec3 &ab = adjacents[b];
for (size_t j = 0; j < 3; j++) {
if (ab[j] == InvalidIndex) {
ab[j] = a;
break;
}
}
}
}
void createPatches(const vec3v_t &positions, const uvec3v_t &indices,
const vec3v_t &faceNormals, const uvec3v_t &adjacents,
vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches,
float threshold) {
assert(adjacents.size() == indices.size());
patches.clear();
oPositions.clear();
oIndices.clear();
vector<bool> processed(indices.size(), false);
for (size_t i = 0; i < indices.size(); i++) {
if (processed[i])
continue;
vector<uint32_t> faces;
map<uint32_t, uint32_t> vertexMap;
vec3 normal = faceNormals[i];
// check all adjacent faces
stack<uint32_t> facesToCheck;
facesToCheck.push(i);
while (facesToCheck.size()) {
uint32_t face = facesToCheck.top();
facesToCheck.pop();
if (face == InvalidIndex || processed[face])
continue;
if (dot(normal, faceNormals[face]) > threshold) {
faces.push_back(face);
//normal = normalize(normal + 0.5f * faceNormals[face]);
processed[face] = true;
facesToCheck.push(adjacents[face].x);
facesToCheck.push(adjacents[face].y);
facesToCheck.push(adjacents[face].z);
}
}
// fill new arrays
for (size_t j = 0; j < faces.size(); j++) {
uvec3 idx = indices[faces[j]];
for (size_t k = 0; k < 3; k++) {
auto it = vertexMap.find(idx[k]);
if (it == vertexMap.end()) {
uint32_t newIdx = oPositions.size();
oPositions.push_back(positions[idx[k]]);
vertexMap[idx[k]] = newIdx;
idx[k] = newIdx;
} else {
idx[k] = it->second;
}
}
oIndices.push_back(idx);
}
printf("\n");
}
}