1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2014 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 #include "OgreXSIMaterialExporter.h" 29 #include "OgreMaterialManager.h" 30 #include "OgreMaterial.h" 31 #include "OgreTechnique.h" 32 #include "OgrePass.h" 33 #include "OgreTextureUnitState.h" 34 35 #include <xsi_shader.h> 36 #include <xsi_imageclip.h> 37 #include <xsi_image.h> 38 39 40 namespace Ogre { 41 42 //------------------------------------------------------------------------- XsiMaterialExporter()43 XsiMaterialExporter::XsiMaterialExporter() 44 { 45 46 } 47 //------------------------------------------------------------------------- ~XsiMaterialExporter()48 XsiMaterialExporter::~XsiMaterialExporter() 49 { 50 clearPassQueue(); 51 } 52 //------------------------------------------------------------------------- exportMaterials(MaterialMap & materials,TextureProjectionMap & texProjMap,const String & filename,bool copyTextures)53 void XsiMaterialExporter::exportMaterials(MaterialMap& materials, 54 TextureProjectionMap& texProjMap, const String& filename, 55 bool copyTextures) 56 { 57 LogOgreAndXSI("** Begin OGRE Material Export **"); 58 59 mTextureProjectionMap = texProjMap; 60 61 String texturePath; 62 if (copyTextures) 63 { 64 // derive the texture path 65 String::size_type pos = filename.find_last_of("\\"); 66 if (pos == String::npos) 67 { 68 pos = filename.find_last_of("/"); 69 } 70 if (pos != String::npos) 71 { 72 texturePath = filename.substr(0, pos + 1); 73 } 74 } 75 76 mMatSerializer.clearQueue(); 77 78 for (MaterialMap::iterator m = materials.begin(); m != materials.end(); ++m) 79 { 80 exportMaterial(m->second, copyTextures, texturePath); 81 } 82 83 mMatSerializer.exportQueued(filename); 84 85 LogOgreAndXSI("** OGRE Material Export Complete **"); 86 } 87 //------------------------------------------------------------------------- exportMaterial(MaterialEntry * matEntry,bool copyTextures,const String & texturePath)88 void XsiMaterialExporter::exportMaterial(MaterialEntry* matEntry, 89 bool copyTextures, const String& texturePath) 90 { 91 LogOgreAndXSI("Exporting " + matEntry->name); 92 93 MaterialPtr mat = MaterialManager::getSingleton().create( 94 matEntry->name, 95 ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); 96 Technique* t = mat->createTechnique(); 97 98 // collect the passes into our queue 99 // XSI stores passes in reverse order, so invert them 100 clearPassQueue(); 101 XSI::Shader shader(matEntry->xsiShader); 102 PassEntry* passEntry = new PassEntry(); 103 mPassQueue.push_front(passEntry); 104 while (1) 105 { 106 passEntry->shaders.Add(shader); 107 108 XSI::CRef source = shader.GetParameter(L"previous").GetSource(); 109 if(!source.IsValid() || !source.IsA(XSI::siShaderID)) 110 { 111 // finish 112 break; 113 } 114 115 shader = XSI::Shader(source); 116 // If we find a 'blending' parameter, we're on a new pass 117 if (shader.GetParameter(L"blending").IsValid()) 118 { 119 passEntry = new PassEntry(); 120 mPassQueue.push_front(passEntry); // push front to invert order 121 } 122 } 123 124 125 // Now go through each pass and create OGRE version 126 for (PassQueue::iterator p = mPassQueue.begin(); p != mPassQueue.end(); ++p) 127 { 128 PassEntry* passEntry = *p; 129 Pass* pass = t->createPass(); 130 LogOgreAndXSI("Added Pass"); 131 132 // Need to pre-populate pass textures to match up transforms 133 populatePassTextures(pass, passEntry, copyTextures, texturePath); 134 // Do the rest 135 for (int s = 0; s < passEntry->shaders.GetCount(); ++s) 136 { 137 XSI::Shader shader(passEntry->shaders[s]); 138 populatePass(pass, shader); 139 } 140 141 } 142 143 144 mMatSerializer.queueForExport(mat); 145 146 147 } 148 //------------------------------------------------------------------------- clearPassQueue(void)149 void XsiMaterialExporter::clearPassQueue(void) 150 { 151 for (PassQueue::iterator i = mPassQueue.begin(); i != mPassQueue.end(); ++i) 152 { 153 delete *i; 154 } 155 mPassQueue.clear(); 156 157 } 158 //------------------------------------------------------------------------- populatePass(Pass * pass,XSI::Shader & xsishader)159 void XsiMaterialExporter::populatePass(Pass* pass, XSI::Shader& xsishader) 160 { 161 populatePassDepthCull(pass, xsishader); 162 populatePassSceneBlend(pass, xsishader); 163 populatePassLighting(pass, xsishader); 164 populatePassTextureTransforms(pass, xsishader); 165 populatePassCgPrograms(pass, xsishader); 166 populatePassHLSLPrograms(pass, xsishader); 167 populatePassD3DAssemblerPrograms(pass, xsishader); 168 } 169 //------------------------------------------------------------------------- populatePassCgPrograms(Pass * pass,XSI::Shader & xsishader)170 void XsiMaterialExporter::populatePassCgPrograms(Pass* pass, 171 XSI::Shader& xsishader) 172 { 173 XSI::Parameter param = xsishader.GetParameter(L"Cg_Program"); 174 if (param.IsValid()) 175 { 176 // TODO 177 // XSI can't reference external files which makes it v.difficult to 178 // re-use shaders - mod XSI plugin? 179 } 180 } 181 //------------------------------------------------------------------------- populatePassHLSLPrograms(Pass * pass,XSI::Shader & xsishader)182 void XsiMaterialExporter::populatePassHLSLPrograms(Pass* pass, 183 XSI::Shader& xsishader) 184 { 185 XSI::Parameter param = xsishader.GetParameter(L"HLSL_Program"); 186 if (param.IsValid()) 187 { 188 // TODO 189 // XSI can't reference external files which makes it v.difficult to 190 // re-use shaders - mod XSI plugin? 191 } 192 } 193 //------------------------------------------------------------------------- populatePassD3DAssemblerPrograms(Pass * pass,XSI::Shader & xsishader)194 void XsiMaterialExporter::populatePassD3DAssemblerPrograms(Pass* pass, 195 XSI::Shader& xsishader) 196 { 197 XSI::Parameter param = xsishader.GetParameter(L"Vertex_Shader"); 198 if (param.IsValid()) 199 { 200 // TODO 201 // XSI can't reference external files which makes it v.difficult to 202 // re-use shaders - mod XSI plugin? 203 } 204 param = xsishader.GetParameter(L"Pixel_Shader"); 205 if (param.IsValid()) 206 { 207 // TODO 208 // XSI can't reference external files which makes it v.difficult to 209 // re-use shaders - mod XSI plugin? 210 } 211 } 212 //------------------------------------------------------------------------- populatePassDepthCull(Pass * pass,XSI::Shader & xsishader)213 void XsiMaterialExporter::populatePassDepthCull(Pass* pass, 214 XSI::Shader& xsishader) 215 { 216 XSI::Parameter param = xsishader.GetParameter(L"cullingmode"); 217 if (param.IsValid()) 218 { 219 short xsiCull = param.GetValue(); 220 switch (xsiCull) 221 { 222 case 0: 223 pass->setCullingMode(CULL_NONE); 224 pass->setManualCullingMode(MANUAL_CULL_NONE); 225 break; 226 case 1: 227 pass->setCullingMode(CULL_CLOCKWISE); 228 pass->setManualCullingMode(MANUAL_CULL_BACK); 229 break; 230 case 2: 231 pass->setCullingMode(CULL_ANTICLOCKWISE); 232 pass->setManualCullingMode(MANUAL_CULL_FRONT); 233 break; 234 235 }; 236 } 237 238 param = xsishader.GetParameter(L"depthtest"); 239 if (param.IsValid()) 240 { 241 bool depthTest = param.GetValue(); 242 pass->setDepthCheckEnabled(depthTest); 243 } 244 param = xsishader.GetParameter(L"depthwrite"); 245 if (param.IsValid()) 246 { 247 bool depthWrite = param.GetValue(); 248 pass->setDepthWriteEnabled(depthWrite); 249 } 250 } 251 //------------------------------------------------------------------------- populatePassSceneBlend(Pass * pass,XSI::Shader & xsishader)252 void XsiMaterialExporter::populatePassSceneBlend(Pass* pass, 253 XSI::Shader& xsishader) 254 { 255 XSI::Parameter param = xsishader.GetParameter(L"blending"); 256 if (param.IsValid() && (bool)param.GetValue()) 257 { 258 SceneBlendFactor src = SBF_ONE; 259 SceneBlendFactor dst = SBF_ONE; 260 261 param = xsishader.GetParameter(L"srcblendingfunction"); 262 if (param.IsValid()) 263 { 264 src = convertSceneBlend(param.GetValue()); 265 } 266 param = xsishader.GetParameter(L"dstblendingfunction"); 267 if (param.IsValid()) 268 { 269 dst = convertSceneBlend(param.GetValue()); 270 } 271 272 pass->setSceneBlending(src, dst); 273 } 274 } 275 //------------------------------------------------------------------------- populatePassLighting(Pass * pass,XSI::Shader & xsishader)276 void XsiMaterialExporter::populatePassLighting(Pass* pass, 277 XSI::Shader& xsishader) 278 { 279 XSI::Parameter param = xsishader.GetParameter(L"Enable_Lighting"); 280 if (param.IsValid()) 281 { 282 pass->setLightingEnabled(param.GetValue()); 283 284 ColourValue tmpColour; 285 xsishader.GetColorParameterValue(L"Ambient", tmpColour.r, tmpColour.g, 286 tmpColour.b, tmpColour.a); 287 pass->setAmbient(tmpColour); 288 xsishader.GetColorParameterValue(L"Diffuse", tmpColour.r, tmpColour.g, 289 tmpColour.b, tmpColour.a); 290 pass->setDiffuse(tmpColour); 291 xsishader.GetColorParameterValue(L"Emissive", tmpColour.r, tmpColour.g, 292 tmpColour.b, tmpColour.a); 293 pass->setSelfIllumination(tmpColour); 294 xsishader.GetColorParameterValue(L"Specular", tmpColour.r, tmpColour.g, 295 tmpColour.b, tmpColour.a); 296 pass->setSpecular(tmpColour); 297 298 pass->setShininess(xsishader.GetParameter(L"Shininess").GetValue()); 299 } 300 301 302 } 303 //------------------------------------------------------------------------- populatePassTextures(Pass * pass,PassEntry * passEntry,bool copyTextures,const String & targetFolder)304 void XsiMaterialExporter::populatePassTextures(Pass* pass, 305 PassEntry* passEntry, bool copyTextures, const String& targetFolder) 306 { 307 // We need to search all shaders back to the point we would change 308 // passes, and add all the textures. This is because we don't know 309 // where in the shaders the texture transforms might be, since they 310 // are linked via 'target' not by being on the same object. 311 mTextureUnitTargetMap.clear(); 312 313 for (int s = 0; s < passEntry->shaders.GetCount(); ++s) 314 { 315 XSI::Shader shader(passEntry->shaders[s]); 316 TextureUnitState* tex = 0; 317 318 String progID = XSItoOgre(shader.GetProgID()); 319 if (progID.find("OGL13Texture") != String::npos || 320 progID.find("DXTexture") != String::npos || 321 progID.find("OGLCom") != String::npos) 322 { 323 if (!shader.GetParameter(L"bottom").IsValid()) 324 { 325 tex = add2DTexture(pass, shader, copyTextures, targetFolder); 326 } 327 else if (shader.GetParameter(L"bottom").IsValid()) 328 { 329 tex = addCubicTexture(pass, shader, copyTextures, targetFolder); 330 } 331 } 332 else 333 { 334 continue; // not a texture so skip the rest 335 } 336 337 338 // texture coordinate set 339 XSI::Parameter param = shader.GetParameter(L"tspace_id"); 340 if (param.IsValid()) 341 { 342 // this is a name, need to look up index 343 tex->setTextureCoordSet( 344 getTextureCoordIndex(XSItoOgre(XSI::CString(param.GetValue())))); 345 } 346 347 // filtering & anisotropy 348 // DX and GL shaders deal differently 349 if (progID.find("OGL") != String::npos) 350 { 351 populateOGLFiltering(tex, shader); 352 } 353 else if (progID.find("DX") != String::npos) 354 { 355 populateDXFiltering(tex, shader); 356 } 357 358 // colour operation 359 param = shader.GetParameter(L"modulation"); 360 if (param.IsValid()) 361 { 362 long colourop = ((LONG)param.GetValue()); 363 switch (colourop) 364 { 365 case 0: 366 // modulate 367 tex->setColourOperation(LBO_MODULATE); 368 break; 369 case 1: 370 // decal 371 tex->setColourOperation(LBO_ALPHA_BLEND); 372 break; 373 case 2: 374 // blend 375 tex->setColourOperation(LBO_MODULATE); 376 break; 377 case 3: 378 // replace 379 tex->setColourOperation(LBO_REPLACE); 380 break; 381 case 4: 382 // add 383 tex->setColourOperation(LBO_ADD); 384 break; 385 } 386 387 } 388 389 390 391 } 392 } 393 //------------------------------------------------------------------------- add2DTexture(Pass * pass,XSI::Shader & shader,bool copyTextures,const String & targetFolder)394 TextureUnitState* XsiMaterialExporter::add2DTexture(Pass* pass, XSI::Shader& shader, 395 bool copyTextures, const String& targetFolder) 396 { 397 // create texture unit state and map from target incase future xforms 398 TextureUnitState* tex = pass->createTextureUnitState(); 399 400 XSI::Parameter param = shader.GetParameter(L"target"); // OGL 401 if (!param.IsValid()) 402 param = shader.GetParameter(L"Texture_Target"); // DX 403 404 long target = ((LONG)param.GetValue()); 405 mTextureUnitTargetMap.insert( 406 TextureUnitTargetMap::value_type(target, tex)); 407 408 // Get image 409 XSI::CRef src = shader.GetParameter(L"Texture").GetSource(); 410 if (!src.IsValid() || !src.IsA(XSI::siImageClipID)) 411 { 412 // Try Texture_1 (OGL Combined) 413 src = shader.GetParameter(L"Texture_1").GetSource(); 414 415 } 416 if (src.IsValid() && src.IsA(XSI::siImageClipID)) 417 { 418 XSI::ImageClip imgClip(src); 419 String srcTextureName = 420 XSItoOgre(XSI::CString(imgClip.GetParameter(L"SourceFileName").GetValue())); 421 422 String::size_type pos = srcTextureName.find_last_of("\\"); 423 if (pos == String::npos) 424 { 425 pos = srcTextureName.find_last_of("/"); 426 } 427 String textureName = 428 srcTextureName.substr(pos+1, srcTextureName.size() - pos - 1); 429 String destTextureName = targetFolder + textureName; 430 431 // copy texture if required 432 if (copyTextures) 433 { 434 copyFile(srcTextureName, destTextureName); 435 } 436 437 LogOgreAndXSI("Adding texture " + textureName); 438 tex->setTextureName(textureName); 439 440 } 441 442 return tex; 443 } 444 //------------------------------------------------------------------------- populateOGLFiltering(TextureUnitState * tex,XSI::Shader & shader)445 void XsiMaterialExporter::populateOGLFiltering(TextureUnitState* tex, 446 XSI::Shader& shader) 447 { 448 FilterOptions minFilter, mipFilter, magFilter; 449 minFilter = FO_LINEAR; 450 magFilter = FO_LINEAR; 451 mipFilter = FO_POINT; 452 XSI::Parameter param = shader.GetParameter(L"minfilter"); 453 if (param.IsValid()) 454 { 455 // XSI OGL shader uses minfilter to determine mip too 456 long filt = ((LONG)param.GetValue()); 457 switch(filt) 458 { 459 case 0: 460 minFilter = FO_POINT; 461 mipFilter = FO_NONE; 462 break; 463 case 1: 464 minFilter = FO_LINEAR; 465 mipFilter = FO_NONE; 466 break; 467 case 2: 468 minFilter = FO_POINT; 469 mipFilter = FO_POINT; 470 break; 471 case 3: 472 minFilter = FO_POINT; 473 mipFilter = FO_LINEAR; 474 break; 475 case 4: 476 minFilter = FO_LINEAR; 477 mipFilter = FO_POINT; 478 break; 479 case 5: 480 minFilter = FO_LINEAR; 481 mipFilter = FO_LINEAR; 482 break; 483 }; 484 485 } 486 param = shader.GetParameter(L"magfilter"); 487 if (param.IsValid()) 488 { 489 long filt = ((LONG)param.GetValue()); 490 switch(filt) 491 { 492 case 0: 493 magFilter = FO_POINT; 494 break; 495 case 1: 496 magFilter = FO_LINEAR; 497 break; 498 }; 499 } 500 501 param = shader.GetParameter(L"anisotropy"); 502 if (param.IsValid()) 503 { 504 long aniso = ((LONG)param.GetValue()); 505 if (aniso > 1) 506 { 507 // No specific aniso filtering option, so upgrade linear -> aniso 508 if (minFilter == FO_LINEAR) 509 minFilter = FO_ANISOTROPIC; 510 if (magFilter == FO_LINEAR) 511 magFilter = FO_ANISOTROPIC; 512 } 513 tex->setTextureAnisotropy(aniso); 514 } 515 516 tex->setTextureFiltering(minFilter, magFilter, mipFilter); 517 } 518 //------------------------------------------------------------------------- populateDXFiltering(TextureUnitState * tex,XSI::Shader & shader)519 void XsiMaterialExporter::populateDXFiltering(TextureUnitState* tex, 520 XSI::Shader& shader) 521 { 522 FilterOptions minFilter, mipFilter, magFilter; 523 minFilter = FO_LINEAR; 524 magFilter = FO_LINEAR; 525 mipFilter = FO_POINT; 526 XSI::Parameter param = shader.GetParameter(L"minfilter"); 527 if (param.IsValid()) 528 { 529 // XSI DX shader has min/mag and mip, and has more options 530 long filt = ((LONG)param.GetValue()); 531 switch(filt) 532 { 533 case 0: 534 minFilter = FO_NONE; 535 break; 536 case 1: 537 minFilter = FO_POINT; 538 break; 539 case 2: 540 minFilter = FO_LINEAR; 541 break; 542 case 3: 543 case 4: // we don't support cubic/gaussian, use aniso 544 case 5: 545 minFilter = FO_ANISOTROPIC; 546 break; 547 }; 548 } 549 param = shader.GetParameter(L"magfilter"); 550 if (param.IsValid()) 551 { 552 // XSI DX shader has mag/mag and mip, and has more options 553 long filt = ((LONG)param.GetValue()); 554 switch(filt) 555 { 556 case 0: 557 magFilter = FO_NONE; 558 break; 559 case 1: 560 magFilter = FO_POINT; 561 break; 562 case 2: 563 magFilter = FO_LINEAR; 564 break; 565 case 3: 566 case 4: // we don't support cubic/gaussian, use aniso 567 case 5: 568 magFilter = FO_ANISOTROPIC; 569 break; 570 }; 571 } 572 param = shader.GetParameter(L"mipfilter"); 573 if (param.IsValid()) 574 { 575 // XSI DX shader has mip/mag and mip, and has more options 576 long filt = ((LONG)param.GetValue()); 577 switch(filt) 578 { 579 case 0: 580 mipFilter = FO_NONE; 581 break; 582 case 1: 583 mipFilter = FO_POINT; 584 break; 585 case 2: 586 mipFilter = FO_LINEAR; 587 break; 588 case 3: 589 case 4: // we don't support cubic/gaussian, use aniso 590 case 5: 591 mipFilter = FO_ANISOTROPIC; 592 break; 593 }; 594 } 595 // Aniso 596 param = shader.GetParameter(L"anisotropy"); 597 if (param.IsValid()) 598 { 599 long aniso = ((LONG)param.GetValue()); 600 tex->setTextureAnisotropy(aniso); 601 } 602 603 tex->setTextureFiltering(minFilter, magFilter, mipFilter); 604 } 605 //------------------------------------------------------------------------- addCubicTexture(Pass * pass,XSI::Shader & shader,bool copyTextures,const String & targetFolder)606 TextureUnitState* XsiMaterialExporter::addCubicTexture(Pass* pass, XSI::Shader& shader, 607 bool copyTextures, const String& targetFolder) 608 { 609 // create texture unit state and map from target incase future xforms 610 TextureUnitState* tex = pass->createTextureUnitState(); 611 612 XSI::Parameter param = shader.GetParameter(L"target"); // OGL 613 if (!param.IsValid()) 614 param = shader.GetParameter(L"Texture_Target"); // DX 615 616 long target = ((LONG)param.GetValue()); 617 mTextureUnitTargetMap.insert( 618 TextureUnitTargetMap::value_type(target, tex)); 619 620 // Get images 621 wchar_t* cubeFaceName[6] = { 622 L"front", L"back", L"top", L"bottom", L"left", L"right" }; 623 624 String finalNames[6]; 625 626 627 for (int face = 0; face < 6; ++face) 628 { 629 XSI::CRef src = shader.GetParameter(cubeFaceName[face]).GetSource(); 630 if (src.IsValid() && src.IsA(XSI::siImageClipID)) 631 { 632 XSI::ImageClip imgClip(src); 633 String srcTextureName = 634 XSItoOgre(XSI::CString(imgClip.GetParameter(L"SourceFileName").GetValue())); 635 636 String::size_type pos = srcTextureName.find_last_of("\\"); 637 if (pos == String::npos) 638 { 639 pos = srcTextureName.find_last_of("/"); 640 } 641 finalNames[face] = 642 srcTextureName.substr(pos+1, srcTextureName.size() - pos - 1); 643 String destTextureName = targetFolder + finalNames[face]; 644 645 // copy texture if required 646 if (copyTextures) 647 { 648 copyFile(srcTextureName, destTextureName); 649 } 650 651 652 LogOgreAndXSI("Cubemap face: " + srcTextureName); 653 } 654 } 655 656 LogOgreAndXSI("Adding cubic texture"); 657 // Cannot do combinedUVW for now, DevIL can't write DDS cubemap so 658 // go for separates (user can modify) 659 tex->setCubicTextureName(finalNames, false); 660 661 return tex; 662 663 } 664 //------------------------------------------------------------------------- getTextureCoordIndex(const String & tspace)665 unsigned short XsiMaterialExporter::getTextureCoordIndex(const String& tspace) 666 { 667 TextureProjectionMap::iterator i = mTextureProjectionMap.find(tspace); 668 if (i != mTextureProjectionMap.end()) 669 { 670 return i->second; 671 } 672 else 673 { 674 // default 675 return 0; 676 } 677 } 678 //------------------------------------------------------------------------- populatePassTextureTransforms(Pass * pass,XSI::Shader & shader)679 void XsiMaterialExporter::populatePassTextureTransforms(Pass* pass, 680 XSI::Shader& shader) 681 { 682 // TODO 683 // Check we have the right object 684 XSI::Parameter param = shader.GetParameter(L"wrap_u"); 685 if (param.IsValid()) 686 { 687 688 // addressing mode 689 Sampler::UVWAddressingMode uvwadd; 690 uvwadd.u = convertAddressingMode(param.GetValue()); 691 // default other dimensions incase not supplied 692 uvwadd.v = uvwadd.u; 693 uvwadd.w = uvwadd.u; 694 695 param = shader.GetParameter(L"wrap_v"); 696 if (param.IsValid()) 697 { 698 uvwadd.v = convertAddressingMode(param.GetValue()); 699 } 700 param = shader.GetParameter(L"wrap_w"); 701 if (param.IsValid()) 702 { 703 uvwadd.w = convertAddressingMode(param.GetValue()); 704 } 705 706 // transform 707 bool usexform = false; 708 Matrix4 xform = Matrix4::IDENTITY; 709 param = shader.GetParameter(L"Transform"); 710 if (param.IsValid() && (bool)param.GetValue()) 711 { 712 Quaternion qx, qy, qz, qfinal; 713 qx.FromAngleAxis(Degree(shader.GetParameter(L"rotx").GetValue()), 714 Vector3::UNIT_X); 715 qy.FromAngleAxis(Degree(shader.GetParameter(L"roty").GetValue()), 716 Vector3::UNIT_Y); 717 qz.FromAngleAxis(Degree(shader.GetParameter(L"rotz").GetValue()), 718 Vector3::UNIT_Z); 719 qfinal = qx * qy * qz; 720 721 Vector3 trans; 722 trans.x = shader.GetParameter(L"trsx").GetValue(); 723 trans.y = shader.GetParameter(L"trsy").GetValue(); 724 trans.z = shader.GetParameter(L"trsz").GetValue(); 725 726 Matrix3 rot3x3, scale3x3; 727 qfinal.ToRotationMatrix(rot3x3); 728 scale3x3 = Matrix3::ZERO; 729 scale3x3[0][0] = shader.GetParameter(L"sclx").GetValue(); 730 scale3x3[1][1] = shader.GetParameter(L"scly").GetValue(); 731 scale3x3[2][2] = shader.GetParameter(L"sclz").GetValue(); 732 733 xform = rot3x3 * scale3x3; 734 xform.setTrans(trans); 735 usexform = true; 736 737 } 738 739 740 // Look up texture unit(s) that are using this target 741 long target = ((LONG)shader.GetParameter(L"Texture_Target").GetValue()); 742 TextureUnitTargetMap::iterator i = mTextureUnitTargetMap.find(target); 743 while (i != mTextureUnitTargetMap.end() && i->first == target) 744 { 745 TextureUnitState* tex = i->second; 746 tex->setTextureAddressingMode(uvwadd); 747 if (usexform) 748 tex->setTextureTransform(xform); 749 750 // texgen (not texcoord_index as in OGRE!) 751 // Can turn into 2 different calls 752 param = shader.GetParameter(L"texcoord_index"); 753 if (param.IsValid()) 754 { 755 long e = ((LONG)param.GetValue()); 756 if (e != 0) 757 { 758 // Not Explicit 759 // details differ per DX/OGL 760 if (XSItoOgre(shader.GetProgID()).find("DX") != String::npos) 761 { 762 convertTexGenDX(tex, e, shader); 763 } 764 else 765 { 766 convertTexGenOGL(tex, e, shader); 767 } 768 769 } 770 771 } 772 ++i; 773 } 774 775 776 777 778 } 779 param = shader.GetParameter(L"Additive_Transform"); 780 if (param.IsValid()) 781 { 782 unsigned short target = shader.GetParameter(L"Texture_Coord_ID").GetValue(); 783 if (pass->getNumTextureUnitStates() > target) 784 { 785 TextureUnitState* tex = pass->getTextureUnitState(target); 786 787 long uvType = ((LONG)shader.GetParameter(L"UV_Type").GetValue()); 788 if (uvType != 0) 789 { 790 double val1 = shader.GetParameter(L"Val1").GetValue(); 791 double val2 = shader.GetParameter(L"Val2").GetValue(); 792 long wave = ((LONG)shader.GetParameter(L"Wave").GetValue()); 793 WaveformType wft; 794 switch (wave) 795 { 796 case 1: 797 wft = WFT_SINE; 798 break; 799 case 2: 800 wft = WFT_TRIANGLE; 801 break; 802 case 3: 803 wft = WFT_SQUARE; 804 break; 805 case 4: 806 wft = WFT_SAWTOOTH; 807 break; 808 case 5: 809 wft = WFT_INVERSE_SAWTOOTH; 810 break; 811 } 812 double base = shader.GetParameter(L"Base").GetValue(); 813 double amp = shader.GetParameter(L"Amplitude").GetValue(); 814 double phase = shader.GetParameter(L"Phase").GetValue(); 815 double freq = shader.GetParameter(L"Frequency").GetValue(); 816 817 switch(uvType) 818 { 819 case 1: 820 // translate 821 tex->setTextureScroll(val1, val2); 822 break; 823 case 2: 824 // rotate 825 tex->setTextureRotate(Degree(val1)); 826 break; 827 case 3: 828 // scale 829 tex->setTextureScale(val1, val2); 830 break; 831 case 4: 832 // scroll 833 if (wave != 0) 834 { 835 tex->setTransformAnimation(TextureUnitState::TT_TRANSLATE_U, 836 wft, base, freq, phase, amp); 837 tex->setTransformAnimation(TextureUnitState::TT_TRANSLATE_V, 838 wft, base, freq, phase, amp); 839 } 840 else 841 { 842 tex->setScrollAnimation(val1, val2); 843 } 844 break; 845 case 5: 846 // turn 847 if (wave != 0) 848 { 849 tex->setTransformAnimation(TextureUnitState::TT_ROTATE, 850 wft, base, freq, phase, amp); 851 } 852 else 853 { 854 tex->setRotateAnimation(val1 / 360.0f); 855 } 856 break; 857 case 6: 858 // stretch (only wave) 859 if (wave != 0) 860 { 861 tex->setTransformAnimation(TextureUnitState::TT_SCALE_U, 862 wft, base, freq, phase, amp); 863 tex->setTransformAnimation(TextureUnitState::TT_SCALE_V, 864 wft, base, freq, phase, amp); 865 } 866 break; 867 868 } 869 } 870 } 871 872 } 873 874 // if more than one entry for the same target is found, it is ok for the 875 // latter to take precedence since this is what happens in XSI. 876 877 } 878 //------------------------------------------------------------------------- convertTexGenOGL(TextureUnitState * tex,long xsiVal,XSI::Shader & shader)879 void XsiMaterialExporter::convertTexGenOGL(TextureUnitState* tex, 880 long xsiVal, XSI::Shader& shader) 881 { 882 switch(xsiVal) 883 { 884 // no 0 885 case 1: 886 // Object linear 887 tex->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR); 888 break; 889 case 2: 890 // Eye linear (texture projection) 891 tex->setProjectiveTexturing(true); 892 break; 893 case 3: 894 // Sphere map 895 tex->setEnvironmentMap(true, TextureUnitState::ENV_CURVED); 896 break; 897 case 4: 898 // Reflection map 899 tex->setEnvironmentMap(true, TextureUnitState::ENV_REFLECTION); 900 break; 901 case 5: 902 // Normal map 903 tex->setEnvironmentMap(true, TextureUnitState::ENV_NORMAL); 904 break; 905 906 }; 907 } 908 //------------------------------------------------------------------------- convertTexGenDX(TextureUnitState * tex,long xsiVal,XSI::Shader & shader)909 void XsiMaterialExporter::convertTexGenDX(TextureUnitState* tex, 910 long xsiVal, XSI::Shader& shader) 911 { 912 switch(xsiVal) 913 { 914 // no 0 915 case 1: 916 // Normal in camera space 917 tex->setEnvironmentMap(true, TextureUnitState::ENV_CURVED); 918 break; 919 case 2: 920 // Position in camera space 921 tex->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR); 922 break; 923 case 3: 924 // Reflection vector in camera space 925 tex->setEnvironmentMap(true, TextureUnitState::ENV_REFLECTION); 926 break; 927 928 }; 929 } 930 //------------------------------------------------------------------------- 931 TextureAddressingMode convertAddressingMode(short xsiVal)932 XsiMaterialExporter::convertAddressingMode(short xsiVal) 933 { 934 // same for OGL and DX 935 switch(xsiVal) 936 { 937 case 0: 938 return TextureUnitState::TAM_WRAP; 939 case 1: 940 return TextureUnitState::TAM_MIRROR; 941 case 2: 942 return TextureUnitState::TAM_CLAMP; 943 case 3: 944 // border? 945 return TextureUnitState::TAM_CLAMP; 946 case 4: 947 // mirror once 948 return TextureUnitState::TAM_MIRROR; 949 case 5: 950 // clamp to edge 951 return TextureUnitState::TAM_CLAMP; 952 953 }; 954 955 // Keep compiler happy 956 return TextureUnitState::TAM_WRAP; 957 } 958 //------------------------------------------------------------------------- convertSceneBlend(short xsiVal)959 SceneBlendFactor XsiMaterialExporter::convertSceneBlend(short xsiVal) 960 { 961 switch(xsiVal) 962 { 963 case 0: 964 return SBF_ZERO; 965 case 1: 966 return SBF_ONE; 967 case 2: 968 return SBF_DEST_COLOUR; 969 case 3: 970 return SBF_ONE_MINUS_DEST_COLOUR; 971 case 4: 972 return SBF_SOURCE_ALPHA; 973 case 5: 974 return SBF_ONE_MINUS_SOURCE_ALPHA; 975 case 6: 976 return SBF_DEST_ALPHA; 977 case 7: 978 return SBF_ONE_MINUS_DEST_ALPHA; 979 }; 980 981 return SBF_ZERO; 982 983 } 984 985 } 986 987