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