#include "BBCColladaMeshSerializer.h" namespace BBC { ColladaMeshSerializer::ColladaMeshSerializer() { } ColladaMeshSerializer::~ColladaMeshSerializer() { } void ColladaMeshSerializer::setEntity(EntityPtr entity) { mEntity = entity; } EntityPtr ColladaMeshSerializer::getEntity() { return mEntity; } void ColladaMeshSerializer::exportMesh(const Ogre::String& fileName, bool mergeSubMeshes = false, bool tangents = false) { Ogre::String outputFileName; outputFileName = BBC::Util::getBaseName(fileName) + ".dae"; mFCDocument = new FCDocument(); mFCDocument->AddVisualScene(); mFCDVisualSceneNodeLibrary = mFCDocument->GetVisualSceneLibrary(); mSceneNode = mFCDocument->GetVisualSceneRoot()->AddChildNode(); //mSceneNode->AddTransform(FCDTransform::SCALE, -1); //mSceneNode->AddTransform(FCDTransform::ROTATION, -1); //mSceneNode->AddTransform(FCDTransform::TRANSLATION, -1); mFCDEntityInstanceList = (const FCDEntityInstanceList&)mSceneNode->GetInstances(); mFCDGeometry = mFCDocument->GetGeometryLibrary()->AddEntity(); mFCDGeometryMesh = mFCDGeometry->CreateMesh(); mFCDGeometryInstance = new FCDGeometryInstance(mFCDocument, mFCDGeometry); mFCDMaterialInstance = new FCDMaterialInstance(mFCDocument, mFCDGeometryInstance); mFCDMaterial = mFCDocument->GetMaterialLibrary()->AddMaterial(); mFCDEffect = mFCDocument->GetMaterialLibrary()->AddEffect(); mFCDMaterial->SetEffect(mFCDEffect); ((FCDMaterialInstanceList)mFCDGeometryInstance->GetMaterialInstanceList()).push_back(mFCDMaterialInstance); mSceneNode->GetInstances().push_back(mFCDGeometryInstance); Ogre::LogManager::getSingleton().logMessage("** Begin Collada Mesh Export **"); // Derive the scene root // Construct mesh BBC::MeshPtr pMesh(new BBC::Mesh(Ogre::MeshManager::getSingleton().createManual(outputFileName, outputFileName).getPointer())); Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(outputFileName, outputFileName); Ogre::LogManager::getSingleton().logMessage("Num.SubEntities:" + Ogre::StringConverter::toString(mEntity->getNumSubEntities())); mEntity->setMesh(pMesh); buildMesh(pMesh, mergeSubMeshes); save(outputFileName); mFloatPositionList.clear(); mFloatNormalList.clear(); mIntPositionIDFaceList.clear(); for (unsigned int iTexCoordSet = 0; iTexCoordSet < mEntity->getSubEntity(0)->getNumTexCoordSets(); iTexCoordSet++) { mFloatTexCoordList[iTexCoordSet].clear(); } mFloatColorList.clear(); delete mFCDocument; Ogre::LogManager::getSingleton().logMessage("** Collada Mesh Export Complete **"); } void ColladaMeshSerializer::exportSubMesh(MeshPtr pMesh, unsigned int iSubEntity) { bool hasVertexColours = mEntity->getSubEntity(iSubEntity)->hasVertexColours(); bool hasNormals = mEntity->getSubEntity(iSubEntity)->hasNormals(); for (unsigned int iVertex = 0; iVertex < mEntity->getSubEntity(iSubEntity)->getNumVertices(); iVertex++) { Ogre::Vector3 position = mEntity->getSubEntity(iSubEntity)->getPosition(iVertex); mFloatPositionList.push_back(position[0]); mFloatPositionList.push_back(position[1]); mFloatPositionList.push_back(position[2]); if (hasNormals) { Ogre::Vector3 normal = mEntity->getSubEntity(iSubEntity)->getNormal(iVertex); mFloatNormalList.push_back(normal[0]); mFloatNormalList.push_back(normal[1]); mFloatNormalList.push_back(normal[2]); } if (hasVertexColours) { Ogre::ColourValue color; //color.setAsARGB(mEntity->getSubEntity(iSubEntity)->getVertexColour(iVertex) & 0xFF); color.setAsARGB(mEntity->getSubEntity(iSubEntity)->getVertexColour(iVertex)); mFloatColorList.push_back(color.r); mFloatColorList.push_back(color.g); mFloatColorList.push_back(color.b); mFloatColorList.push_back(color.a); } for (unsigned int iTexCoordSet = 0; iTexCoordSet < mEntity->getSubEntity(iSubEntity)->getNumTexCoordSets(); iTexCoordSet++) { if (mEntity->getSubEntity(iSubEntity)->getTexCoordDimensions(iTexCoordSet) == 2) { Ogre::Vector3 texcoord0 = mEntity->getSubEntity(iSubEntity)->getTexCoord(iVertex, iTexCoordSet); mFloatTexCoordList[iTexCoordSet].push_back(texcoord0[0]); mFloatTexCoordList[iTexCoordSet].push_back(texcoord0[1]); } if (mEntity->getSubEntity(iSubEntity)->getTexCoordDimensions(iTexCoordSet) == 3) { Ogre::Vector3 texcoord0 = mEntity->getSubEntity(iSubEntity)->getTexCoord(iVertex, iTexCoordSet); mFloatTexCoordList[iTexCoordSet].push_back(texcoord0[0]); mFloatTexCoordList[iTexCoordSet].push_back(texcoord0[1]); mFloatTexCoordList[iTexCoordSet].push_back(texcoord0[2]); } } } if (iSubEntity == 0) { mFCDGeometryVertexSource = mFCDGeometryMesh->AddVertexSource(); } //mFCDGeometryVertexSource = mFCDGeometryMesh->AddSource(); mFCDGeometryVertexSource->SetSourceType(FUDaeGeometryInput::POSITION); if (iSubEntity == (mEntity->getNumSubEntities() - 1)) { mFCDGeometryVertexSource->SetSourceData(mFloatPositionList, 3, 0, 0); } mFCDGeometryPolygons = mFCDGeometryMesh->AddPolygons(); mFCDGeometryPolygonsInput = mFCDGeometryPolygons->FindInput(mFCDGeometryVertexSource); if (hasNormals) { if (iSubEntity == 0) { mFCDGeometryNormalsSource = mFCDGeometryMesh->AddVertexSource(); //mFCDGeometryNormalsSource = mFCDGeometryMesh->AddSource(); } mFCDGeometryNormalsSource->SetSourceType(FUDaeGeometryInput::NORMAL); if (iSubEntity == (mEntity->getNumSubEntities() - 1)) { mFCDGeometryNormalsSource->SetSourceData(mFloatNormalList, 3, 0, 0); } //mFCDGeometryPolygons->AddInput(mFCDGeometryNormalsSource, 0); } for (unsigned int iTexCoordSet = 0; iTexCoordSet < mEntity->getSubEntity(iSubEntity)->getNumTexCoordSets(); iTexCoordSet++) { if (iSubEntity == (mEntity->getNumSubEntities() - 1)) { //mFCDGeometrySource = mFCDGeometryMesh->AddVertexSource(); mFCDGeometryTexCoordSource = mFCDGeometryMesh->AddSource(); mFCDGeometryTexCoordSource->SetSourceType(FUDaeGeometryInput::TEXCOORD); mFCDGeometryTexCoordSource->SetSourceData(mFloatTexCoordList[iTexCoordSet], 2, 0, 0); mFCDGeometryPolygons->AddInput(mFCDGeometryTexCoordSource, 0); } } if (hasVertexColours) { if (iSubEntity == (mEntity->getNumSubEntities() - 1)) { //mFCDGeometrySource = mFCDGeometryMesh->AddVertexSource(); mFCDGeometryColorSource = mFCDGeometryMesh->AddSource(); mFCDGeometryColorSource->SetSourceType(FUDaeGeometryInput::COLOR); mFCDGeometryColorSource->SetSourceData(mFloatColorList, 4, 0, 0); mFCDGeometryPolygons->AddInput(mFCDGeometryColorSource, 0); } } iCount = 0; iSubEntityNextFirstIDFace = 0; for (unsigned int iFace = 0; iFace < mEntity->getSubEntity(iSubEntity)->getNumFaces(); iFace++) { Ogre::Vector3 positionIDFace; positionIDFace = mEntity->getSubEntity(iSubEntity)->getFaceVerticesIDs(iFace); mFCDGeometryPolygons->AddFace(3); mFCDGeometryPolygonsInput->indices[iCount] = iSubEntityFirstIDFace + positionIDFace[0]; mFCDGeometryPolygonsInput->indices[iCount+1] = iSubEntityFirstIDFace + positionIDFace[1]; mFCDGeometryPolygonsInput->indices[iCount+2] = iSubEntityFirstIDFace + positionIDFace[2]; if (positionIDFace[0] > iSubEntityNextFirstIDFace) { iSubEntityNextFirstIDFace = positionIDFace[0] + 1; } if (positionIDFace[1] > iSubEntityNextFirstIDFace) { iSubEntityNextFirstIDFace = positionIDFace[1] + 1; } if (positionIDFace[2] > iSubEntityNextFirstIDFace) { iSubEntityNextFirstIDFace = positionIDFace[2] + 1; } iCount = iCount + 3; } iSubEntityLastIDFace = iSubEntityFirstIDFace + (iSubEntityNextFirstIDFace - 1); iSubEntityFirstIDFace = iSubEntityLastIDFace + 1; } void ColladaMeshSerializer::save(Ogre::String filename) { //mFCDocument->WriteToFile(fstring("test.dae")); // Create a new xml root node from this COLLADA document xmlNode* rootNode = FUXmlWriter::CreateNode(DAE_COLLADA_ELEMENT); FUStatus status; status = mFCDocument->WriteDocumentToXML(rootNode); if (status.IsSuccessful()) { // Create the XML document and write it out to the given filename xmlDoc* daeDocument = xmlNewDoc(NULL); // NULL implies version 1.0 xmlDocSetRootElement(daeDocument, rootNode); intptr_t bytesWritten = xmlSaveFormatFileEnc(filename.c_str(), daeDocument, "utf-8", 1); if (bytesWritten < 0) { //status.Fail(FS("Unable to write COLLADA document to file '") + filename + FS("'. Verify that the folder exists and the file is writable."), rootNode->line); } else if (status.IsSuccessful()) { //status.AppendString(FC("COLLADA document written successfully.")); } xmlFreeDoc(daeDocument); } else { xmlFreeNode(rootNode); } // Clean-up xmlCleanupParser(); } void ColladaMeshSerializer::exportSubMeshes(MeshPtr pMesh) { iCount = 0; iSubEntityFirstIDFace = 0; iSubEntityNextFirstIDFace = 0; iSubEntityLastIDFace = 0; for (unsigned int iSubEntity = 0; iSubEntity < mEntity->getNumSubEntities(); iSubEntity++) { exportSubMesh(pMesh, iSubEntity); } } void ColladaMeshSerializer::buildMesh(MeshPtr pMesh, bool mergeSubmeshes) { if (!mergeSubmeshes) { exportSubMeshes(pMesh); } // TODO if (mergeSubmeshes) { } } }