void CalCoreBone::calculateBoundingBox(CalCoreModel * pCoreModel) { int boneId = m_pCoreSkeleton->getCoreBoneId(m_strName); bool bBoundsComputed = false; initBoundingBox(); int meshId; for(meshId=0; meshId < pCoreModel->getCoreMeshCount(); ++meshId) { CalCoreMesh * pCoreMesh = pCoreModel->getCoreMesh(meshId); int submeshId; for(submeshId=0;submeshId<pCoreMesh->getCoreSubmeshCount();submeshId++) { CalCoreSubmesh *pCoreSubmesh = pCoreMesh->getCoreSubmesh(submeshId); if(pCoreSubmesh->getSpringCount()==0) { std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pCoreSubmesh->getVectorVertex(); for(size_t vertexId=0;vertexId <vectorVertex.size(); ++vertexId) { for(size_t influenceId=0;influenceId<vectorVertex[vertexId].vectorInfluence.size();++influenceId) { CalCoreSubmesh::Influence &influence = vectorVertex[vertexId].vectorInfluence[influenceId]; if(influence.boneId == boneId && influence.weight > 0.5f) { const bool updated = updateBoundingBox(vectorVertex[vertexId].position); bBoundsComputed = bBoundsComputed || updated; } } } } } } // To handle bones with no vertices assigned (do not "optimize" this code away!) if(!bBoundsComputed) { for(int planeId = 0; planeId < 6; ++planeId) { m_boundingBox.plane[planeId].setPosition(m_translation); m_boundingPosition[planeId] = m_translation; } } m_boundingBoxPrecomputed = true; }
U1 Resource::CreateHardwareBuff( MeshHDBuffer* pOutBuff,CalCoreMesh* pInMesh ){ std::vector<ABuff> vertexData; std::vector<UInt> indexData; SInt iMeshCount = pInMesh->getCoreSubmeshCount(); SInt iVertexCount = 0; SInt iIndexCount = 0; //首先计算顶点数 和 索引数 for(SInt i=0;i<iMeshCount;i++){ CalCoreSubmesh* pSubMesh = pInMesh->getCoreSubmesh(i); iVertexCount += pSubMesh->getVectorVertex().size(); iIndexCount += pSubMesh->getFaceCount()*3; } if( iVertexCount == 0 || iIndexCount == 0) { return false; } //分配空间 vertexData.resize(iVertexCount); indexData.resize(iIndexCount); SInt iV = 0; SInt iI = 0; for(SInt i=0;i<iMeshCount;i++){ CalCoreSubmesh* pSubMesh = pInMesh->getCoreSubmesh(i); //计算切线 pSubMesh->enableTangents(0,true); std::vector<CalCoreSubmesh::Vertex>& lstVector = pSubMesh->getVectorVertex(); std::vector<std::vector<CalCoreSubmesh::TangentSpace> >& lstTangent = pSubMesh->getVectorVectorTangentSpace(); std::vector<std::vector<CalCoreSubmesh::TextureCoordinate> >& lstTexcoord = pSubMesh->getVectorVectorTextureCoordinate(); std::vector<CalCoreSubmesh::Face>& lstFace = pSubMesh->getVectorFace(); SInt iFaceCount = lstFace.size(); //索引缓冲 for(SInt j=0;j<iFaceCount;j++){ indexData[iI] = lstFace[j].vertexId[0] + iV; indexData[iI+1] = lstFace[j].vertexId[1] + iV; indexData[iI+2] = lstFace[j].vertexId[2] + iV; iI += 3; } //顶点缓冲数据 for(SInt j=0;j<iVertexCount;j++){ CalCoreSubmesh::Vertex& ver = lstVector[j]; CalCoreSubmesh::TangentSpace tang = lstTangent[0][j]; CalCoreSubmesh::TextureCoordinate uv = lstTexcoord[0][j]; //位置 vertexData[iV].Position = Float3(ver.position.x,ver.position.y,ver.position.z); SInt iBoneCount = ver.vectorInfluence.size(); for(SInt k=0;k<4;k++){ if(k<iBoneCount){ vertexData[iV].BoneWeight[k] = ver.vectorInfluence[k].weight*255.0f; //如果只传递自己需要的矩阵 //骨骼索引变成0~n vertexData[iV].BoneIndex[k] = ver.vectorInfluence[k].boneId; }else{ vertexData[iV].BoneWeight[k] = 0; vertexData[iV].BoneIndex[k] = 0; } } //法线 vertexData[iV].Normal = Float3(ver.normal.x,ver.normal.y,ver.normal.z); //UV vertexData[iV].UV.x = uv.u; vertexData[iV].UV.y = uv.v; //切线 vertexData[iV].Tangent.x = tang.tangent.x; vertexData[iV].Tangent.y = tang.tangent.y; vertexData[iV].Tangent.z = tang.tangent.z; iV++; } AString strName = m_strProductName + pInMesh->getName(); Render::Vertex::IDeclare::Info dInfo; dInfo.SetPNTT_Animation(); pOutBuff->pVertexDeclare = Render::System::GetSingleton()->CreateProduct<Render::Vertex::IDeclare>("PNTTANIM",&dInfo); Render::Buffer::Info vInfo; vInfo.SetVertexBuffer(iVertexCount,52); vInfo.InitData = &vertexData[0]; pOutBuff->pVertexBuff = Render::System::GetSingleton()->CreateProduct<Render::Buffer>(strName+"VB",&vInfo); vInfo.SetIndexBuffer32(iFaceCount*3); vInfo.InitData = &indexData[0]; pOutBuff->pIndexBuff = Render::System::GetSingleton()->CreateProduct<Render::Buffer>(strName+"IB",&vInfo); } return true; }
CalCoreModel* osgCal::loadCoreModel( const std::string& cfgFileName, float& scale, bool ignoreMeshes ) throw (std::runtime_error) { // -- Initial loading of model -- scale = 1.0f; bool bScale = false; FILE* f = fopen( cfgFileName.c_str(), "r" ); if( !f ) { throw std::runtime_error( "Can't open " + cfgFileName ); } FileCloser closer( f ); std::auto_ptr< CalCoreModel > calCoreModel( new CalCoreModel( "dummy" ) ); // Extract path from fileName std::string dir = osgDB::getFilePath( cfgFileName ); static const int LINE_BUFFER_SIZE = 4096; char buffer[LINE_BUFFER_SIZE]; while ( fgets( buffer, LINE_BUFFER_SIZE,f ) ) { // Ignore comments or empty lines if ( *buffer == '#' || *buffer == 0 ) continue; char* equal = strchr( buffer, '=' ); if ( equal ) { // Terminates first token *equal++ = 0; // Removes ending newline ( CR & LF ) { int last = strlen( equal ) - 1; if ( equal[last] == '\n' ) equal[last] = 0; if ( last > 0 && equal[last-1] == '\r' ) equal[last-1] = 0; } // extract file name. all animations, meshes and materials names // are taken from file name without extension std::string nameToLoad; char* point = strrchr( equal, '.' ); if ( point ) { nameToLoad = std::string( equal, point ); } else { nameToLoad = equal; } std::string fullpath = dir + "/" + std::string( equal ); // process .cfg parameters if ( !strcmp( buffer, "scale" ) ) { bScale = true; std::istringstream equal_stream(equal); equal_stream.imbue(std::locale::classic()); equal_stream >> scale; continue; } if ( !strcmp( buffer, "skeleton" ) ) { if( !calCoreModel->loadCoreSkeleton( fullpath ) ) { throw std::runtime_error( "Can't load skeleton: " + CalError::getLastErrorDescription() ); } } else if ( !strcmp( buffer, "animation" ) ) { int animationId = calCoreModel->loadCoreAnimation( fullpath ); if( animationId < 0 ) { throw std::runtime_error( "Can't load animation " + nameToLoad + ": " + CalError::getLastErrorDescription() ); } calCoreModel->getCoreAnimation(animationId) ->setName( nameToLoad ); } else if ( !strcmp( buffer, "mesh" ) ) { if ( ignoreMeshes ) { // we don't need meshes since VBO data is already loaded // from cache continue; } int meshId = calCoreModel->loadCoreMesh( fullpath ); if( meshId < 0 ) { throw std::runtime_error( "Can't load mesh " + nameToLoad + ": " + CalError::getLastErrorDescription() ); } calCoreModel->getCoreMesh( meshId )->setName( nameToLoad ); // -- Remove zero influence vertices -- // warning: this is a temporary workaround and subject to // remove! (this actually must be fixed in blender exporter) CalCoreMesh* cm = calCoreModel->getCoreMesh( meshId ); for ( int i = 0; i < cm->getCoreSubmeshCount(); i++ ) { CalCoreSubmesh* sm = cm->getCoreSubmesh( i ); std::vector< CalCoreSubmesh::Vertex >& v = sm->getVectorVertex(); for ( size_t j = 0; j < v.size(); j++ ) { std::vector< CalCoreSubmesh::Influence >& infl = v[j].vectorInfluence; std::vector< CalCoreSubmesh::Influence >::iterator it = infl.begin(); for ( ;it != infl.end(); ) { if ( it->weight <= 0.0001 ) it = infl.erase( it ); else ++it; } std::sort( infl.begin(), infl.end(), DataCmp<CalCoreSubmesh::Influence,float> (FIELD_OFFSET(CalCoreSubmesh::Influence,weight)) ); } } } else if ( !strcmp( buffer, "material" ) ) { int materialId = calCoreModel->loadCoreMaterial( fullpath ); if( materialId < 0 ) { throw std::runtime_error( "Can't load material " + nameToLoad + ": " + CalError::getLastErrorDescription() ); } else { calCoreModel->createCoreMaterialThread( materialId ); calCoreModel->setCoreMaterialId( materialId, 0, materialId ); CalCoreMaterial* material = calCoreModel->getCoreMaterial( materialId ); material->setName( nameToLoad ); } } } }
void loadMeshes( CalCoreModel* calCoreModel, MeshesVector& meshes ) throw (std::runtime_error) { const int maxVertices = Constants::MAX_VERTEX_PER_MODEL; const int maxFaces = Constants::MAX_VERTEX_PER_MODEL * 3; std::auto_ptr< CalHardwareModel > calHardwareModel( new CalHardwareModel( calCoreModel ) ); osg::ref_ptr< VertexBuffer > vertexBuffer( new VertexBuffer( maxVertices ) ); osg::ref_ptr< WeightBuffer > weightBuffer( new WeightBuffer( maxVertices ) ); osg::ref_ptr< MatrixIndexBuffer > matrixIndexBuffer( new MatrixIndexBuffer( maxVertices ) ); osg::ref_ptr< NormalBuffer > normalBuffer( new NormalBuffer( maxVertices ) ); osg::ref_ptr< NormalBuffer > tangentBuffer( new NormalBuffer( maxVertices ) ); osg::ref_ptr< NormalBuffer > binormalBuffer( new NormalBuffer( maxVertices ) ); osg::ref_ptr< TexCoordBuffer > texCoordBuffer( new TexCoordBuffer( maxVertices ) ); std::vector< CalIndex > indexBuffer( maxFaces*3 ); std::vector< float > floatMatrixIndexBuffer( maxVertices*4 ); calHardwareModel->setVertexBuffer((char*)vertexBuffer->getDataPointer(), 3*sizeof(float)); #ifdef OSG_CAL_BYTE_BUFFERS std::vector< float > floatNormalBuffer( getVertexCount()*3 ); calHardwareModel->setNormalBuffer((char*)&floatNormalBuffer.begin(), 3*sizeof(float)); #else calHardwareModel->setNormalBuffer((char*)normalBuffer->getDataPointer(), 3*sizeof(float)); #endif calHardwareModel->setWeightBuffer((char*)weightBuffer->getDataPointer(), 4*sizeof(float)); calHardwareModel->setMatrixIndexBuffer((char*)&floatMatrixIndexBuffer.front(), 4*sizeof(float)); calHardwareModel->setTextureCoordNum( 1 ); calHardwareModel->setTextureCoordBuffer(0, // texture stage # (char*)texCoordBuffer->getDataPointer(), 2*sizeof(float)); calHardwareModel->setIndexBuffer( &indexBuffer.front() ); // calHardwareModel->setCoreMeshIds(_activeMeshes); // if ids not set all meshes will be used at load() time //std::cout << "calHardwareModel->load" << std::endl; calHardwareModel->load( 0, 0, Constants::MAX_BONES_PER_MESH ); //std::cout << "calHardwareModel->load ok" << std::endl; int vertexCount = calHardwareModel->getTotalVertexCount(); // int faceCount = calHardwareModel->getTotalFaceCount(); // std::cout << "vertexCount = " << vertexCount << "; faceCount = " << faceCount << std::endl; GLubyte* matrixIndexBufferData = (GLubyte*) matrixIndexBuffer->getDataPointer(); for ( int i = 0; i < vertexCount*4; i++ ) { matrixIndexBufferData[i] = static_cast< GLubyte >( floatMatrixIndexBuffer[i] ); } #ifdef OSG_CAL_BYTE_BUFFERS GLbyte* normals = (GLbyte*) normalBuffer->getDataPointer(); for ( int i = 0; i < vertexCount*3; i++ ) { normals[i] = static_cast< GLbyte >( floatNormalBuffer[i]*127.0 ); } #endif // invert UVs for OpenGL (textures are inverted otherwise - for example, see abdulla/klinok) GLfloat* texCoordBufferData = (GLfloat*) texCoordBuffer->getDataPointer(); for ( float* tcy = texCoordBufferData + 1; tcy < texCoordBufferData + 2*vertexCount; tcy += 2 ) { *tcy = 1.0f - *tcy; } // -- And now create meshes data -- int unriggedBoneIndex = calCoreModel->getCoreSkeleton()->getVectorCoreBone().size(); // we add empty bone in ModelData to handle unrigged vertices; for( int hardwareMeshId = 0; hardwareMeshId < calHardwareModel->getHardwareMeshCount(); hardwareMeshId++ ) { calHardwareModel->selectHardwareMesh(hardwareMeshId); int faceCount = calHardwareModel->getFaceCount(); if ( faceCount == 0 ) { continue; // we ignore empty meshes } CalHardwareModel::CalHardwareMesh* hardwareMesh = &calHardwareModel->getVectorHardwareMesh()[ hardwareMeshId ]; osg::ref_ptr< MeshData > m( new MeshData ); m->name = calCoreModel->getCoreMesh( hardwareMesh->meshId )->getName(); m->coreMaterial = hardwareMesh->pCoreMaterial; if ( m->coreMaterial == NULL ) { CalCoreMesh* coreMesh = calCoreModel->getCoreMesh( hardwareMesh->meshId ); CalCoreSubmesh* coreSubmesh = coreMesh->getCoreSubmesh( hardwareMesh->submeshId ); // hardwareMesh->pCoreMaterial = // coreModel->getCoreMaterial( coreSubmesh->getCoreMaterialThreadId() ); char buf[ 1024 ]; snprintf( buf, 1024, "pCoreMaterial == NULL for mesh '%s' (mesh material id = %d), verify your mesh file data", m->name.c_str(), coreSubmesh->getCoreMaterialThreadId() ); throw std::runtime_error( buf ); } // -- Create index buffer -- int indexesCount = faceCount * 3; int startIndex = calHardwareModel->getStartIndex(); if ( indexesCount <= 0x100 ) { m->indexBuffer = new osg::DrawElementsUByte( osg::PrimitiveSet::TRIANGLES, indexesCount ); GLubyte* data = (GLubyte*)m->indexBuffer->getDataPointer(); const CalIndex* i = &indexBuffer[ startIndex ]; const CalIndex* iEnd = &indexBuffer[ startIndex + indexesCount ]; while ( i < iEnd ) { *data++ = (GLubyte)*i++; } } else if ( indexesCount <= 0x10000 ) { m->indexBuffer = new osg::DrawElementsUShort( osg::PrimitiveSet::TRIANGLES, indexesCount ); GLushort* data = (GLushort*)m->indexBuffer->getDataPointer(); const CalIndex* i = &indexBuffer[ startIndex ]; const CalIndex* iEnd = &indexBuffer[ startIndex + indexesCount ]; while ( i < iEnd ) { *data++ = (GLushort)*i++; } } else { m->indexBuffer = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, indexesCount ); GLuint* data = (GLuint*)m->indexBuffer->getDataPointer(); const CalIndex* i = &indexBuffer[ startIndex ]; const CalIndex* iEnd = &indexBuffer[ startIndex + indexesCount ]; while ( i < iEnd ) { *data++ = (GLuint)*i++; } } // -- Create other buffers -- int vertexCount = calHardwareModel->getVertexCount(); int baseVertexIndex = calHardwareModel->getBaseVertexIndex(); #define SUB_BUFFER( _type, _name ) \ new _type( _name->begin() + baseVertexIndex, \ _name->begin() + baseVertexIndex + vertexCount ) m->vertexBuffer = SUB_BUFFER( VertexBuffer, vertexBuffer ); m->weightBuffer = SUB_BUFFER( WeightBuffer, weightBuffer ); m->matrixIndexBuffer = SUB_BUFFER( MatrixIndexBuffer, matrixIndexBuffer ); m->normalBuffer = SUB_BUFFER( NormalBuffer, normalBuffer ); m->texCoordBuffer = SUB_BUFFER( TexCoordBuffer, texCoordBuffer ); // -- Parameters and buffers setup -- m->boundingBox = calculateBoundingBox( m->vertexBuffer.get() ); m->bonesIndices = hardwareMesh->m_vectorBonesIndices; checkRigidness( m.get(), unriggedBoneIndex ); checkForEmptyTexCoord( m.get() ); generateTangentAndHandednessBuffer( m.get(), &indexBuffer[ startIndex ] ); meshes.push_back( m.get() ); } }
bool CalHardwareModel::load(int baseVertexIndex, int startIndex,int maxBonesPerMesh) { if(m_pVertexBuffer==NULL || m_pNormalBuffer ==NULL|| m_pWeightBuffer ==NULL || m_pMatrixIndexBuffer ==NULL) { CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__); return false; } int mapId; for(mapId = 0; mapId < m_textureCoordNum; mapId++) { if(m_pTextureCoordBuffer[mapId]==NULL) { CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__); return false; } } m_vectorVertexIndiceUsed.resize(50000); int vertexCount=baseVertexIndex; int faceIndexCount = startIndex; // unused. //CalCoreSkeleton * pCoreSkeleton = m_pCoreModel->getCoreSkeleton(); //std::vector< CalCoreBone *>& vectorBone = pCoreSkeleton->getVectorCoreBone(); // if unspecified, fill with all core mesh ids if(m_coreMeshIds.empty()) { for(int coreMeshId = 0; coreMeshId < m_pCoreModel->getCoreMeshCount(); coreMeshId++) m_coreMeshIds.push_back(coreMeshId); } for(std::vector<int>::iterator meshIdIt = m_coreMeshIds.begin();meshIdIt != m_coreMeshIds.end(); meshIdIt++) { int meshId = *meshIdIt; CalCoreMesh *pCoreMesh = m_pCoreModel->getCoreMesh(meshId); int submeshCount= pCoreMesh->getCoreSubmeshCount(); int submeshId; for(submeshId = 0 ;submeshId < submeshCount ; submeshId++) { CalCoreSubmesh *pCoreSubmesh = pCoreMesh->getCoreSubmesh(submeshId); std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pCoreSubmesh->getVectorVertex(); std::vector<CalCoreSubmesh::Face>& vectorFace = pCoreSubmesh->getVectorFace(); // unused. //std::vector< std::vector<CalCoreSubmesh::TextureCoordinate> >& vectorTex = pCoreSubmesh->getVectorVectorTextureCoordinate(); CalHardwareMesh hardwareMesh; hardwareMesh.meshId = meshId; hardwareMesh.submeshId = submeshId; hardwareMesh.baseVertexIndex=vertexCount; hardwareMesh.startIndex=faceIndexCount; hardwareMesh.m_vectorBonesIndices.clear(); hardwareMesh.vertexCount=0; hardwareMesh.faceCount=0; int startIndex=hardwareMesh.startIndex; int faceId; for( faceId =0 ;faceId<pCoreSubmesh->getFaceCount();faceId++) { if(canAddFace(hardwareMesh,vectorFace[faceId],vectorVertex,maxBonesPerMesh)) { m_pIndexBuffer[startIndex+hardwareMesh.faceCount*3]= addVertex(hardwareMesh,vectorFace[faceId].vertexId[0],pCoreSubmesh,maxBonesPerMesh); m_pIndexBuffer[startIndex+hardwareMesh.faceCount*3+1]= addVertex(hardwareMesh,vectorFace[faceId].vertexId[1],pCoreSubmesh,maxBonesPerMesh); m_pIndexBuffer[startIndex+hardwareMesh.faceCount*3+2]= addVertex(hardwareMesh,vectorFace[faceId].vertexId[2],pCoreSubmesh,maxBonesPerMesh); hardwareMesh.faceCount++; } else { vertexCount+=hardwareMesh.vertexCount; faceIndexCount+=hardwareMesh.faceCount*3; hardwareMesh.pCoreMaterial= m_pCoreModel->getCoreMaterial(pCoreSubmesh->getCoreMaterialThreadId()); m_vectorHardwareMesh.push_back(hardwareMesh); hardwareMesh.baseVertexIndex=vertexCount; hardwareMesh.startIndex=faceIndexCount; hardwareMesh.m_vectorBonesIndices.clear(); hardwareMesh.vertexCount=0; hardwareMesh.faceCount=0; startIndex=hardwareMesh.startIndex; m_pIndexBuffer[startIndex+hardwareMesh.faceCount*3]= addVertex(hardwareMesh,vectorFace[faceId].vertexId[0],pCoreSubmesh,maxBonesPerMesh); m_pIndexBuffer[startIndex+hardwareMesh.faceCount*3+1]= addVertex(hardwareMesh,vectorFace[faceId].vertexId[1],pCoreSubmesh,maxBonesPerMesh); m_pIndexBuffer[startIndex+hardwareMesh.faceCount*3+2]= addVertex(hardwareMesh,vectorFace[faceId].vertexId[2],pCoreSubmesh,maxBonesPerMesh); hardwareMesh.faceCount++; } } vertexCount+=hardwareMesh.vertexCount; faceIndexCount+=hardwareMesh.faceCount*3; hardwareMesh.pCoreMaterial= m_pCoreModel->getCoreMaterial(pCoreSubmesh->getCoreMaterialThreadId()); m_vectorHardwareMesh.push_back(hardwareMesh); } } m_vectorVertexIndiceUsed.clear(); m_totalFaceCount=0; m_totalVertexCount=0; for(size_t hardwareMeshId = 0; hardwareMeshId < m_vectorHardwareMesh.size(); hardwareMeshId++) { m_totalFaceCount+=m_vectorHardwareMesh[hardwareMeshId].faceCount; m_totalVertexCount+=m_vectorHardwareMesh[hardwareMeshId].vertexCount; } return true; }
void CalCoreBone::calculateBoundingBox(CalCoreModel * pCoreModel) { int boneId = m_pCoreSkeleton->getCoreBoneId(m_strName); bool bBoundsComputed=false; int planeId; CalQuaternion rot; rot=m_rotationBoneSpace; rot.invert(); CalVector dir = CalVector(1.0f,0.0f,0.0f); dir*=rot; m_boundingBox.plane[0].setNormal(dir); dir = CalVector(-1.0f,0.0f,0.0f); dir*=rot; m_boundingBox.plane[1].setNormal(dir); dir = CalVector(0.0f,1.0f,0.0f); dir*=rot; m_boundingBox.plane[2].setNormal(dir); dir = CalVector(0.0f,-1.0f,0.0f); dir*=rot; m_boundingBox.plane[3].setNormal(dir); dir = CalVector(0.0f,0.0f,1.0f); dir*=rot; m_boundingBox.plane[4].setNormal(dir); dir = CalVector(0.0f,0.0f,-1.0f); dir*=rot; m_boundingBox.plane[5].setNormal(dir); int meshId; for(meshId=0; meshId < pCoreModel->getCoreMeshCount(); ++meshId) { CalCoreMesh * pCoreMesh = pCoreModel->getCoreMesh(meshId); int submeshId; for(submeshId=0;submeshId<pCoreMesh->getCoreSubmeshCount();submeshId++) { CalCoreSubmesh *pCoreSubmesh = pCoreMesh->getCoreSubmesh(submeshId); if(pCoreSubmesh->getSpringCount()==0) { std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pCoreSubmesh->getVectorVertex(); for(size_t vertexId=0;vertexId <vectorVertex.size(); ++vertexId) { for(size_t influenceId=0;influenceId<vectorVertex[vertexId].vectorInfluence.size();++influenceId) { if(vectorVertex[vertexId].vectorInfluence[influenceId].boneId == boneId && vectorVertex[vertexId].vectorInfluence[influenceId].weight > 0.5f) { for(planeId = 0; planeId < 6; ++planeId) { if(m_boundingBox.plane[planeId].eval(vectorVertex[vertexId].position) < 0.0f) { m_boundingBox.plane[planeId].setPosition(vectorVertex[vertexId].position); m_boundingPosition[planeId]=vectorVertex[vertexId].position; bBoundsComputed=true; } } } } } } } } // To handle bones with no vertices assigned if(!bBoundsComputed) { for(planeId = 0; planeId < 6; ++planeId) { m_boundingBox.plane[planeId].setPosition(m_translation); m_boundingPosition[planeId] = m_translation; } } m_boundingBoxPrecomputed = true; }
bool CExporter::ExportMesh(const std::string& strFilename) { // check if a valid interface is set if(m_pInterface == 0) { SetLastError("Invalid handle.", __FILE__, __LINE__); return false; } // build a mesh candidate CMeshCandidate meshCandidate; // build a skeleton candidate CSkeletonCandidate skeletonCandidate; // show export wizard sheet CMeshExportSheet sheet("Cal3D Mesh Export", m_pInterface->GetMainWnd()); sheet.SetSkeletonCandidate(&skeletonCandidate); sheet.SetMeshCandidate(&meshCandidate); sheet.SetWizardMode(); if(sheet.DoModal() != ID_WIZFINISH) return true; // create the core mesh instance CalCoreMeshPtr coreMesh = new CalCoreMesh; // get the submesh candidate vector std::vector<CSubmeshCandidate *>& vectorSubmeshCandidate = meshCandidate.GetVectorSubmeshCandidate(); // start the progress info m_pInterface->StartProgressInfo("Exporting to mesh file..."); for(size_t submeshCandidateId = 0; submeshCandidateId < vectorSubmeshCandidate.size(); submeshCandidateId++) { // update the progress info m_pInterface->SetProgressInfo(int(100.0f * (float)submeshCandidateId / (float)vectorSubmeshCandidate.size())); // get the submesh candidate CSubmeshCandidate *pSubmeshCandidate = vectorSubmeshCandidate[submeshCandidateId]; // get the face vector std::vector<CSubmeshCandidate::Face>& vectorFace = pSubmeshCandidate->GetVectorFace(); // check if the submesh actually contains faces if(vectorFace.size() > 0) { // allocate new core submesh instance CalCoreSubmesh *pCoreSubmesh = new CalCoreSubmesh(); if(pCoreSubmesh == 0) { SetLastError("Memory allocation failed.", __FILE__, __LINE__); m_pInterface->StopProgressInfo(); return false; } // set the core material id pCoreSubmesh->setCoreMaterialThreadId(pSubmeshCandidate->GetMaterialThreadId()); // get the vertex candidate vector std::vector<CVertexCandidate *>& vectorVertexCandidate = pSubmeshCandidate->GetVectorVertexCandidate(); // get the spring vector std::vector<CSubmeshCandidate::Spring>& vectorSpring = pSubmeshCandidate->GetVectorSpring(); // reserve memory for all the submesh data if(!pCoreSubmesh->reserve(vectorVertexCandidate.size(), pSubmeshCandidate->GetMapCount(), vectorFace.size(), vectorSpring.size())) { SetLastError(CalError::getLastErrorText(), __FILE__, __LINE__); delete pCoreSubmesh; m_pInterface->StopProgressInfo(); return false; } for(size_t vertexCandidateId = 0; vertexCandidateId < vectorVertexCandidate.size(); vertexCandidateId++) { // get the vertex candidate CVertexCandidate *pVertexCandidate = vectorVertexCandidate[vertexCandidateId]; CalCoreSubmesh::Vertex vertex; pVertexCandidate->GetPosition(vertex.position); pVertexCandidate->GetNormal(vertex.normal); vertex.collapseId = pVertexCandidate->GetCollapseId(); vertex.faceCollapseCount = pVertexCandidate->GetFaceCollapseCount(); // get the texture coordinate vector std::vector<CVertexCandidate::TextureCoordinate>& vectorTextureCoordinate = pVertexCandidate->GetVectorTextureCoordinate(); // set all texture coordinates for(size_t textureCoordinateId = 0; textureCoordinateId < vectorTextureCoordinate.size(); textureCoordinateId++) { CalCoreSubmesh::TextureCoordinate textureCoordinate; textureCoordinate.u = vectorTextureCoordinate[textureCoordinateId].u; textureCoordinate.v = vectorTextureCoordinate[textureCoordinateId].v; // set texture coordinate pCoreSubmesh->setTextureCoordinate(pVertexCandidate->GetLodId(), textureCoordinateId, textureCoordinate); } // get the influence vector std::vector<CVertexCandidate::Influence>& vectorInfluence = pVertexCandidate->GetVectorInfluence(); // reserve memory for the influences in the vertex vertex.vectorInfluence.reserve(vectorInfluence.size()); vertex.vectorInfluence.resize(vectorInfluence.size()); // set all influences for(size_t influenceId = 0; influenceId < vectorInfluence.size(); influenceId++) { vertex.vectorInfluence[influenceId].boneId = vectorInfluence[influenceId].boneId; vertex.vectorInfluence[influenceId].weight = vectorInfluence[influenceId].weight; } // set vertex in the core submesh instance pCoreSubmesh->setVertex(pVertexCandidate->GetLodId(), vertex); // set the physical property if there is a spring system if(vectorSpring.size() > 0) { // get the physical property vector CVertexCandidate::PhysicalProperty physicalPropertyCandidate; pVertexCandidate->GetPhysicalProperty(physicalPropertyCandidate); CalCoreSubmesh::PhysicalProperty physicalProperty; physicalProperty.weight = physicalPropertyCandidate.weight; // set the physical property in the core submesh instance pCoreSubmesh->setPhysicalProperty(vertexCandidateId, physicalProperty); } } for(size_t faceId = 0; faceId < vectorFace.size(); faceId++) { CalCoreSubmesh::Face face; // set the vertex ids face.vertexId[0] = vectorFace[faceId].vertexLodId[0]; face.vertexId[1] = vectorFace[faceId].vertexLodId[1]; face.vertexId[2] = vectorFace[faceId].vertexLodId[2]; // set face in the core submesh instance pCoreSubmesh->setFace(vectorFace[faceId].lodId, face); } for(size_t springId = 0; springId < vectorSpring.size(); springId++) { CalCoreSubmesh::Spring spring; // set the vertex ids spring.vertexId[0] = vectorSpring[springId].vertexId[0]; spring.vertexId[1] = vectorSpring[springId].vertexId[1]; spring.springCoefficient = vectorSpring[springId].springCoefficient; spring.idleLength = vectorSpring[springId].idleLength; // set face in the core submesh instance pCoreSubmesh->setSpring(springId, spring); } // set the LOD step count pCoreSubmesh->setLodCount(pSubmeshCandidate->GetLodCount()); // add the core submesh to the core mesh instance coreMesh->addCoreSubmesh(pCoreSubmesh); } } // stop the progress info m_pInterface->StopProgressInfo(); // save core mesh to the file if(!CalSaver::saveCoreMesh(strFilename, coreMesh.get())) { SetLastError(CalError::getLastErrorText(), __FILE__, __LINE__); return false; } return true; }
void CalCoreSkeleton::calculateBoundingBoxes(CalCoreModel *pCoreModel) { size_t boneId; // First, find out whether all the bounding boxes have already been precomputed. // If so, we can bail out early. bool alreadyComputed = true; for(boneId=0;boneId<m_vectorCoreBone.size();++boneId) { if (! m_vectorCoreBone[boneId]->isBoundingBoxPrecomputed()) { alreadyComputed = false; break; } } if (alreadyComputed) { return; } // Initialize all bounding boxes empty. for(boneId=0;boneId<m_vectorCoreBone.size();++boneId) { m_vectorCoreBone[boneId]->initBoundingBox(); } // Loop over all vertices updating bounding boxes. for(int meshId=0; meshId < pCoreModel->getCoreMeshCount(); ++meshId) { CalCoreMesh * pCoreMesh = pCoreModel->getCoreMesh(meshId); for(int submeshId=0;submeshId<pCoreMesh->getCoreSubmeshCount();submeshId++) { CalCoreSubmesh *pCoreSubmesh = pCoreMesh->getCoreSubmesh(submeshId); if(pCoreSubmesh->getSpringCount()==0) { std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pCoreSubmesh->getVectorVertex(); for(size_t vertexId=0;vertexId <vectorVertex.size(); ++vertexId) { for(size_t influenceId=0; influenceId < vectorVertex[vertexId].vectorInfluence.size(); ++influenceId) { if (vectorVertex[vertexId].vectorInfluence[influenceId].weight > 0.5f) { boneId = vectorVertex[vertexId].vectorInfluence[influenceId].boneId; m_vectorCoreBone[boneId]->updateBoundingBox( vectorVertex[vertexId].position ); break; // there can be at most one bone with majority influence } } } } } } // Mark bounding boxes as computed. for(boneId=0;boneId<m_vectorCoreBone.size();++boneId) { m_vectorCoreBone[boneId]->setBoundingBoxPrecomputed( true ); } }