void Mesh::collapse_verts (void) { const DTuint HASH_TABLE_SIZE = 1021; DTsize num_old_verts = _vertex_stream.size(); DTsize num_new_verts = 0; // // Rebuild the mesh // std::vector<Vector3> vertex_stream; std::vector<Vector3> normals_stream; std::vector<Vector3> tangents_stream; std::vector<Color4b> colors_stream; std::vector<Vector2> uvs_stream_0; std::vector<Vector2> uvs_stream_1; std::vector<WeightsIndex> weights_index_stream; std::vector<Vector4> weights_strength_stream; if (_vertex_stream.size() > 0) vertex_stream.resize(num_old_verts); if (_normals_stream.size() > 0) normals_stream.resize(num_old_verts); if (_tangents_stream.size() > 0) tangents_stream.resize(num_old_verts); if (_colors_stream.size() > 0) colors_stream.resize(num_old_verts); if (_uvs_stream_0.size()) uvs_stream_0.resize(num_old_verts); if (_uvs_stream_1.size() > 0) uvs_stream_1.resize(num_old_verts); if (_weights_index_stream.size() > 0) weights_index_stream.resize(num_old_verts); if (_weights_strength_stream.size() > 0) weights_strength_stream.resize(num_old_verts); // Hash all vertices std::list<std::pair<DTuint, DTuint>> vert_hashes[HASH_TABLE_SIZE]; // new index, old index for (DTuint i = 0; i < num_old_verts; ++i) { DTuint h = hash_vertex(i); // Add vertex only if unique std::list<std::pair<DTuint, DTuint>> &list = vert_hashes[h % HASH_TABLE_SIZE]; std::list<std::pair<DTuint, DTuint>>::iterator j; for (j = list.begin(); j != list.end(); ++j) { if (j->second == i) continue; if (equal_vertex(j->second, i)) break; } // It is unique so add the vertex to the new geometry if (j == list.end()) { if (vertex_stream.size() > 0) vertex_stream[num_new_verts] = _vertex_stream[i]; if (normals_stream.size() > 0) normals_stream[num_new_verts] = _normals_stream[i]; if (tangents_stream.size() > 0) tangents_stream[num_new_verts] = _tangents_stream[i]; if (colors_stream.size() > 0) colors_stream[num_new_verts] = _colors_stream[i]; if (uvs_stream_0.size() > 0) uvs_stream_0[num_new_verts] = _uvs_stream_0[i]; if (uvs_stream_1.size() > 0) uvs_stream_1[num_new_verts] = _uvs_stream_1[i]; if (weights_index_stream.size() > 0) weights_index_stream[num_new_verts] = _weights_index_stream[i]; if (weights_strength_stream.size() > 0) weights_strength_stream[num_new_verts] = _weights_strength_stream[i]; vert_hashes[h % HASH_TABLE_SIZE].push_back( std::make_pair(num_new_verts, i) ); ++num_new_verts; } } // Time to re-wire the face indices for (DTuint f = 0; f < _indices_stream.size(); ++f) { DTuint &v0 = _indices_stream[f].v[0]; DTuint &v1 = _indices_stream[f].v[1]; DTuint &v2 = _indices_stream[f].v[2]; ASSERT(v0 < num_old_verts); ASSERT(v1 < num_old_verts); ASSERT(v2 < num_old_verts); DTuint h0 = hash_vertex(v0); DTuint h1 = hash_vertex(v1); DTuint h2 = hash_vertex(v2); // Add vertex only if unique std::list<std::pair<DTuint, DTuint>> &list0 = vert_hashes[h0 % HASH_TABLE_SIZE]; std::list<std::pair<DTuint, DTuint>> &list1 = vert_hashes[h1 % HASH_TABLE_SIZE]; std::list<std::pair<DTuint, DTuint>> &list2 = vert_hashes[h2 % HASH_TABLE_SIZE]; std::list<std::pair<DTuint, DTuint>>::iterator j; for (j = list0.begin(); j != list0.end(); ++j) { if (equal_vertex(j->second, v0)) { v0 = j->first; break; } } ASSERT(j != list0.end()); ASSERT(v0 < num_new_verts); for (j = list1.begin(); j != list1.end(); ++j) { if (equal_vertex(j->second, v1)) { v1 = j->first; break; } } ASSERT(j != list1.end()); ASSERT(v1 < num_new_verts); for (j = list2.begin(); j != list2.end(); ++j) { if (equal_vertex(j->second, v2)) { v2 = j->first; break; } } ASSERT(j != list2.end()); ASSERT(v2 < num_new_verts); } if (vertex_stream.size() > 0) vertex_stream.resize(num_new_verts); if (normals_stream.size() > 0) normals_stream.resize(num_new_verts); if (tangents_stream.size() > 0) tangents_stream.resize(num_new_verts); if (colors_stream.size() > 0) colors_stream.resize(num_new_verts); if (uvs_stream_0.size() > 0) uvs_stream_0.resize(num_new_verts); if (uvs_stream_1.size() > 0) uvs_stream_1.resize(num_new_verts); if (weights_index_stream.size() > 0) weights_index_stream.resize(num_new_verts); if (weights_strength_stream.size() > 0) weights_strength_stream.resize(num_new_verts); _vertex_stream = vertex_stream; _normals_stream = normals_stream; _tangents_stream = tangents_stream; _colors_stream = colors_stream; _uvs_stream_0 = uvs_stream_0; _uvs_stream_1 = uvs_stream_1; _weights_index_stream = weights_index_stream; _weights_strength_stream = weights_strength_stream; LOG_MESSAGE << "Old size: " << num_old_verts; LOG_MESSAGE << "New size: " << num_new_verts; }
void Mesh::generate_normals (void) { ASSERT(_vertex_stream.size() > 0); const DTuint HASH_TABLE_SIZE = 1021; _normals_stream.clear(); _normals_stream.resize(_vertex_stream.size(), Vector3(0.0F,0.0F,0.0F)); // Fill hash table std::list<DTuint> vert_hashes[HASH_TABLE_SIZE]; for (DTuint i = 0; i < _vertex_stream.size(); ++i) { DTuint h = hash_vertex (i, true); vert_hashes[h % HASH_TABLE_SIZE].push_back(i); } // Accumulate normals for (DTuint i = 0; i < _index_stream.size(); ++i) { DTuint ai,bi,ci; ai = _index_stream[i].v[0]; bi = _index_stream[i].v[1]; ci = _index_stream[i].v[2]; ASSERT(ai < _vertex_stream.size()); ASSERT(bi < _vertex_stream.size()); ASSERT(ci < _vertex_stream.size()); Vector3 n = Vector3::cross(_vertex_stream[bi] - _vertex_stream[ai], _vertex_stream[ci] - _vertex_stream[ai]); n.normalize(); // Hashes of vertex positions DTuint h0 = hash_vertex(ai, true); DTuint h1 = hash_vertex(bi, true); DTuint h2 = hash_vertex(ci, true); // Get hash entries for verts std::list<DTuint> &list0 = vert_hashes[h0 % HASH_TABLE_SIZE]; std::list<DTuint> &list1 = vert_hashes[h1 % HASH_TABLE_SIZE]; std::list<DTuint> &list2 = vert_hashes[h2 % HASH_TABLE_SIZE]; for (auto j : list0) { if (equal_vertex(ai, j, true)) _normals_stream[j] += n; } for (auto j : list1) { if (equal_vertex(bi, j, true)) _normals_stream[j] += n; } for (auto j : list2) { if (equal_vertex(ci, j, true)) _normals_stream[j] += n; } } for (DTuint i = 0; i < _vertex_stream.size(); ++i) if (_normals_stream[i] != Vector3(0.0F,0.0F,0.0F)) _normals_stream[i].normalize(); }