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 ); } } } }
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; }
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 ); } }