void mCSkin::LimitNumInfluencingBonesPerVert( MIUInt const a_uMax ) { mTArray< MIUInt > arrVertexIndices( m_arrVertexIndices.GetCount() ); mTArray< MIUInt > arrBoneIndices( m_arrBoneIndices.GetCount() ); mTArray< MIFloat > arrWeights( m_arrWeights.GetCount() ); mTArray< MIUInt > arrVertWeightIndices( 0, 100 ); MIUInt * pVertWeightIndices = arrVertWeightIndices.AccessBuffer(); for ( MIUInt u = 0, ue = GetNumVerts(); u != ue; ++u ) { MIUInt uWeightCount = GetNumInfluencingBones( u ); MIFloat fWeightSum = 0.0f; s_pWeights = &m_arrWeights[ m_arrFirstWeightIndexPerVertex[ u ] ]; for ( MIUInt v = uWeightCount; v--; pVertWeightIndices[ v ] = v ); qsort( pVertWeightIndices, uWeightCount, sizeof( *pVertWeightIndices ), &CompareVretWeightIndices ); uWeightCount = g_min( uWeightCount, a_uMax ); for ( MIUInt v = 0; v != uWeightCount; ++v ) { arrVertexIndices.Add( u ); arrBoneIndices.Add( GetBoneIndex( u, pVertWeightIndices[ v ] ) ); arrWeights.Add( s_pWeights[ pVertWeightIndices[ v ] ] ); fWeightSum += s_pWeights[ pVertWeightIndices[ v ] ]; } for ( MIFloat * pWeights = &arrWeights.Back(), * pEnd = pWeights - uWeightCount; pWeights != pEnd; *pWeights-- /= fWeightSum ); } arrVertexIndices.UnReserve(); arrBoneIndices.UnReserve(); arrWeights.UnReserve(); mCSkin skinResult; skinResult.InitSwapping( GetNumVerts(), m_arrBoneIDs, arrVertexIndices, arrBoneIndices, arrWeights ); Swap( skinResult ); }
/*! * \param [in] v the vertex to add, Vector3<float> * \param [out] indx the index to the vertex, unsigned int * \return a bool indicating whether the HalfEdgeMesh::Vertex was successfully inserted (true) or already existed (false) */ bool HalfEdgeMesh::AddVertex(const Vector3<float> & v, unsigned int &indx){ std::map<Vector3<float>,unsigned int>::iterator it = mUniqueVerts.find(v); if (it != mUniqueVerts.end()){ indx = (*it).second; // get the index of the already existing vertex return false; } mUniqueVerts[v] = indx = GetNumVerts(); // op. [ ] constructs a new entry in map Vertex vert; vert.pos = v; mVerts.push_back(vert); // add it to the vertex list return true; }
MIUInt mCSkin::GetNumInfluencingBones( MIUInt a_uVertexIndex ) const { MIUInt const uNextFirstIndex = ( a_uVertexIndex + 1 < GetNumVerts() ) ? m_arrFirstWeightIndexPerVertex[ a_uVertexIndex + 1 ] : GetNumWeights(); return uNextFirstIndex - m_arrFirstWeightIndexPerVertex[ a_uVertexIndex ]; }
void HalfEdgeMesh::Update() { // Calculate and store all differentials and area // First update all face normals and triangle areas for(unsigned int i = 0; i < GetNumFaces(); i++){ f(i).normal = FaceNormal(i); } // Then update all vertex normals and curvature for(unsigned int i = 0; i < GetNumVerts(); i++){ // Vertex normals are just weighted averages mVerts.at(i).normal = VertexNormal(i); } // Then update vertex curvature for(unsigned int i = 0; i < GetNumVerts(); i++){ mVerts.at(i).curvature = VertexCurvature(i); // std::cerr << mVerts.at(i).curvature << "\n"; } // Finally update face curvature for(unsigned int i = 0; i < GetNumFaces(); i++){ f(i).curvature = FaceCurvature(i); } std::cerr << "Area: " << Area() << ".\n"; std::cerr << "Volume: " << Volume() << ".\n"; // Update vertex and face colors if (mVisualizationMode == CurvatureVertex) { std::vector<Vertex>::iterator iter = mVerts.begin(); std::vector<Vertex>::iterator iend = mVerts.end(); float minCurvature = (std::numeric_limits<float>::max)(); float maxCurvature = -(std::numeric_limits<float>::max)(); while (iter != iend) { if (minCurvature > (*iter).curvature) minCurvature = (*iter).curvature; if (maxCurvature < (*iter).curvature) maxCurvature = (*iter).curvature; iter++; } std::cerr << "Mapping color based on vertex curvature with range [" << minCurvature << "," << maxCurvature << "]" << std::endl; iter = mVerts.begin(); while (iter != iend) { (*iter).color = mColorMap->Map((*iter).curvature, minCurvature, maxCurvature); iter++; } } else if (mVisualizationMode == CurvatureFace) { std::vector<Face>::iterator iter = mFaces.begin(); std::vector<Face>::iterator iend = mFaces.end(); float minCurvature = (std::numeric_limits<float>::max)(); float maxCurvature = -(std::numeric_limits<float>::max)(); while (iter != iend) { if (minCurvature > (*iter).curvature) minCurvature = (*iter).curvature; if (maxCurvature < (*iter).curvature) maxCurvature = (*iter).curvature; iter++; } std::cerr << "Mapping color based on face curvature with range [" << minCurvature << "," << maxCurvature << "]" << std::endl; iter = mFaces.begin(); while (iter != iend) { (*iter).color = mColorMap->Map((*iter).curvature, minCurvature, maxCurvature); iter++; } } }
/*! Proceeds to check if the mesh is valid. All indices are inspected and * checked to see that they are initialized. The method checks: mEdges, mFaces and mVerts. * Also checks to see if all verts have a neighborhood using the findNeighbourFaces method. */ void HalfEdgeMesh::Validate() { std::vector<HalfEdge>::iterator iterEdge = mEdges.begin(); std::vector<HalfEdge>::iterator iterEdgeEnd = mEdges.end(); while (iterEdge != iterEdgeEnd) { if ((*iterEdge).face == UNINITIALIZED || (*iterEdge).next == UNINITIALIZED || (*iterEdge).pair == UNINITIALIZED || (*iterEdge).prev == UNINITIALIZED || (*iterEdge).vert == UNINITIALIZED) std::cerr << "HalfEdge " << iterEdge - mEdges.begin() << " not properly initialized" << std::endl; iterEdge++; } std::cerr << "Done with edge check (checked " << GetNumEdges() << " edges)" << std::endl; std::vector<Face>::iterator iterTri = mFaces.begin(); std::vector<Face>::iterator iterTriEnd = mFaces.end(); while (iterTri != iterTriEnd) { if ((*iterTri).edge == UNINITIALIZED) std::cerr << "Tri " << iterTri - mFaces.begin() << " not properly initialized" << std::endl; iterTri++; } std::cerr << "Done with face check (checked " << GetNumFaces() << " faces)" << std::endl; std::vector<Vertex>::iterator iterVertex = mVerts.begin(); std::vector<Vertex>::iterator iterVertexEnd = mVerts.end(); while (iterVertex != iterVertexEnd) { if ((*iterVertex).edge == UNINITIALIZED) std::cerr << "Vertex " << iterVertex - mVerts.begin() << " not properly initialized" << std::endl; iterVertex++; } std::cerr << "Done with vertex check (checked " << GetNumVerts() << " vertices)" << std::endl; std::cerr << "Looping through triangle neighborhood of each vertex... "; iterVertex = mVerts.begin(); iterVertexEnd = mVerts.end(); int emptyCount = 0; std::vector<unsigned int> problemVerts; while (iterVertex != iterVertexEnd) { std::vector<unsigned int> foundFaces = FindNeighborFaces(iterVertex - mVerts.begin()); std::vector<unsigned int> foundVerts = FindNeighborVertices(iterVertex - mVerts.begin()); if (foundFaces.empty() || foundVerts.empty()) emptyCount++; std::set<unsigned int> uniqueFaces(foundFaces.begin(), foundFaces.end()); std::set<unsigned int> uniqueVerts(foundVerts.begin(), foundVerts.end()); if ( foundFaces.size() != uniqueFaces.size() || foundVerts.size() != uniqueVerts.size() ) problemVerts.push_back(iterVertex - mVerts.begin()); iterVertex++; } std::cerr << std::endl << "Done: " << emptyCount << " isolated vertices found" << std::endl; if(problemVerts.size()){ std::cerr << std::endl << "Found " << problemVerts.size() << " duplicate faces in vertices: "; std::copy(problemVerts.begin(), problemVerts.end(), std::ostream_iterator<unsigned int>(std::cerr, ", ")); std::cerr << "\n"; } std::cerr << std::endl << "The mesh has genus " << Genus() << ", and consists of " << Shells() << " shells.\n"; }
int StaticMesh::GetAvailableVertexSpace() const { return MAX_VERTICES - GetNumVerts(); }
int MyMeshText::CreateString(bool concat, float fontheight, float x, float y, float z, float rotz, unsigned char justificationflags, ColorByte color, Vector2 size, const char* text, ...) { assert( m_pFont && m_pFont->m_pFont ); if( strlen( text ) == 0 ) return 0; const char* stringtodraw = text; if( g_pLanguageTable != 0 && text[0] == '.' ) stringtodraw = g_pLanguageTable->LookUp( text ); int numlines = 0; if( concat == false ) { ClearText(); } bool moretexttocome = true; const char* stringpos = stringtodraw; while( moretexttocome ) { numlines++; char singlelinebuffer[300]; singlelinebuffer[0] = 0; char* singlelinebufferpos = singlelinebuffer; // word wrap if width of text is not 0. if( size.x != 0 ) { float linewidth = -1;// = GetStringSize( fontheight, Vector2(0,0), singlelinebuffer ).x; while( linewidth < size.x && *stringpos != 0 ) { *singlelinebufferpos = *stringpos; singlelinebufferpos++; *singlelinebufferpos = 0; stringpos++; linewidth = GetStringSize( fontheight, Vector2(0,0), singlelinebuffer ).x; assert( singlelinebufferpos < singlelinebuffer + 300 ); } int numcharswewentback = 0; while( ( *(singlelinebufferpos-1) != ' ' && *stringpos != 0 ) && singlelinebufferpos > singlelinebuffer ) { singlelinebufferpos--; numcharswewentback++; } if( singlelinebufferpos != singlelinebuffer ) { *singlelinebufferpos = 0; stringpos -= numcharswewentback; } if( *stringpos == 0 ) moretexttocome = false; stringtodraw = singlelinebuffer; } else { moretexttocome = false; } //// don't bother drawing if fontheight is zero... still doing logic above so the currect number of lines will be returned. //if( g_pRTQGlobals->m_WordWrapCountLinesOnly ) // continue; Vertex_XYZUV_RGBA* pVertsToDraw = (Vertex_XYZUV_RGBA*)GetVerts( true ); int newverts = (int)strlen( stringtodraw ) * 4; #if _DEBUG m_MostLettersAttemptedToDrawThisFrame += newverts/4; if( m_MostLettersAttemptedToDrawThisFrame > m_MostLettersAttemptedToDrawEver ) m_MostLettersAttemptedToDrawEver = m_MostLettersAttemptedToDrawThisFrame; #endif if( m_NumVertsToDraw + newverts > GetNumVerts() ) { #if _DEBUG LOGInfo( LOGTag, "TextMesh buffer isn't big enough for string (%s) - %d of %d letters used - most letters needed (%d)\n", stringtodraw, m_NumVertsToDraw/4, GetNumVerts()/4, m_MostLettersAttemptedToDrawEver ); #endif //assert( false ); // drawing more than we have room for. return 0; } pVertsToDraw += m_NumVertsToDraw; unsigned int textstrlen = m_pFont->m_pFont->GenerateVerts( stringtodraw, true, pVertsToDraw, fontheight, GL_TRIANGLES, justificationflags, color ); m_NumVertsToDraw += (unsigned short)(textstrlen * 4); m_NumIndicesToDraw += textstrlen * 6; MyMatrix position; position.SetIdentity(); position.Rotate( rotz, 0, 0, 1 ); position.SetPosition( x, y - (numlines-1)*fontheight, z ); //position.SetPosition( x, y - (numlines-1)*g_pRTQGlobals->m_WordWrapLineIncSize, z ); //position.SetPosition( x, y, z ); for( unsigned int i=0; i<textstrlen*4; i++ ) { Vector3 out = position.TransformVector3( *(Vector3*)&pVertsToDraw[i].x ); pVertsToDraw[i].x = out.x; pVertsToDraw[i].y = out.y; pVertsToDraw[i].z = out.z; } } return numlines; }