nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** nuclear@0: This file contains material related code. This is nuclear@0: spilitted up from the main file OgreImporter.cpp nuclear@0: to make it shorter easier to maintain. nuclear@0: */ nuclear@0: #include "AssimpPCH.h" nuclear@0: nuclear@0: #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER nuclear@0: nuclear@0: #include nuclear@0: #include nuclear@0: using namespace std; nuclear@0: nuclear@0: #include "OgreImporter.hpp" nuclear@0: #include "irrXMLWrapper.h" nuclear@0: #include "TinyFormatter.h" nuclear@0: nuclear@0: namespace Assimp nuclear@0: { nuclear@0: namespace Ogre nuclear@0: { nuclear@0: nuclear@0: nuclear@0: nuclear@0: aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const nuclear@0: { nuclear@0: /*For better understanding of the material parser, here is a material example file: nuclear@0: nuclear@0: material Sarg nuclear@0: { nuclear@0: receive_shadows on nuclear@0: technique nuclear@0: { nuclear@0: pass nuclear@0: { nuclear@0: ambient 0.500000 0.500000 0.500000 1.000000 nuclear@0: diffuse 0.640000 0.640000 0.640000 1.000000 nuclear@0: specular 0.500000 0.500000 0.500000 1.000000 12.500000 nuclear@0: emissive 0.000000 0.000000 0.000000 1.000000 nuclear@0: texture_unit nuclear@0: { nuclear@0: texture SargTextur.tga nuclear@0: tex_address_mode wrap nuclear@0: filtering linear linear none nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: */ nuclear@0: nuclear@0: /*and here is another one: nuclear@0: nuclear@0: import * from abstract_base_passes_depth.material nuclear@0: import * from abstract_base.material nuclear@0: import * from mat_shadow_caster.material nuclear@0: import * from mat_character_singlepass.material nuclear@0: nuclear@0: material hero/hair/caster : mat_shadow_caster_skin_areject nuclear@0: { nuclear@0: set $diffuse_map "hero_hair_alpha_c.dds" nuclear@0: } nuclear@0: nuclear@0: material hero/hair_alpha : mat_char_cns_singlepass_areject_4weights nuclear@0: { nuclear@0: set $diffuse_map "hero_hair_alpha_c.dds" nuclear@0: set $specular_map "hero_hair_alpha_s.dds" nuclear@0: set $normal_map "hero_hair_alpha_n.dds" nuclear@0: set $light_map "black_lightmap.dds" nuclear@0: nuclear@0: set $shadow_caster_material "hero/hair/caster" nuclear@0: } nuclear@0: */ nuclear@0: nuclear@0: //Read the file into memory and put it in a stringstream nuclear@0: stringstream ss; nuclear@0: {// after this block, the temporarly loaded data will be released nuclear@0: nuclear@0: /* nuclear@0: We have 3 guesses for the Material filename: nuclear@0: - the Material Name nuclear@0: - the Name of the mesh file nuclear@0: - the DefaultMaterialLib (which you can set before importing) nuclear@0: */ nuclear@0: nuclear@0: IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialName+".material"); nuclear@0: if(NULL==MatFilePtr) nuclear@0: { nuclear@0: //the filename typically ends with .mesh or .mesh.xml nuclear@0: const string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.rfind(".mesh"))+".material"; nuclear@0: nuclear@0: MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName); nuclear@0: if(NULL==MatFilePtr) nuclear@0: { nuclear@0: //try the default mat Library nuclear@0: if(NULL==MatFilePtr) nuclear@0: { nuclear@0: nuclear@0: MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename); nuclear@0: if(NULL==MatFilePtr) nuclear@0: { nuclear@0: DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!"); nuclear@0: return new aiMaterial(); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: //Fill the stream nuclear@0: boost::scoped_ptr MaterialFile(MatFilePtr); nuclear@0: if(MaterialFile->FileSize()>0) nuclear@0: { nuclear@0: vector FileData(MaterialFile->FileSize()); nuclear@0: MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1); nuclear@0: BaseImporter::ConvertToUTF8(FileData); nuclear@0: nuclear@0: FileData.push_back('\0');//terminate the string with zero, so that the ss can parse it correctly nuclear@0: ss << &FileData[0]; nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: DefaultLogger::get()->warn("Material " + MaterialName + " seams to be empty"); nuclear@0: return NULL; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: //create the material nuclear@0: aiMaterial *NewMaterial=new aiMaterial(); nuclear@0: nuclear@0: aiString ts(MaterialName.c_str()); nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_NAME); nuclear@0: nuclear@0: string Line; nuclear@0: ss >> Line; nuclear@0: // unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another nuclear@0: while(!ss.eof()) nuclear@0: { nuclear@0: if(Line=="material") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line==MaterialName)//Load the next material nuclear@0: { nuclear@0: string RestOfLine; nuclear@0: getline(ss, RestOfLine);//ignore the rest of the line nuclear@0: ss >> Line; nuclear@0: nuclear@0: if(Line!="{") nuclear@0: { nuclear@0: DefaultLogger::get()->warn("empyt material!"); nuclear@0: return NULL; nuclear@0: } nuclear@0: nuclear@0: while(Line!="}")//read until the end of the material nuclear@0: { nuclear@0: //Proceed to the first technique nuclear@0: ss >> Line; nuclear@0: if(Line=="technique") nuclear@0: { nuclear@0: ReadTechnique(ss, NewMaterial); nuclear@0: } nuclear@0: nuclear@0: DefaultLogger::get()->info(Line); nuclear@0: //read informations from a custom material: nuclear@0: if(Line=="set") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line=="$specular")//todo load this values: nuclear@0: { nuclear@0: } nuclear@0: if(Line=="$diffuse") nuclear@0: { nuclear@0: } nuclear@0: if(Line=="$ambient") nuclear@0: { nuclear@0: } nuclear@0: if(Line=="$colormap") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: aiString ts(Line.c_str()); nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); nuclear@0: } nuclear@0: if(Line=="$normalmap") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: aiString ts(Line.c_str()); nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); nuclear@0: } nuclear@0: nuclear@0: if(Line=="$shininess_strength") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: float Shininess=fast_atof(Line.c_str()); nuclear@0: NewMaterial->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH); nuclear@0: } nuclear@0: nuclear@0: if(Line=="$shininess_exponent") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: float Shininess=fast_atof(Line.c_str()); nuclear@0: NewMaterial->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS); nuclear@0: } nuclear@0: nuclear@0: //Properties from Venetica: nuclear@0: if(Line=="$diffuse_map") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line[0]=='"')// "file" -> file nuclear@0: Line=Line.substr(1, Line.size()-2); nuclear@0: aiString ts(Line.c_str()); nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); nuclear@0: } nuclear@0: if(Line=="$specular_map") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line[0]=='"')// "file" -> file nuclear@0: Line=Line.substr(1, Line.size()-2); nuclear@0: aiString ts(Line.c_str()); nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0)); nuclear@0: } nuclear@0: if(Line=="$normal_map") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line[0]=='"')// "file" -> file nuclear@0: Line=Line.substr(1, Line.size()-2); nuclear@0: aiString ts(Line.c_str()); nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); nuclear@0: } nuclear@0: if(Line=="$light_map") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line[0]=='"')// "file" -> file nuclear@0: Line=Line.substr(1, Line.size()-2); nuclear@0: aiString ts(Line.c_str()); nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0)); nuclear@0: } nuclear@0: } nuclear@0: }//end of material nuclear@0: } nuclear@0: else {} //this is the wrong material, proceed the file until we reach the next material nuclear@0: } nuclear@0: ss >> Line; nuclear@0: } nuclear@0: nuclear@0: return NewMaterial; nuclear@0: } nuclear@0: nuclear@0: void OgreImporter::ReadTechnique(stringstream &ss, aiMaterial* NewMaterial) const nuclear@0: { nuclear@0: unsigned int CurrentDiffuseTextureId=0; nuclear@0: unsigned int CurrentSpecularTextureId=0; nuclear@0: unsigned int CurrentNormalTextureId=0; nuclear@0: unsigned int CurrentLightTextureId=0; nuclear@0: nuclear@0: nuclear@0: string RestOfLine; nuclear@0: getline(ss, RestOfLine);//ignore the rest of the line nuclear@0: nuclear@0: string Line; nuclear@0: ss >> Line; nuclear@0: if(Line!="{") nuclear@0: { nuclear@0: DefaultLogger::get()->warn("empty technique!"); nuclear@0: return; nuclear@0: } nuclear@0: while(Line!="}")//read until the end of the technique nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line=="pass") nuclear@0: { nuclear@0: getline(ss, RestOfLine);//ignore the rest of the line nuclear@0: nuclear@0: ss >> Line; nuclear@0: if(Line!="{") nuclear@0: { nuclear@0: DefaultLogger::get()->warn("empty pass!"); nuclear@0: return; nuclear@0: } nuclear@0: while(Line!="}")//read until the end of the pass nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line=="ambient") nuclear@0: { nuclear@0: float r,g,b; nuclear@0: ss >> r >> g >> b; nuclear@0: const aiColor3D Color(r,g,b); nuclear@0: NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_AMBIENT); nuclear@0: } nuclear@0: else if(Line=="diffuse") nuclear@0: { nuclear@0: float r,g,b; nuclear@0: ss >> r >> g >> b; nuclear@0: const aiColor3D Color(r,g,b); nuclear@0: NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_DIFFUSE); nuclear@0: } nuclear@0: else if(Line=="specular") nuclear@0: { nuclear@0: float r,g,b; nuclear@0: ss >> r >> g >> b; nuclear@0: const aiColor3D Color(r,g,b); nuclear@0: NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_SPECULAR); nuclear@0: } nuclear@0: else if(Line=="emmisive") nuclear@0: { nuclear@0: float r,g,b; nuclear@0: ss >> r >> g >> b; nuclear@0: const aiColor3D Color(r,g,b); nuclear@0: NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_EMISSIVE); nuclear@0: } nuclear@0: else if(Line=="texture_unit") nuclear@0: { nuclear@0: getline(ss, RestOfLine);//ignore the rest of the line nuclear@0: nuclear@0: std::string TextureName; nuclear@0: int TextureType=-1; nuclear@0: int UvSet=0; nuclear@0: nuclear@0: ss >> Line; nuclear@0: if(Line!="{") nuclear@0: throw DeadlyImportError("empty texture unit!"); nuclear@0: while(Line!="}")//read until the end of the texture_unit nuclear@0: { nuclear@0: ss >> Line; nuclear@0: if(Line=="texture") nuclear@0: { nuclear@0: ss >> Line; nuclear@0: TextureName=Line; nuclear@0: nuclear@0: if(m_TextureTypeFromFilename) nuclear@0: { nuclear@0: if(Line.find("_n.")!=string::npos)// Normalmap nuclear@0: { nuclear@0: TextureType=aiTextureType_NORMALS; nuclear@0: } nuclear@0: else if(Line.find("_s.")!=string::npos)// Specularmap nuclear@0: { nuclear@0: TextureType=aiTextureType_SPECULAR; nuclear@0: } nuclear@0: else if(Line.find("_l.")!=string::npos)// Lightmap nuclear@0: { nuclear@0: TextureType=aiTextureType_LIGHTMAP; nuclear@0: } nuclear@0: else// colormap nuclear@0: { nuclear@0: TextureType=aiTextureType_DIFFUSE; nuclear@0: } nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: TextureType=aiTextureType_DIFFUSE; nuclear@0: } nuclear@0: } nuclear@0: else if(Line=="tex_coord_set") nuclear@0: { nuclear@0: ss >> UvSet; nuclear@0: } nuclear@0: else if(Line=="colour_op")//TODO implement this nuclear@0: { nuclear@0: /* nuclear@0: ss >> Line; nuclear@0: if("replace"==Line)//I don't think, assimp has something for this... nuclear@0: { nuclear@0: } nuclear@0: else if("modulate"==Line) nuclear@0: { nuclear@0: //TODO: set value nuclear@0: //NewMaterial->AddProperty(aiTextureOp_Multiply) nuclear@0: } nuclear@0: */ nuclear@0: } nuclear@0: nuclear@0: }//end of texture unit nuclear@0: Line="";//clear the } that would end the outer loop nuclear@0: nuclear@0: //give the texture to assimp: nuclear@0: nuclear@0: aiString ts(TextureName.c_str()); nuclear@0: switch(TextureType) nuclear@0: { nuclear@0: case aiTextureType_DIFFUSE: nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, CurrentDiffuseTextureId)); nuclear@0: NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentDiffuseTextureId)); nuclear@0: CurrentDiffuseTextureId++; nuclear@0: break; nuclear@0: case aiTextureType_NORMALS: nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, CurrentNormalTextureId)); nuclear@0: NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentNormalTextureId)); nuclear@0: CurrentNormalTextureId++; nuclear@0: break; nuclear@0: case aiTextureType_SPECULAR: nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SPECULAR, CurrentSpecularTextureId)); nuclear@0: NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentSpecularTextureId)); nuclear@0: CurrentSpecularTextureId++; nuclear@0: break; nuclear@0: case aiTextureType_LIGHTMAP: nuclear@0: NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, CurrentLightTextureId)); nuclear@0: NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentLightTextureId)); nuclear@0: CurrentLightTextureId++; nuclear@0: break; nuclear@0: default: nuclear@0: DefaultLogger::get()->warn("Invalid Texture Type!"); nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: Line="";//clear the } that would end the outer loop nuclear@0: } nuclear@0: }//end of technique nuclear@0: } nuclear@0: nuclear@0: nuclear@0: }//namespace Ogre nuclear@0: }//namespace Assimp nuclear@0: nuclear@0: #endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER