//----------------------------------------------------------------------- void Entity::buildSubEntityList(Mesh* mesh, SubEntityList* sublist) { // Create SubEntities int i, numSubMeshes; SubMesh* subMesh; SubEntity* subEnt; numSubMeshes = mesh->getNumSubMeshes(); for (i = 0; i < numSubMeshes; ++i) { subMesh = mesh->getSubMesh(i); subEnt = new SubEntity(); subEnt->mParentEntity = this; subEnt->mSubMesh = subMesh; if (subMesh->isMatInitialised()) subEnt->setMaterialName(subMesh->getMaterialName()); sublist->push_back(subEnt); } }
void MeshSerializerTests::assertMeshClone(Mesh* a, Mesh* b, MeshVersion version /*= MESH_VERSION_LATEST*/) { // TODO: Compare skeleton // TODO: Compare animations // TODO: Compare pose animations // CPPUNIT_ASSERT(a->getGroup() == b->getGroup()); // CPPUNIT_ASSERT(a->getName() == b->getName()); #ifndef OGRE_TEST_XMLSERIALIZER // XML serializer fails on these! CPPUNIT_ASSERT(isEqual(a->getBoundingSphereRadius(), b->getBoundingSphereRadius())); CPPUNIT_ASSERT(isEqual(a->getBounds().getMinimum(), b->getBounds().getMinimum())); CPPUNIT_ASSERT(isEqual(a->getBounds().getMaximum(), b->getBounds().getMaximum())); #else StringStream str; Real val1 = a->getBoundingSphereRadius(); Real val2 = b->getBoundingSphereRadius(); Real diff = (val1 > val2) ? (val1 / val2) : (val2 / val1); if (diff > 1.1) { str << "bound sphere diff: " << diff << std::endl; } val1 = a->getBounds().getMinimum().length(); val2 = b->getBounds().getMinimum().length(); diff = (val1 > val2) ? (val1 / val2) : (val2 / val1); if (diff > 1.1) { str << "bound min diff: " << diff << std::endl; } val1 = a->getBounds().getMaximum().length(); val2 = b->getBounds().getMaximum().length(); diff = (val1 > val2) ? (val1 / val2) : (val2 / val1); if (diff > 1.1) { str << "bound max diff: " << diff << std::endl; } if (!str.str().empty()) { StringStream str2; str2 << std::endl << "Mesh name: " << b->getName() << std::endl; str2 << str.str(); std::cout << str2.str(); // OutputDebugStringA(str2.str().c_str()); } #endif /* ifndef OGRE_TEST_XMLSERIALIZER */ // AutobuildEdgeLists is not saved to mesh file. You need to set it after loading a mesh! // CPPUNIT_ASSERT(a->getAutoBuildEdgeLists() == b->getAutoBuildEdgeLists()); CPPUNIT_ASSERT(isHashMapClone(a->getSubMeshNameMap(), b->getSubMeshNameMap())); assertVertexDataClone(a->sharedVertexData, b->sharedVertexData); CPPUNIT_ASSERT(a->getCreator() == b->getCreator()); CPPUNIT_ASSERT(a->getIndexBufferUsage() == b->getIndexBufferUsage()); CPPUNIT_ASSERT(a->getSharedVertexDataAnimationIncludesNormals() == b->getSharedVertexDataAnimationIncludesNormals()); CPPUNIT_ASSERT(a->getSharedVertexDataAnimationType() == b->getSharedVertexDataAnimationType()); CPPUNIT_ASSERT(a->getVertexBufferUsage() == b->getVertexBufferUsage()); CPPUNIT_ASSERT(a->hasVertexAnimation() == b->hasVertexAnimation()); #ifndef OGRE_TEST_XMLSERIALIZER CPPUNIT_ASSERT(a->isEdgeListBuilt() == b->isEdgeListBuilt()); // <== OgreXMLSerializer is doing post processing to generate edgelists! #endif // !OGRE_TEST_XMLSERIALIZER if ((a->getNumLodLevels() > 1 || b->getNumLodLevels() > 1) && ((version < MESH_VERSION_1_8 || (!isLodMixed(a) && !isLodMixed(b))) && // mixed lod only supported in v1.10+ (version < MESH_VERSION_1_4 || (a->getLodStrategy() == DistanceLodStrategy::getSingletonPtr() && b->getLodStrategy() == DistanceLodStrategy::getSingletonPtr())))) { // Lod Strategy only supported in v1.41+ CPPUNIT_ASSERT(a->getNumLodLevels() == b->getNumLodLevels()); CPPUNIT_ASSERT(a->hasManualLodLevel() == b->hasManualLodLevel()); CPPUNIT_ASSERT(a->getLodStrategy() == b->getLodStrategy()); int numLods = a->getNumLodLevels(); for (int i = 0; i < numLods; i++) { if (version != MESH_VERSION_1_0 && a->getAutoBuildEdgeLists() == b->getAutoBuildEdgeLists()) { assertEdgeDataClone(a->getEdgeList(i), b->getEdgeList(i)); } else if (a->getLodLevel(i).edgeData != NULL && b->getLodLevel(i).edgeData != NULL) { assertEdgeDataClone(a->getLodLevel(i).edgeData, b->getLodLevel(i).edgeData); } assertLodUsageClone(a->getLodLevel(i), b->getLodLevel(i)); } } CPPUNIT_ASSERT(a->getNumSubMeshes() == b->getNumSubMeshes()); int numLods = std::min(a->getNumLodLevels(), b->getNumLodLevels()); int numSubmeshes = a->getNumSubMeshes(); for (int i = 0; i < numSubmeshes; i++) { SubMesh* aSubmesh = a->getSubMesh(i); SubMesh* bSubmesh = b->getSubMesh(i); CPPUNIT_ASSERT(aSubmesh->getMaterialName() == bSubmesh->getMaterialName()); CPPUNIT_ASSERT(aSubmesh->isMatInitialised() == bSubmesh->isMatInitialised()); CPPUNIT_ASSERT(aSubmesh->useSharedVertices == bSubmesh->useSharedVertices); CPPUNIT_ASSERT(aSubmesh->getVertexAnimationIncludesNormals() == bSubmesh->getVertexAnimationIncludesNormals()); CPPUNIT_ASSERT(aSubmesh->getVertexAnimationType() == bSubmesh->getVertexAnimationType()); CPPUNIT_ASSERT(aSubmesh->getTextureAliasCount() == bSubmesh->getTextureAliasCount()); CPPUNIT_ASSERT(isContainerClone(aSubmesh->blendIndexToBoneIndexMap, bSubmesh->blendIndexToBoneIndexMap)); // TODO: Compare getBoneAssignments and getTextureAliases for (int n = 0; n < numLods; n++) { if (a->_isManualLodLevel(n)) { continue; } RenderOperation aop, bop; aSubmesh->_getRenderOperation(aop, n); bSubmesh->_getRenderOperation(bop, n); assertIndexDataClone(aop.indexData, bop.indexData); assertVertexDataClone(aop.vertexData, bop.vertexData); CPPUNIT_ASSERT(aop.operationType == bop.operationType); CPPUNIT_ASSERT(aop.useIndexes == bop.useIndexes); } } }
MeshPtr MeshMergeTool::merge(const Ogre::String& name, const Ogre::String& resourceGroupName) { print("Baking: New Mesh started", V_HIGH); MeshPtr mp = MeshManager::getSingleton().createManual(name, resourceGroupName); if (!mBaseSkeleton.isNull()) { mp->setSkeletonName(mBaseSkeleton->getName()); } AxisAlignedBox totalBounds = AxisAlignedBox(); for (std::vector<Ogre::MeshPtr>::iterator it = mMeshes.begin(); it != mMeshes.end(); ++it) { print("Baking: adding submeshes for " + (*it)->getName(), V_HIGH); // insert all submeshes for (Ogre::ushort sid = 0; sid < (*it)->getNumSubMeshes(); ++sid) { SubMesh* sub = (*it)->getSubMesh(sid); const String name = findSubmeshName((*it), sid); // create submesh with correct name SubMesh* newsub; if (name.length() == 0) { newsub = mp->createSubMesh(); } else { /// @todo check if a submesh with this name has been created before newsub = mp->createSubMesh(name); } newsub->useSharedVertices = sub->useSharedVertices; // add index newsub->indexData = sub->indexData->clone(); // add geometry if (!newsub->useSharedVertices) { newsub->vertexData = sub->vertexData->clone(); if (!mBaseSkeleton.isNull()) { // build bone assignments SubMesh::BoneAssignmentIterator bit = sub->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); newsub->addBoneAssignment(vba); } } } newsub->setMaterialName(sub->getMaterialName()); // Add vertex animations for this submesh Animation *anim = 0; for (unsigned short i = 0; i < (*it)->getNumAnimations(); ++i) { anim = (*it)->getAnimation(i); // get or create the animation for the new mesh Animation *newanim; if (mp->hasAnimation(anim->getName())) { newanim = mp->getAnimation(anim->getName()); } else { newanim = mp->createAnimation(anim->getName(), anim->getLength()); } print("Baking: adding vertex animation " + anim->getName() + " for " + (*it)->getName(), V_HIGH); Animation::VertexTrackIterator vti=anim->getVertexTrackIterator(); while (vti.hasMoreElements()) { VertexAnimationTrack *vt = vti.getNext(); // handle=0 targets the main mesh, handle i (where i>0) targets submesh i-1. // In this case there are only submeshes so index 0 will not be used. unsigned short handle = mp->getNumSubMeshes(); VertexAnimationTrack* newvt = newanim->createVertexTrack( handle, vt->getAssociatedVertexData()->clone(), vt->getAnimationType()); for (int keyFrameIndex = 0; keyFrameIndex < vt->getNumKeyFrames(); ++keyFrameIndex) { switch (vt->getAnimationType()) { case VAT_MORPH: { // copy the keyframe vertex buffer VertexMorphKeyFrame *kf = vt->getVertexMorphKeyFrame(keyFrameIndex); VertexMorphKeyFrame *newkf = newvt->createVertexMorphKeyFrame(kf->getTime()); // This creates a ref to the buffer in the original model // so don't delete it until the export is completed. newkf->setVertexBuffer(kf->getVertexBuffer()); break; } case VAT_POSE: { /// @todo implement pose amination merge break; } case VAT_NONE: default: { break; } } } } } print("Baking: adding submesh '" + name + "' with material " + sub->getMaterialName(), V_HIGH); } // sharedvertices if ((*it)->sharedVertexData) { /// @todo merge with existing sharedVertexData if (!mp->sharedVertexData) { mp->sharedVertexData = (*it)->sharedVertexData->clone(); } if (!mBaseSkeleton.isNull()) { Mesh::BoneAssignmentIterator bit = (*it)->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); mp->addBoneAssignment(vba); } } } print("Baking: adding bounds for " + (*it)->getName(), V_HIGH); // add bounds totalBounds.merge((*it)->getBounds()); } mp->_setBounds(totalBounds); /// @todo merge submeshes with same material /// @todo add parameters mp->buildEdgeList(); print("Baking: Finished", V_HIGH); reset(); return mp; }
MeshPtr MergeMesh::bake() { log( "Baking: New Mesh started" ); MeshPtr mp = MeshManager::getSingleton(). createManual( "mergedMesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); mp->setSkeletonName( m_BaseSkeleton->getName() ); AxisAlignedBox totalBounds = AxisAlignedBox(); for( std::vector< Ogre::MeshPtr >::iterator it = m_Meshes.begin(); it != m_Meshes.end(); ++it ) { log( "Baking: adding submeshes for " + (*it)->getName() ); // insert all submeshes for( Ogre::ushort sid = 0; sid < (*it)->getNumSubMeshes(); ++sid ) { SubMesh* sub = (*it)->getSubMesh( sid ); const String name = findSubmeshName( (*it), sid ); // create submesh with correct name SubMesh* newsub; if( name.length() == 0 ) newsub = mp->createSubMesh( ); else /// @todo check if a submesh with this name has been created before newsub = mp->createSubMesh( name ); newsub->useSharedVertices = sub->useSharedVertices; // add index newsub->indexData = sub->indexData->clone(); // add geometry if( !newsub->useSharedVertices ) { newsub->vertexData = sub->vertexData->clone(); // build bone assignments SubMesh::BoneAssignmentIterator bit = sub->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); newsub->addBoneAssignment(vba); } } newsub->setMaterialName( sub->getMaterialName() ); log("Baking: adding submesh '" + name + "' with material " + sub->getMaterialName()); } // sharedvertices if ((*it)->sharedVertexData) { /// @todo merge with existing sharedVertexData if (!mp->sharedVertexData) { mp->sharedVertexData = (*it)->sharedVertexData->clone(); } Mesh::BoneAssignmentIterator bit = (*it)->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); mp->addBoneAssignment(vba); } } log("Baking: adding bounds for " + (*it)->getName()); // add bounds totalBounds.merge((*it)->getBounds()); } mp->_setBounds( totalBounds ); /// @todo merge submeshes with same material /// @todo add parameters mp->buildEdgeList(); log( "Baking: Finished" ); return mp; }
void MeshObject::loadMesh() { try { Ogre::String resourceGroup = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME; mesh = static_cast<Ogre::MeshPtr>(Ogre::MeshManager::getSingleton().create(meshName, resourceGroup)); if(backgroundLoading) { mesh->setBackgroundLoaded(true); mesh->addListener(this); ticket = Ogre::ResourceBackgroundQueue::getSingleton().load( Ogre::MeshManager::getSingletonPtr()->getResourceType(), mesh->getName(), resourceGroup, false, 0, 0, 0); // try to load its textures in the background for(int i=0; i<mesh->getNumSubMeshes(); i++) { SubMesh *sm = mesh->getSubMesh(i); String materialName = sm->getMaterialName(); Ogre::MaterialPtr mat = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName(materialName)); //, resourceGroup)); if(mat.isNull()) continue; for(int tn=0; tn<mat->getNumTechniques(); tn++) { Technique *t = mat->getTechnique(tn); for(int pn=0; pn<t->getNumPasses(); pn++) { Pass *p = t->getPass(pn); for(int tun=0; tun<p->getNumTextureUnitStates(); tun++) { TextureUnitState *tu = p->getTextureUnitState(tun); String textureName = tu->getTextureName(); // now add this texture to the background loading queue Ogre::TexturePtr tex = static_cast<Ogre::TexturePtr>(Ogre::TextureManager::getSingleton().create(textureName, resourceGroup)); tex->setBackgroundLoaded(true); tex->addListener(this); ticket = Ogre::ResourceBackgroundQueue::getSingleton().load( Ogre::TextureManager::getSingletonPtr()->getResourceType(), tex->getName(), resourceGroup, false, 0, 0, 0); } } } } } if(!backgroundLoading) postProcess(); } catch (Ogre::Exception* e) { LOG("exception while loading mesh: " + e->getFullDescription()); } }