void ZoaDebugFunctions::trimeshDrawNormals( ci::TriMesh &mesh ) { std::vector<ci::Vec3f> meshVertices = mesh.getVertices(); std::vector<ci::Vec3f> meshNormals = mesh.getNormals(); for( size_t i = 3; i < meshNormals.size(); i+=4 ) { float t = 0.5f; // Because T is 0.5 it's not really necessary but the we could project along the plane this way ci::Vec3f midPoint = ci::Vec3f( (1.0f - t) * ( meshVertices[i-2] ) + t * ( meshVertices[i] ) ); ci::Vec3f normal = meshNormals[i]*10; ci::gl::drawVector( midPoint, midPoint+normal, 10, 2.5); } }
void DelaunayMeshMaker::update(){ mTesselator->update(); if( mNeedsProcessing && mTesselator->isRunning() ){ mTesselator->interrupt(); }else if( mNeedsProcessing && !mTesselator->isRunning() ){ mNeedsProcessing = false; mTesselator->process( mBorderPoints, mSteinerPoints, mBlend, mSurface, mDepthOffset ); } if( mBlend != mPrevBlend ){ mPrevBlend = mBlend; } if( mDepthOffset != mPrevDepthOffset ){ std::vector<Vec3f> verts = mMesh.getVertices(); std::vector<Vec3f> newVerts; int count = 0; for( auto itr = verts.begin(); itr != verts.end(); ++itr ){ float z = (*itr).z; newVerts.push_back( Vec3f( (*itr).x, (*itr).y, mDepthRandom[count] * mDepthOffset ) ); count++; } mMesh.getVertices().swap( newVerts ); mMesh.recalculateNormals(); mVboMesh = gl::VboMesh( mMesh ); mPrevDepthOffset = mDepthOffset; } if( mScaleDown != mScaleDownPrev ){ mScaleDownPrev = mScaleDown; mEdgeDetectSurface = edgeDetect( Surface8u( mSurface ), mCannyMinThreshold, mCannyMaxThreshold, mScaleDownPrev ); } }
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 ); }