void XMLToBinary(XmlOptions opts) { // Read root element and decide from there what type String response; TiXmlDocument* doc = new TiXmlDocument(opts.source); // Some double-parsing here but never mind if (!doc->LoadFile()) { cout << "Unable to open file " << opts.source << " - fatal error." << endl; delete doc; exit (1); } TiXmlElement* root = doc->RootElement(); if (!stricmp(root->Value(), "mesh")) { delete doc; MeshPtr newMesh = MeshManager::getSingleton().createManual("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); VertexElementType colourElementType; if (opts.d3d) colourElementType = VET_COLOUR_ARGB; else colourElementType = VET_COLOUR_ABGR; xmlMeshSerializer->importMesh(opts.source, colourElementType, newMesh.getPointer()); // Re-jig the buffers? // Make sure animation types are up to date first newMesh->_determineAnimationTypes(); if (opts.reorganiseBuffers) { logMgr->logMessage("Reorganising vertex buffers to automatic layout..."); // Shared geometry if (newMesh->sharedVertexData) { // Automatic VertexDeclaration* newDcl = newMesh->sharedVertexData->vertexDeclaration->getAutoOrganisedDeclaration( newMesh->hasSkeleton(), newMesh->hasVertexAnimation(), newMesh->getSharedVertexDataAnimationIncludesNormals()); if (*newDcl != *(newMesh->sharedVertexData->vertexDeclaration)) { // Usages don't matter here since we're onlly exporting BufferUsageList bufferUsages; for (size_t u = 0; u <= newDcl->getMaxSource(); ++u) bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY); newMesh->sharedVertexData->reorganiseBuffers(newDcl, bufferUsages); } } // Dedicated geometry Mesh::SubMeshIterator smIt = newMesh->getSubMeshIterator(); while (smIt.hasMoreElements()) { SubMesh* sm = smIt.getNext(); if (!sm->useSharedVertices) { const bool hasVertexAnim = sm->getVertexAnimationType() != Ogre::VAT_NONE; // Automatic VertexDeclaration* newDcl = sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration( newMesh->hasSkeleton(), hasVertexAnim, sm->getVertexAnimationIncludesNormals()); if (*newDcl != *(sm->vertexData->vertexDeclaration)) { // Usages don't matter here since we're onlly exporting BufferUsageList bufferUsages; for (size_t u = 0; u <= newDcl->getMaxSource(); ++u) bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY); sm->vertexData->reorganiseBuffers(newDcl, bufferUsages); } } } } if( opts.mergeTexcoordResult != opts.mergeTexcoordToDestroy ) { newMesh->mergeAdjacentTexcoords( uint16(opts.mergeTexcoordResult), uint16(opts.mergeTexcoordToDestroy) ); } if (opts.nuextremityPoints) { Mesh::SubMeshIterator smIt = newMesh->getSubMeshIterator(); while (smIt.hasMoreElements()) { SubMesh* sm = smIt.getNext(); sm->generateExtremes (opts.nuextremityPoints); } } meshSerializer->exportMesh(newMesh.getPointer(), opts.dest, opts.endian); // Clean up the conversion mesh MeshManager::getSingleton().remove("conversion"); } else if (!stricmp(root->Value(), "skeleton")) { delete doc; SkeletonPtr newSkel = SkeletonManager::getSingleton().create("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); xmlSkeletonSerializer->importSkeleton(opts.source, newSkel.getPointer()); if (opts.optimiseAnimations) { newSkel->optimiseAllAnimations(); } skeletonSerializer->exportSkeleton(newSkel.getPointer(), opts.dest, SKELETON_VERSION_LATEST, opts.endian); // Clean up the conversion skeleton SkeletonManager::getSingleton().remove("conversion"); } else { delete doc; } }
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); } } }
void XMLToBinary(XmlOptions opts) { // Read root element and decide from there what type String response; TiXmlDocument* doc = new TiXmlDocument(opts.source); // Some double-parsing here but never mind if (!doc->LoadFile()) { cout << "Unable to open file " << opts.source << " - fatal error." << endl; delete doc; exit (1); } TiXmlElement* root = doc->RootElement(); if (!stricmp(root->Value(), "mesh")) { delete doc; MeshPtr newMesh = MeshManager::getSingleton().createManual("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); VertexElementType colourElementType; if (opts.d3d) colourElementType = VET_COLOUR_ARGB; else colourElementType = VET_COLOUR_ABGR; xmlMeshSerializer->importMesh(opts.source, colourElementType, newMesh.getPointer()); // Re-jig the buffers? // Make sure animation types are up to date first newMesh->_determineAnimationTypes(); if (opts.reorganiseBuffers) { logMgr->logMessage("Reorganising vertex buffers to automatic layout.."); // Shared geometry if (newMesh->sharedVertexData) { // Automatic VertexDeclaration* newDcl = newMesh->sharedVertexData->vertexDeclaration->getAutoOrganisedDeclaration( newMesh->hasSkeleton(), newMesh->hasVertexAnimation(), newMesh->getSharedVertexDataAnimationIncludesNormals()); if (*newDcl != *(newMesh->sharedVertexData->vertexDeclaration)) { // Usages don't matter here since we're onlly exporting BufferUsageList bufferUsages; for (size_t u = 0; u <= newDcl->getMaxSource(); ++u) bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY); newMesh->sharedVertexData->reorganiseBuffers(newDcl, bufferUsages); } } // Dedicated geometry Mesh::SubMeshIterator smIt = newMesh->getSubMeshIterator(); while (smIt.hasMoreElements()) { SubMesh* sm = smIt.getNext(); if (!sm->useSharedVertices) { // Automatic VertexDeclaration* newDcl = sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration( newMesh->hasSkeleton(), newMesh->hasVertexAnimation(), sm->getVertexAnimationIncludesNormals()); if (*newDcl != *(sm->vertexData->vertexDeclaration)) { // Usages don't matter here since we're onlly exporting BufferUsageList bufferUsages; for (size_t u = 0; u <= newDcl->getMaxSource(); ++u) bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY); sm->vertexData->reorganiseBuffers(newDcl, bufferUsages); } } } } // Prompt for LOD generation? bool genLod = false; bool askLodDtls = false; if (!opts.interactiveMode) // derive from params if in batch mode { askLodDtls = false; if (opts.numLods == 0) { genLod = false; } else { genLod = true; } } else if(opts.numLods == 0) // otherwise only ask if not specified on command line { if (newMesh->getNumLodLevels() > 1) { std::cout << "\nXML already contains level-of detail information.\n" "Do you want to: (u)se it, (r)eplace it, or (d)rop it?"; while (response == "") { cin >> response; StringUtil::toLowerCase(response); if (response == "u") { // Do nothing } else if (response == "d") { newMesh->removeLodLevels(); } else if (response == "r") { genLod = true; askLodDtls = true; } else { std::cout << "Did not understand \"" << response << "\" please try again:" << std::endl; response = ""; } }// while response == "" } else // no existing LOD {