vrshoot

annotate libs/assimp/OgreMaterial.cpp @ 1:e7ca128b8713

looks nice :)
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 02 Feb 2014 00:35:22 +0200
parents
children
rev   line source
nuclear@0 1 /*
nuclear@0 2 Open Asset Import Library (assimp)
nuclear@0 3 ----------------------------------------------------------------------
nuclear@0 4
nuclear@0 5 Copyright (c) 2006-2012, assimp team
nuclear@0 6 All rights reserved.
nuclear@0 7
nuclear@0 8 Redistribution and use of this software in source and binary forms,
nuclear@0 9 with or without modification, are permitted provided that the
nuclear@0 10 following conditions are met:
nuclear@0 11
nuclear@0 12 * Redistributions of source code must retain the above
nuclear@0 13 copyright notice, this list of conditions and the
nuclear@0 14 following disclaimer.
nuclear@0 15
nuclear@0 16 * Redistributions in binary form must reproduce the above
nuclear@0 17 copyright notice, this list of conditions and the
nuclear@0 18 following disclaimer in the documentation and/or other
nuclear@0 19 materials provided with the distribution.
nuclear@0 20
nuclear@0 21 * Neither the name of the assimp team, nor the names of its
nuclear@0 22 contributors may be used to endorse or promote products
nuclear@0 23 derived from this software without specific prior
nuclear@0 24 written permission of the assimp team.
nuclear@0 25
nuclear@0 26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 37
nuclear@0 38 ----------------------------------------------------------------------
nuclear@0 39 */
nuclear@0 40
nuclear@0 41 /**
nuclear@0 42 This file contains material related code. This is
nuclear@0 43 spilitted up from the main file OgreImporter.cpp
nuclear@0 44 to make it shorter easier to maintain.
nuclear@0 45 */
nuclear@0 46 #include "AssimpPCH.h"
nuclear@0 47
nuclear@0 48 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
nuclear@0 49
nuclear@0 50 #include <vector>
nuclear@0 51 #include <sstream>
nuclear@0 52 using namespace std;
nuclear@0 53
nuclear@0 54 #include "OgreImporter.hpp"
nuclear@0 55 #include "irrXMLWrapper.h"
nuclear@0 56 #include "TinyFormatter.h"
nuclear@0 57
nuclear@0 58 namespace Assimp
nuclear@0 59 {
nuclear@0 60 namespace Ogre
nuclear@0 61 {
nuclear@0 62
nuclear@0 63
nuclear@0 64
nuclear@0 65 aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
nuclear@0 66 {
nuclear@0 67 /*For better understanding of the material parser, here is a material example file:
nuclear@0 68
nuclear@0 69 material Sarg
nuclear@0 70 {
nuclear@0 71 receive_shadows on
nuclear@0 72 technique
nuclear@0 73 {
nuclear@0 74 pass
nuclear@0 75 {
nuclear@0 76 ambient 0.500000 0.500000 0.500000 1.000000
nuclear@0 77 diffuse 0.640000 0.640000 0.640000 1.000000
nuclear@0 78 specular 0.500000 0.500000 0.500000 1.000000 12.500000
nuclear@0 79 emissive 0.000000 0.000000 0.000000 1.000000
nuclear@0 80 texture_unit
nuclear@0 81 {
nuclear@0 82 texture SargTextur.tga
nuclear@0 83 tex_address_mode wrap
nuclear@0 84 filtering linear linear none
nuclear@0 85 }
nuclear@0 86 }
nuclear@0 87 }
nuclear@0 88 }
nuclear@0 89
nuclear@0 90 */
nuclear@0 91
nuclear@0 92 /*and here is another one:
nuclear@0 93
nuclear@0 94 import * from abstract_base_passes_depth.material
nuclear@0 95 import * from abstract_base.material
nuclear@0 96 import * from mat_shadow_caster.material
nuclear@0 97 import * from mat_character_singlepass.material
nuclear@0 98
nuclear@0 99 material hero/hair/caster : mat_shadow_caster_skin_areject
nuclear@0 100 {
nuclear@0 101 set $diffuse_map "hero_hair_alpha_c.dds"
nuclear@0 102 }
nuclear@0 103
nuclear@0 104 material hero/hair_alpha : mat_char_cns_singlepass_areject_4weights
nuclear@0 105 {
nuclear@0 106 set $diffuse_map "hero_hair_alpha_c.dds"
nuclear@0 107 set $specular_map "hero_hair_alpha_s.dds"
nuclear@0 108 set $normal_map "hero_hair_alpha_n.dds"
nuclear@0 109 set $light_map "black_lightmap.dds"
nuclear@0 110
nuclear@0 111 set $shadow_caster_material "hero/hair/caster"
nuclear@0 112 }
nuclear@0 113 */
nuclear@0 114
nuclear@0 115 //Read the file into memory and put it in a stringstream
nuclear@0 116 stringstream ss;
nuclear@0 117 {// after this block, the temporarly loaded data will be released
nuclear@0 118
nuclear@0 119 /*
nuclear@0 120 We have 3 guesses for the Material filename:
nuclear@0 121 - the Material Name
nuclear@0 122 - the Name of the mesh file
nuclear@0 123 - the DefaultMaterialLib (which you can set before importing)
nuclear@0 124 */
nuclear@0 125
nuclear@0 126 IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialName+".material");
nuclear@0 127 if(NULL==MatFilePtr)
nuclear@0 128 {
nuclear@0 129 //the filename typically ends with .mesh or .mesh.xml
nuclear@0 130 const string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.rfind(".mesh"))+".material";
nuclear@0 131
nuclear@0 132 MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName);
nuclear@0 133 if(NULL==MatFilePtr)
nuclear@0 134 {
nuclear@0 135 //try the default mat Library
nuclear@0 136 if(NULL==MatFilePtr)
nuclear@0 137 {
nuclear@0 138
nuclear@0 139 MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename);
nuclear@0 140 if(NULL==MatFilePtr)
nuclear@0 141 {
nuclear@0 142 DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!");
nuclear@0 143 return new aiMaterial();
nuclear@0 144 }
nuclear@0 145 }
nuclear@0 146 }
nuclear@0 147 }
nuclear@0 148 //Fill the stream
nuclear@0 149 boost::scoped_ptr<IOStream> MaterialFile(MatFilePtr);
nuclear@0 150 if(MaterialFile->FileSize()>0)
nuclear@0 151 {
nuclear@0 152 vector<char> FileData(MaterialFile->FileSize());
nuclear@0 153 MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1);
nuclear@0 154 BaseImporter::ConvertToUTF8(FileData);
nuclear@0 155
nuclear@0 156 FileData.push_back('\0');//terminate the string with zero, so that the ss can parse it correctly
nuclear@0 157 ss << &FileData[0];
nuclear@0 158 }
nuclear@0 159 else
nuclear@0 160 {
nuclear@0 161 DefaultLogger::get()->warn("Material " + MaterialName + " seams to be empty");
nuclear@0 162 return NULL;
nuclear@0 163 }
nuclear@0 164 }
nuclear@0 165
nuclear@0 166 //create the material
nuclear@0 167 aiMaterial *NewMaterial=new aiMaterial();
nuclear@0 168
nuclear@0 169 aiString ts(MaterialName.c_str());
nuclear@0 170 NewMaterial->AddProperty(&ts, AI_MATKEY_NAME);
nuclear@0 171
nuclear@0 172 string Line;
nuclear@0 173 ss >> Line;
nuclear@0 174 // unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another
nuclear@0 175 while(!ss.eof())
nuclear@0 176 {
nuclear@0 177 if(Line=="material")
nuclear@0 178 {
nuclear@0 179 ss >> Line;
nuclear@0 180 if(Line==MaterialName)//Load the next material
nuclear@0 181 {
nuclear@0 182 string RestOfLine;
nuclear@0 183 getline(ss, RestOfLine);//ignore the rest of the line
nuclear@0 184 ss >> Line;
nuclear@0 185
nuclear@0 186 if(Line!="{")
nuclear@0 187 {
nuclear@0 188 DefaultLogger::get()->warn("empyt material!");
nuclear@0 189 return NULL;
nuclear@0 190 }
nuclear@0 191
nuclear@0 192 while(Line!="}")//read until the end of the material
nuclear@0 193 {
nuclear@0 194 //Proceed to the first technique
nuclear@0 195 ss >> Line;
nuclear@0 196 if(Line=="technique")
nuclear@0 197 {
nuclear@0 198 ReadTechnique(ss, NewMaterial);
nuclear@0 199 }
nuclear@0 200
nuclear@0 201 DefaultLogger::get()->info(Line);
nuclear@0 202 //read informations from a custom material:
nuclear@0 203 if(Line=="set")
nuclear@0 204 {
nuclear@0 205 ss >> Line;
nuclear@0 206 if(Line=="$specular")//todo load this values:
nuclear@0 207 {
nuclear@0 208 }
nuclear@0 209 if(Line=="$diffuse")
nuclear@0 210 {
nuclear@0 211 }
nuclear@0 212 if(Line=="$ambient")
nuclear@0 213 {
nuclear@0 214 }
nuclear@0 215 if(Line=="$colormap")
nuclear@0 216 {
nuclear@0 217 ss >> Line;
nuclear@0 218 aiString ts(Line.c_str());
nuclear@0 219 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
nuclear@0 220 }
nuclear@0 221 if(Line=="$normalmap")
nuclear@0 222 {
nuclear@0 223 ss >> Line;
nuclear@0 224 aiString ts(Line.c_str());
nuclear@0 225 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
nuclear@0 226 }
nuclear@0 227
nuclear@0 228 if(Line=="$shininess_strength")
nuclear@0 229 {
nuclear@0 230 ss >> Line;
nuclear@0 231 float Shininess=fast_atof(Line.c_str());
nuclear@0 232 NewMaterial->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
nuclear@0 233 }
nuclear@0 234
nuclear@0 235 if(Line=="$shininess_exponent")
nuclear@0 236 {
nuclear@0 237 ss >> Line;
nuclear@0 238 float Shininess=fast_atof(Line.c_str());
nuclear@0 239 NewMaterial->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
nuclear@0 240 }
nuclear@0 241
nuclear@0 242 //Properties from Venetica:
nuclear@0 243 if(Line=="$diffuse_map")
nuclear@0 244 {
nuclear@0 245 ss >> Line;
nuclear@0 246 if(Line[0]=='"')// "file" -> file
nuclear@0 247 Line=Line.substr(1, Line.size()-2);
nuclear@0 248 aiString ts(Line.c_str());
nuclear@0 249 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
nuclear@0 250 }
nuclear@0 251 if(Line=="$specular_map")
nuclear@0 252 {
nuclear@0 253 ss >> Line;
nuclear@0 254 if(Line[0]=='"')// "file" -> file
nuclear@0 255 Line=Line.substr(1, Line.size()-2);
nuclear@0 256 aiString ts(Line.c_str());
nuclear@0 257 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
nuclear@0 258 }
nuclear@0 259 if(Line=="$normal_map")
nuclear@0 260 {
nuclear@0 261 ss >> Line;
nuclear@0 262 if(Line[0]=='"')// "file" -> file
nuclear@0 263 Line=Line.substr(1, Line.size()-2);
nuclear@0 264 aiString ts(Line.c_str());
nuclear@0 265 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
nuclear@0 266 }
nuclear@0 267 if(Line=="$light_map")
nuclear@0 268 {
nuclear@0 269 ss >> Line;
nuclear@0 270 if(Line[0]=='"')// "file" -> file
nuclear@0 271 Line=Line.substr(1, Line.size()-2);
nuclear@0 272 aiString ts(Line.c_str());
nuclear@0 273 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
nuclear@0 274 }
nuclear@0 275 }
nuclear@0 276 }//end of material
nuclear@0 277 }
nuclear@0 278 else {} //this is the wrong material, proceed the file until we reach the next material
nuclear@0 279 }
nuclear@0 280 ss >> Line;
nuclear@0 281 }
nuclear@0 282
nuclear@0 283 return NewMaterial;
nuclear@0 284 }
nuclear@0 285
nuclear@0 286 void OgreImporter::ReadTechnique(stringstream &ss, aiMaterial* NewMaterial) const
nuclear@0 287 {
nuclear@0 288 unsigned int CurrentDiffuseTextureId=0;
nuclear@0 289 unsigned int CurrentSpecularTextureId=0;
nuclear@0 290 unsigned int CurrentNormalTextureId=0;
nuclear@0 291 unsigned int CurrentLightTextureId=0;
nuclear@0 292
nuclear@0 293
nuclear@0 294 string RestOfLine;
nuclear@0 295 getline(ss, RestOfLine);//ignore the rest of the line
nuclear@0 296
nuclear@0 297 string Line;
nuclear@0 298 ss >> Line;
nuclear@0 299 if(Line!="{")
nuclear@0 300 {
nuclear@0 301 DefaultLogger::get()->warn("empty technique!");
nuclear@0 302 return;
nuclear@0 303 }
nuclear@0 304 while(Line!="}")//read until the end of the technique
nuclear@0 305 {
nuclear@0 306 ss >> Line;
nuclear@0 307 if(Line=="pass")
nuclear@0 308 {
nuclear@0 309 getline(ss, RestOfLine);//ignore the rest of the line
nuclear@0 310
nuclear@0 311 ss >> Line;
nuclear@0 312 if(Line!="{")
nuclear@0 313 {
nuclear@0 314 DefaultLogger::get()->warn("empty pass!");
nuclear@0 315 return;
nuclear@0 316 }
nuclear@0 317 while(Line!="}")//read until the end of the pass
nuclear@0 318 {
nuclear@0 319 ss >> Line;
nuclear@0 320 if(Line=="ambient")
nuclear@0 321 {
nuclear@0 322 float r,g,b;
nuclear@0 323 ss >> r >> g >> b;
nuclear@0 324 const aiColor3D Color(r,g,b);
nuclear@0 325 NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_AMBIENT);
nuclear@0 326 }
nuclear@0 327 else if(Line=="diffuse")
nuclear@0 328 {
nuclear@0 329 float r,g,b;
nuclear@0 330 ss >> r >> g >> b;
nuclear@0 331 const aiColor3D Color(r,g,b);
nuclear@0 332 NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_DIFFUSE);
nuclear@0 333 }
nuclear@0 334 else if(Line=="specular")
nuclear@0 335 {
nuclear@0 336 float r,g,b;
nuclear@0 337 ss >> r >> g >> b;
nuclear@0 338 const aiColor3D Color(r,g,b);
nuclear@0 339 NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_SPECULAR);
nuclear@0 340 }
nuclear@0 341 else if(Line=="emmisive")
nuclear@0 342 {
nuclear@0 343 float r,g,b;
nuclear@0 344 ss >> r >> g >> b;
nuclear@0 345 const aiColor3D Color(r,g,b);
nuclear@0 346 NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_EMISSIVE);
nuclear@0 347 }
nuclear@0 348 else if(Line=="texture_unit")
nuclear@0 349 {
nuclear@0 350 getline(ss, RestOfLine);//ignore the rest of the line
nuclear@0 351
nuclear@0 352 std::string TextureName;
nuclear@0 353 int TextureType=-1;
nuclear@0 354 int UvSet=0;
nuclear@0 355
nuclear@0 356 ss >> Line;
nuclear@0 357 if(Line!="{")
nuclear@0 358 throw DeadlyImportError("empty texture unit!");
nuclear@0 359 while(Line!="}")//read until the end of the texture_unit
nuclear@0 360 {
nuclear@0 361 ss >> Line;
nuclear@0 362 if(Line=="texture")
nuclear@0 363 {
nuclear@0 364 ss >> Line;
nuclear@0 365 TextureName=Line;
nuclear@0 366
nuclear@0 367 if(m_TextureTypeFromFilename)
nuclear@0 368 {
nuclear@0 369 if(Line.find("_n.")!=string::npos)// Normalmap
nuclear@0 370 {
nuclear@0 371 TextureType=aiTextureType_NORMALS;
nuclear@0 372 }
nuclear@0 373 else if(Line.find("_s.")!=string::npos)// Specularmap
nuclear@0 374 {
nuclear@0 375 TextureType=aiTextureType_SPECULAR;
nuclear@0 376 }
nuclear@0 377 else if(Line.find("_l.")!=string::npos)// Lightmap
nuclear@0 378 {
nuclear@0 379 TextureType=aiTextureType_LIGHTMAP;
nuclear@0 380 }
nuclear@0 381 else// colormap
nuclear@0 382 {
nuclear@0 383 TextureType=aiTextureType_DIFFUSE;
nuclear@0 384 }
nuclear@0 385 }
nuclear@0 386 else
nuclear@0 387 {
nuclear@0 388 TextureType=aiTextureType_DIFFUSE;
nuclear@0 389 }
nuclear@0 390 }
nuclear@0 391 else if(Line=="tex_coord_set")
nuclear@0 392 {
nuclear@0 393 ss >> UvSet;
nuclear@0 394 }
nuclear@0 395 else if(Line=="colour_op")//TODO implement this
nuclear@0 396 {
nuclear@0 397 /*
nuclear@0 398 ss >> Line;
nuclear@0 399 if("replace"==Line)//I don't think, assimp has something for this...
nuclear@0 400 {
nuclear@0 401 }
nuclear@0 402 else if("modulate"==Line)
nuclear@0 403 {
nuclear@0 404 //TODO: set value
nuclear@0 405 //NewMaterial->AddProperty(aiTextureOp_Multiply)
nuclear@0 406 }
nuclear@0 407 */
nuclear@0 408 }
nuclear@0 409
nuclear@0 410 }//end of texture unit
nuclear@0 411 Line="";//clear the } that would end the outer loop
nuclear@0 412
nuclear@0 413 //give the texture to assimp:
nuclear@0 414
nuclear@0 415 aiString ts(TextureName.c_str());
nuclear@0 416 switch(TextureType)
nuclear@0 417 {
nuclear@0 418 case aiTextureType_DIFFUSE:
nuclear@0 419 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, CurrentDiffuseTextureId));
nuclear@0 420 NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentDiffuseTextureId));
nuclear@0 421 CurrentDiffuseTextureId++;
nuclear@0 422 break;
nuclear@0 423 case aiTextureType_NORMALS:
nuclear@0 424 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, CurrentNormalTextureId));
nuclear@0 425 NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentNormalTextureId));
nuclear@0 426 CurrentNormalTextureId++;
nuclear@0 427 break;
nuclear@0 428 case aiTextureType_SPECULAR:
nuclear@0 429 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SPECULAR, CurrentSpecularTextureId));
nuclear@0 430 NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentSpecularTextureId));
nuclear@0 431 CurrentSpecularTextureId++;
nuclear@0 432 break;
nuclear@0 433 case aiTextureType_LIGHTMAP:
nuclear@0 434 NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, CurrentLightTextureId));
nuclear@0 435 NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentLightTextureId));
nuclear@0 436 CurrentLightTextureId++;
nuclear@0 437 break;
nuclear@0 438 default:
nuclear@0 439 DefaultLogger::get()->warn("Invalid Texture Type!");
nuclear@0 440 break;
nuclear@0 441 }
nuclear@0 442 }
nuclear@0 443 }
nuclear@0 444 Line="";//clear the } that would end the outer loop
nuclear@0 445 }
nuclear@0 446 }//end of technique
nuclear@0 447 }
nuclear@0 448
nuclear@0 449
nuclear@0 450 }//namespace Ogre
nuclear@0 451 }//namespace Assimp
nuclear@0 452
nuclear@0 453 #endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER