void ZoaDebugFunctions::addQuadToMesh( ci::TriMesh& mesh, const ci::Vec3f& P0, const ci::Vec3f& P1, const ci::Vec3f& P2, const ci::Vec3f& P3, const ci::ColorA& color ) { ci::Vec3f e0 = P2 - P0; ci::Vec3f e1 = P2 - P1; ci::Vec3f n = e0.cross(e1).normalized(); mesh.appendVertex( P0 ); mesh.appendColorRGBA( color ); mesh.appendNormal( n ); mesh.appendVertex( P1 ); mesh.appendColorRGBA( color ); mesh.appendNormal( n ); mesh.appendVertex( P2 ); mesh.appendColorRGBA( color ); mesh.appendNormal( n ); mesh.appendVertex( P3 ); mesh.appendColorRGBA( color ); mesh.appendNormal( n ); int vert0 = mesh.getNumVertices() - 4; int vert1 = mesh.getNumVertices() - 1; int vert2 = mesh.getNumVertices() - 2; int vert3 = mesh.getNumVertices() - 3; mesh.appendTriangle( vert0, vert3, vert1 ); mesh.appendTriangle( vert3, vert2, vert1 ); }
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 ); }
void World::generateMesh(ci::TriMesh & mesh) { using namespace ci; Vec3f offset = Vec3f(m_size * -0.5f, m_size * -0.5f, m_size * -0.5f); for (size_t z = 0; z < m_size; ++z) for (size_t y = 0; y < m_size; ++y) for (size_t x = 0; x < m_size; ++x) { if (cell(x, y, z) == AIR) { for (size_t i = 0; i < 6; ++i) { int index = getNeigbour(x, y, z, i); if (index != -1) { if (cell(index) == DIRT) { Vec3f normal = getNeigbourOffset(i); Vec3f up = std::abs(normal.dot(Vec3f::yAxis())) > 0.9f ? Vec3f::zAxis() : Vec3f::yAxis(); Vec3f side = normal.cross(up) * 0.5f; up = up * 0.5f; Vec3f pos = offset + Vec3f(x, y, z) + (normal * 0.5f); size_t indexStart = mesh.getNumVertices(); // Layout of the quad // // 0 --------------- 3 // | ^ up | // | | | // | side | | // | <-----o pos | // | | // | | // | | // 1 --------------- 2 // Create the vertex data mesh.appendVertex(pos + side + up); mesh.appendVertex(pos + side - up); mesh.appendVertex(pos - side - up); mesh.appendVertex(pos - side + up); mesh.appendNormal(-normal); mesh.appendNormal(-normal); mesh.appendNormal(-normal); mesh.appendNormal(-normal); // Create triangle data mesh.appendTriangle(indexStart + 0, indexStart + 1, indexStart + 2); mesh.appendTriangle(indexStart + 0, indexStart + 2, indexStart + 3); } } } } } }