void ZoaDebugFunctions::calculateTriMeshNormals( ci::TriMesh &mesh ) { const std::vector<ci::Vec3f>& vertices = mesh.getVertices(); const std::vector<uint32_t>& indices = mesh.getIndices(); // remove all current normals std::vector<ci::Vec3f>& normals = mesh.getNormals(); normals.reserve( mesh.getNumVertices() ); normals.clear(); // set the normal for each vertex to (0, 0, 0) for(size_t i=0; i < mesh.getNumVertices(); ++i) normals.push_back( ci::Vec3f::zero() ); // Average out the normal for each vertex at an index for(size_t i=0; i< mesh.getNumTriangles(); ++i) { ci::Vec3f v0 = vertices[ indices[i * 3] ]; ci::Vec3f v1 = vertices[ indices[i * 3 + 1] ]; ci::Vec3f v2 = vertices[ indices[i * 3 + 2] ]; // calculate normal and normalize it, so each of the normals equally contributes to the final result ci::Vec3f e0 = v2 - v0; ci::Vec3f e1 = v2 - v1; ci::Vec3f n = e0.cross(e1).normalized(); // add the normal to the final result, so we get an average of the normals of each triangle normals[ indices[i * 3] ] += n; normals[ indices[i * 3 + 1] ] += n; normals[ indices[i * 3 + 2] ] += n; } // the normals are probably not normalized by now, so make sure their lengths will be 1.0 as expected for(size_t i=0;i< normals.size();++i) { normals[i].normalize(); } }
TriMesh MeshHelper::subdivide( const ci::TriMesh &triMesh, uint32_t division, bool normalize ) { if ( division <= 1 || triMesh.getNumIndices() == 0 || triMesh.getNumVertices() == 0 ) { return triMesh; } vector<uint32_t> indices = triMesh.getIndices(); vector<Vec3f> normals = triMesh.getNormals(); vector<Vec3f> positions = triMesh.getVertices(); vector<Vec2f> texCoords = triMesh.getTexCoords(); vector<uint32_t> indicesBuffer( indices ); indices.clear(); indices.reserve( indicesBuffer.size() * 4 ); uint32_t index0; uint32_t index1; uint32_t index2; uint32_t index3; uint32_t index4; uint32_t index5; for ( vector<uint32_t>::const_iterator iter = indicesBuffer.begin(); iter != indicesBuffer.end(); ) { index0 = *iter; ++iter; index1 = *iter; ++iter; index2 = *iter; ++iter; if ( normalize ) { index3 = positions.size(); positions.push_back( positions.at( index0 ).lerp( 0.5f, positions.at( index1 ) ).normalized() * 0.5f ); index4 = positions.size(); positions.push_back( positions.at( index1 ).lerp( 0.5f, positions.at( index2 ) ).normalized() * 0.5f ); index5 = positions.size(); positions.push_back( positions.at( index2 ).lerp( 0.5f, positions.at( index0 ) ).normalized() * 0.5f ); } else { index3 = positions.size(); positions.push_back( positions.at( index0 ).lerp( 0.5f, positions.at( index1 ) ) ); index4 = positions.size(); positions.push_back( positions.at( index1 ).lerp( 0.5f, positions.at( index2 ) ) ); index5 = positions.size(); positions.push_back( positions.at( index2 ).lerp( 0.5f, positions.at( index0 ) ) ); } if ( !normals.empty() ) { normals.push_back( normals.at( index0 ).lerp( 0.5f, normals.at( index1 ) ) ); normals.push_back( normals.at( index1 ).lerp( 0.5f, normals.at( index2 ) ) ); normals.push_back( normals.at( index2 ).lerp( 0.5f, normals.at( index0 ) ) ); } if ( !texCoords.empty() ) { texCoords.push_back( texCoords.at( index0 ).lerp( 0.5f, texCoords.at( index1 ) ) ); texCoords.push_back( texCoords.at( index1 ).lerp( 0.5f, texCoords.at( index2 ) ) ); texCoords.push_back( texCoords.at( index2 ).lerp( 0.5f, texCoords.at( index0 ) ) ); } indices.push_back( index0 ); indices.push_back( index3 ); indices.push_back( index5 ); indices.push_back( index3 ); indices.push_back( index1 ); indices.push_back( index4 ); indices.push_back( index5 ); indices.push_back( index4 ); indices.push_back( index2 ); indices.push_back( index3 ); indices.push_back( index4 ); indices.push_back( index5 ); } ci::TriMesh mesh = create( indices, positions, normals, texCoords ); indices.clear(); normals.clear(); positions.clear(); texCoords.clear(); return subdivide( mesh, division - 1, normalize ); }