/** * This source file is part of OgreColladaPlugin * an addon for OGRE (Object-oriented Graphics Rendering Engine) * For the latest info, see http://www.ogre3d.org/ * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA, or go to * http://www.gnu.org/copyleft/lesser.txt. * * @authors Philipp Hartl, Jeff Doyle (nfz) * @see README */ #include "OgreResourceGroupManager.h" #include "OgreColladaDocument.h" #include "OgreColladaGeometry.h" #include "OgreColladaLibrary.h" #include "OgreColladaScene.h" #include "OgreColladaSyntax.h" #include "OgreColladaUtils.h" #include "OgreColladaAsset.h" namespace Ogre { //----------------------------------------------------------------------- ColladaDocument::ColladaDocument(ResourceManager* creator, const String& name, ResourceHandle handle, const String& group, bool isManual, ManualResourceLoader* loader) :Resource(creator, name, handle, group, isManual, loader) , mXmlDoc(0) , mSceneMgr(0) , mLibrary(0) , mScene(0) , mAsset(0) , mUpRotation(Quaternion::IDENTITY) { } //------------------------------------------------------------------------- void ColladaDocument::setSceneManager(SceneManager *scenemgr) { mSceneMgr = scenemgr; } //------------------------------------------------------------------------- ColladaDocument::~ColladaDocument() { // have to call this here rather than in Resource destructor // since calling virtual methods in base destructors causes crash LogManager::getSingleton().logMessage("COLLADA Document: " + getName() + " closing."); unload(); } //----------------------------------------------------------------------- void ColladaDocument::loadImpl(void) { LogManager::getSingleton().logMessage("COLLADA Document: attempting to Load: " + mName + "."); // get the data stream from Resource Group Manager DataStreamPtr dataStream = ResourceGroupManager::getSingleton().openResource(mName, mGroup); // make sure everything is still free if (mXmlDoc) xmlFreeDoc(mXmlDoc); // parse an XML file and build a tree // returns the resulting document tree if the file was wellformed, NULL otherwise if (!(mXmlDoc = xmlParseMemory(dataStream->getAsString().c_str(), static_cast(dataStream->size())))) { LogManager::getSingleton().logMessage("ColladaDocument::loadImpl - could not parse file"); xmlCleanupParser(); return; } // start import with root element of document bool status = importCollada(xmlDocGetRootElement(mXmlDoc)); // free up all the structures used by a document, tree included if (mXmlDoc) { xmlFreeDoc(mXmlDoc); mXmlDoc = NULL; } xmlCleanupParser(); } //----------------------------------------------------------------------- void ColladaDocument::unloadImpl(void) { OGRE_DELETE(mLibrary); OGRE_DELETE(mScene); OGRE_DELETE(mAsset); mSceneMgr = NULL; } //------------------------------------------------------------------------- bool ColladaDocument::doImport(const String &filename, const String &options) { bool status = false; // import options - not yet implemented /* TEST FileInfoListPtr pFileInfo = ResourceGroupManager::getSingleton().findResourceFileInfo(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, filename); if (!pFileInfo->empty()) { LogManager::getSingleton().logMessage("test - " + pFileInfo->at(0).path); } */ // Macro to check that the libxml version in use is compatible with the // version the software has been compiled against LIBXML_TEST_VERSION // test suffix against default collada extension ".dae" String suffix = filename.substr(filename.length()-4,4); if (suffix != ".dae") { LogManager::getSingleton().logMessage("ColladaDocument::doImport - not valid file suffix: " + suffix); return false; } // make sure everything is still free if (mXmlDoc) xmlFreeDoc(mXmlDoc); // parse an XML file and build a tree // returns the resulting document tree if the file was wellformed, NULL otherwise if (!(mXmlDoc = xmlParseFile(filename.c_str()))) { LogManager::getSingleton().logMessage("ColladaDocument::doImport - could not parse file"); xmlCleanupParser(); return false; } // start import with root element of document status = importCollada(xmlDocGetRootElement(mXmlDoc)); // free up all the structures used by a document, tree included if (mXmlDoc) { xmlFreeDoc(mXmlDoc); mXmlDoc = NULL; } xmlCleanupParser(); return status; } //------------------------------------------------------------------------- void ColladaDocument::importAsset(xmlNode *node) { mAsset = new ColladaAsset(node); mAsset->doImport(); // setup up matrix based on settings in asset switch (mAsset->getUpAxis()) { case X_UP: mUpRotation = Quaternion(Degree(-90), Vector3::UNIT_Z); break; case Y_UP: break; case Z_UP: mUpRotation = Quaternion(Degree(-90), Vector3::UNIT_X); break; } } //------------------------------------------------------------------------- bool ColladaDocument::importCollada(xmlNode *element) { // is document well-formed? String tagname = (const char *)element->name; if (tagname != CS_ELM_COLLADA) { LogManager::getSingleton().logMessage("ColladaDocument::importCollada - not well-formed Collada XML document: " + tagname); return false; } mLibrary = new ColladaLibraryContainer(this); // get child elements of for (xmlNode *child = element->children; child != NULL; child = child->next) { // we are interested on element nodes only if (child->type != XML_ELEMENT_NODE) continue; tagname = (const char *)child->name; // look for [0,1] if (tagname == CS_ELM_ASSET) { importAsset(child); } // look for [+] else if (tagname == CS_ELM_LIBRARY) { mLibrary->doImport(child); } // look for [1,1] else if (tagname == CS_ELM_SCENE) { mScene = new ColladaSceneNode(this, child); } // unknwon or unsupported tag else { LogManager::getSingleton().logMessage("ColladaDocument::importCollada - unknown child: " + tagname); } } if (mScene != NULL) return mScene->doImport(); return false; } //------------------------------------------------------------------------- UpAxis ColladaDocument::getUpAxis() const { UpAxis axis = Y_UP; if (mAsset) { axis = mAsset->getUpAxis(); } return axis; } //------------------------------------------------------------------------- void ColladaDocument::correctAxis(Vector3& vec) const { if (mAsset) { switch (mAsset->getUpAxis()) { case X_UP: { Real tmp = vec.y; vec.y = vec.x; vec.x = -tmp; } break; case Y_UP: break; case Z_UP: { Real tmp = vec.y; vec.y = vec.z; vec.z = -tmp; } break; } } } //------------------------------------------------------------------------- void ColladaDocument::correctAxis(Real* vec) const { if (mAsset) { switch (mAsset->getUpAxis()) { case X_UP: { Real tmp = vec[1]; vec[1] = vec[0]; vec[0] = -tmp; } break; case Y_UP: break; case Z_UP: { Real tmp = vec[1]; vec[1] = vec[2]; vec[2] = -tmp; } break; } } } //------------------------------------------------------------------------- void ColladaDocument::correctAxis(Quaternion& quat) const { if (mAsset) { switch (mAsset->getUpAxis()) { case X_UP: { Real tmp = quat.y; quat.y = quat.x; quat.x = -tmp; } break; case Y_UP: break; case Z_UP: { Real tmp = quat.y; quat.y = quat.z; quat.z = -tmp; //quat.w = -quat.w; } break; } } } }