/** * 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. * * @author Philipp Hartl * @see README */ #include "OgreColladaMaterial.h" #include "OgreColladaDocument.h" #include "OgreColladaLibrary.h" #include "OgreColladaTexture.h" #include "OgreColladaSyntax.h" #include "OgreColladaUtils.h" #include "OgreMaterialManager.h" #include "OgreTechnique.h" #include "OgreStringConverter.h" namespace Ogre { //------------------------------------------------------------------------- ColladaMaterial::ColladaMaterial(ColladaDocument *doc, xmlNode *n) : ColladaEntity(doc, n) { } //------------------------------------------------------------------------- ColladaMaterial::~ColladaMaterial(void) { if (!mPasses.empty()) { for (ColladaMaterialPassPtrVector::iterator it = mPasses.begin(); it != mPasses.end(); ++it) { if (!(*it)->mTextures.empty()) (*it)->mTextures.clear(); // the instances will be deleted by the library container! OGRE_DELETE(*it); } mPasses.clear(); } } //------------------------------------------------------------------------- MovableObject *ColladaMaterial::getOgreInstance(void) const { ushort ipass = 0; // get new material pointer MaterialPtr material = MaterialManager::getSingleton().create(mId, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // for all passes for (ColladaMaterialPassPtrVector::const_iterator it = mPasses.begin(); it != mPasses.end(); ++it) { // set all parameters, ogre should take only those into account which are necessary for this shading mode material->getTechnique(0)->getPass(ipass)->setShadingMode((*it)->mMode); material->getTechnique(0)->getPass(ipass)->setAmbient((*it)->mAmbient); material->getTechnique(0)->getPass(ipass)->setDiffuse((*it)->mDiffuse); material->getTechnique(0)->getPass(ipass)->setSpecular((*it)->mSpecular); material->getTechnique(0)->getPass(ipass)->setShininess((*it)->mShininess); material->getTechnique(0)->getPass(ipass)->setSelfIllumination((*it)->mEmission); // for multitexturing colouroperations(_ex) must be set! (alpha_blend, src, dest) for (ColladaTexturePtrVector::iterator jt = (*it)->mTextures.begin(); jt != (*it)->mTextures.end(); ++jt) { material->getTechnique(0)->getPass(ipass)->createTextureUnitState((*jt)->getImage()->getSource()); } ipass++; } // load material, resource loader? material->load(); // TEST // LogManager::getSingleton().logMessage("ColladaMaterial::createOgreMaterial - finished!"); return NULL; } //------------------------------------------------------------------------- bool ColladaMaterial::doImport(void) { if (mLoaded) return mStatus; else mLoaded = true; // do we need them? // child // xmlNode *asset = ColladaUtils::getChildByTagName(mNode, CS_ELM_ASSET); // childs // xmlNodePtrVector params = ColladaUtils::getChildsByTagName(mNode, CS_ELM_PARAM); // child xmlNode *shader = ColladaUtils::getChildByTagName(mNode, CS_ELM_SHADER); // get all childs of shader xmlNodePtrVector techniques = ColladaUtils::getChildsByTagName(shader, CS_ELM_TECHNIQUE); // currently we are only interested in "COMMON" profile xmlNode *technique = NULL; xmlNodePtrVector::iterator it; for (it = techniques.begin(); it != techniques.end(); ++it) { String profile = ColladaUtils::getProperty(*it, CS_ATR_PROFILE); if (profile == CS_VAL_TECHNIQUE_PROFILE_COMMON) { technique = *it; break; } } if (technique == NULL) return false; // the first will be ignored // get elements xmlNodePtrVector passes = ColladaUtils::getChildsByTagName(technique, CS_ELM_PASS); // each pass will be stored on the vector list for (it = passes.begin(); it != passes.end(); ++it) mPasses.push_back(importPass(*it)); if (mPasses.empty()) return false; // TEST getOgreInstance(); mStatus = true; return mStatus; } //------------------------------------------------------------------------- ColladaMaterialPass *ColladaMaterial::importPass(xmlNode *pass) { ColladaMaterialPass *newpass = new ColladaMaterialPass; // do we need the node(s)? /** * import tags, maybe there are textures * get source out of input texture node and try to * load the texture entity, push it on the texture list for multitexture purpose */ xmlNodePtrVector inputs = ColladaUtils::getChildsByTagName(pass, CS_ELM_INPUT); xmlNodePtrVector::iterator it; for (it = inputs.begin(); it != inputs.end(); ++it) { // look for the input with semantic="TEXTURE" String semantic = ColladaUtils::getProperty(*it, CS_ATR_INPUT_SEMANTIC); if (semantic == CS_VAL_INPUT_SEMANTIC_TEXTURE) { // get source attribute String source = ColladaUtils::getProperty(*it, CS_ATR_INPUT_SOURCE); if (source.empty()) { LogManager::getSingleton().logMessage("ColladaMaterial::importPass - no source url for texture is given! " + mId); continue; } // local reference of texture file if (source.find("#") == 0) { source.erase(0,1); // try to find the instance and load it, if it is not already loaded ColladaTexture *texture = mDoc->getLibrary()->getTexture(source); if (texture == NULL) { LogManager::getSingleton().logMessage("ColladaMaterial::importPass - can't find the texture reference " + source + "! " + mId); continue; } // try to import the entity if (!texture->doImport()) { LogManager::getSingleton().logMessage("ColladaMaterial::importPass - loading of texture " + source + " failed! " + mId); continue; } // save valid texture on the list newpass->mTextures.push_back(texture); } // external else { LogManager::getSingleton().logMessage("ColladaMaterial::importPass - external refernces are currently not implemented! " + mId); continue; } } } // get xmlNode *program = ColladaUtils::getChildByTagName(pass, CS_ELM_PROGRAM); // possible material shader types: CONSTANT, LAMBERT, PHONG String programUrl = ColladaUtils::getProperty(program, CS_ATR_URL); newpass->mMode = SO_GOURAUD; // lambert if (programUrl == CS_VAL_PROGRAM_URL_PHONG) newpass->mMode = SO_PHONG; else if (programUrl == CS_VAL_PROGRAM_URL_CONSTANT) newpass->mMode = SO_FLAT; // reset all colours newpass->mAmbient = ColourValue(0,0,0,0); newpass->mDiffuse = ColourValue(0,0,0,0); newpass->mSpecular = ColourValue(0,0,0,0); newpass->mShininess = 0.0; newpass->mEmission = ColourValue(0,0,0,0); newpass->mReflective = ColourValue(0,0,0,0); newpass->mReflectivity = 0.0; // mattle newpass->mTransparent = ColourValue(0,0,0,0); newpass->mTransparency = 0.0; // opaque // now get the of the program xmlNodePtrVector params = ColladaUtils::getChildsByTagName(program, CS_ELM_PARAM); for (it = params.begin(); it != params.end(); ++it) { // property name String name = ColladaUtils::getProperty(*it, CS_ATR_NAME); // the value String content = ColladaUtils::getContentDirect(*it); // TEST // LogManager::getSingleton().logMessage("ColladaMaterial::importPass - colour " + name + ": " + content); // AMBIENT, float3 if (name == CS_VAL_MATERIAL_PARAM_AMBIENT) { newpass->mAmbient = StringConverter::parseColourValue(content); } // DIFFUSE else if (name == CS_VAL_MATERIAL_PARAM_DIFFUSE) { newpass->mDiffuse = StringConverter::parseColourValue(content); } // SPECULAR else if (name == CS_VAL_MATERIAL_PARAM_SPECULAR) { newpass->mSpecular = StringConverter::parseColourValue(content); } // SHININESS else if (name == CS_VAL_MATERIAL_PARAM_SHININESS) { newpass->mShininess = StringConverter::parseReal(content); } // TRANSPARENT else if (name == CS_VAL_MATERIAL_PARAM_TRANSPARENT) { newpass->mTransparent = StringConverter::parseColourValue(content); } // TRANSPARENCY else if (name == CS_VAL_MATERIAL_PARAM_TRANSPARENCY) { newpass->mTransparency = StringConverter::parseReal(content); } // EMISSION else if (name == CS_VAL_MATERIAL_PARAM_EMISSION) { newpass->mEmission = StringConverter::parseColourValue(content); } // REFLECTIVE else if (name == CS_VAL_MATERIAL_PARAM_REFLECTIVE) { newpass->mReflective = StringConverter::parseColourValue(content); } // REFLECTIVITY else if (name == CS_VAL_MATERIAL_PARAM_REFLECTIVITY) { newpass->mReflectivity = StringConverter::parseReal(content); } else { LogManager::getSingleton().logMessage("ColladaMaterial::importPass - unknown attribute of material param " + name + "! " + mId); } } // set alpha value for the colours float alpha = 1.0 - newpass->mTransparency; newpass->mDiffuse.a = alpha; newpass->mSpecular.a = alpha; return newpass; } }