~ubuntu-branches/ubuntu/wily/opencollada/wily

« back to all changes in this revision

Viewing changes to COLLADAMax/src/COLLADAMaxEffectExporter.cpp

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (c) 2008-2009 NetAllied Systems GmbH
 
3
 
 
4
        This file is part of COLLADAMax.
 
5
 
 
6
    Portions of the code are:
 
7
    Copyright (c) 2005-2007 Feeling Software Inc.
 
8
    Copyright (c) 2005-2007 Sony Computer Entertainment America
 
9
    
 
10
    Based on the 3dsMax COLLADASW Tools:
 
11
    Copyright (c) 2005-2006 Autodesk Media Entertainment
 
12
        
 
13
    Licensed under the MIT Open Source License, 
 
14
    for details please see LICENSE file or the website
 
15
    http://www.opensource.org/licenses/mit-license.php
 
16
*/
 
17
 
 
18
 
 
19
#include "COLLADAMaxStableHeaders.h"
 
20
 
 
21
#include "COLLADAMaxEffectExporter.h"
 
22
 
 
23
#include "COLLADAMaxExportSceneGraph.h"
 
24
#include "COLLADAMaxMultiMtl.h"
 
25
#include "COLLADAMaxAnimationExporter.h"
 
26
#include "COLLADAMaxConversionFunctor.h"
 
27
#include "COLLADAMaxHwShaderExporter.h"
 
28
 
 
29
#include "COLLADAMaxXRefFunctions.h"
 
30
 
 
31
#include "COLLADASWNode.h"
 
32
//#include "COLLADASWTextureModifier.h"
 
33
 
 
34
#include <algorithm>
 
35
 
 
36
#include <IDxMaterial.h>
 
37
#include <iparamb2.h>
 
38
#include <iparamm2.h>
 
39
#include <stdmat.h>
 
40
#include <shaders.h>
 
41
#include <imtl.h> 
 
42
 
 
43
namespace COLLADAMax
 
44
{
 
45
 
 
46
 
 
47
    const String EffectExporter::COLOR_EFFECT_ID_PREFIX = "ColorEffect";
 
48
    const String EffectExporter::TEXCOORD_BASE = "CHANNEL";
 
49
 
 
50
    const String EffectExporter::DAE_AMBIENT_TEXTURE_CHANNEL = "AMBIENT";
 
51
    const String EffectExporter::DAE_BUMP_TEXTURE_CHANNEL = "BUMP";
 
52
    const String EffectExporter::DAE_DIFFUSE_TEXTURE_CHANNEL = "DIFFUSE";
 
53
    const String EffectExporter::DAE_DISPLACEMENT_TEXTURE_CHANNEL = "DISPLACEMENT";
 
54
    const String EffectExporter::DAE_EMISSION_TEXTURE_CHANNEL = "GLOW";
 
55
    const String EffectExporter::DAE_FILTER_TEXTURE_CHANNEL = "FILTER";
 
56
    //#defineDAE_OPACITY_TEXTURE_CHANNEL = "OPACITY";
 
57
    const String EffectExporter::DAE_REFLECTION_TEXTURE_CHANNEL = "REFLECTION";
 
58
    const String EffectExporter::DAE_REFRACTION_TEXTURE_CHANNEL = "REFRACTION";
 
59
    const String EffectExporter::DAE_SHININESS_TEXTURE_CHANNEL = "SHININESS";
 
60
    const String EffectExporter::DAE_SPECULAR_TEXTURE_CHANNEL = "SPECULAR";
 
61
    const String EffectExporter::DAE_SPECULARLEVEL_TEXTURE_CHANNEL = "SPECULAR-LEVEL";
 
62
    const String EffectExporter::DAE_TRANSPARENT_TEXTURE_CHANNEL = "TRANSPARENT";
 
63
 
 
64
        const String EffectExporter::DAE_BUMP_TYPE_ATTRIBUTE = "bumptype";
 
65
        const String EffectExporter::DAE_BUMP_TYPE_NORMALMAP = "NORMALMAP";
 
66
        const String EffectExporter::DAE_BUMP_TYPE_HEIGHTFIELD = "HEIGHTFIELD";
 
67
 
 
68
    const String EffectExporter::EMPTY_STRING = "";
 
69
 
 
70
        const String EffectExporter::SELF_ILLUMINATION_PARAMETER = "self_illumination";
 
71
 
 
72
        const String EffectExporter::COLOR_PARAMETERS[ 4 ] =
 
73
        {"R", "G", "B", "A"
 
74
        };
 
75
 
 
76
        const String EffectExporter::SHADER_ELEMENT = "shader";
 
77
        const int EffectExporter::SHADER_PARAMETER_COUNT = 7;
 
78
        const Extra::ExtraParameter EffectExporter::SHADER_PARAMETERS[] =
 
79
        {
 
80
                {TYPE_BOOL, 3, "ambient_diffuse_texture_lock"},
 
81
                {TYPE_BOOL, 4, "ambient_diffuse_lock"},
 
82
                {TYPE_BOOL, 5, "diffuse_specular_lock"},
 
83
                {TYPE_BOOL, 6, "use_self_illum_color"},
 
84
                {TYPE_PCNT_FRAC, 7, "self_illumination"},
 
85
                {TYPE_PCNT_FRAC, 9, "specular_level"},
 
86
                {TYPE_FLOAT, 11, "soften"}
 
87
        };
 
88
 
 
89
 
 
90
        const String EffectExporter::EXTENDED_SHADER_ELEMENT = "extended_shader";
 
91
        const int EffectExporter::EXTENDED_SHADER_PARAMETER_COUNT = 11;
 
92
        const Extra::ExtraParameter EffectExporter::EXTENDED_SHADER_PARAMETERS[] =
 
93
        {
 
94
                {TYPE_INT, 0, "opacity_type"},
 
95
                {TYPE_RGBA, 2, "filter_color"},
 
96
                {TYPE_TEXMAP, 3, "filtert_map"},
 
97
                {TYPE_INT, 4, "falloff_type"},
 
98
                {TYPE_PCNT_FRAC, 5, "falloff"},
 
99
                {TYPE_FLOAT, 6, "index_of_refraction"},
 
100
                {TYPE_FLOAT, 7, "wire_size"},
 
101
                {TYPE_INT, 8, "wire_units"},
 
102
                {TYPE_BOOL, 9, "apply_reflection_dimming"},
 
103
                {TYPE_FLOAT, 10, "dim_level"},
 
104
                {TYPE_FLOAT, 11, "reflection_level"}
 
105
        };
 
106
 
 
107
 
 
108
 
 
109
        //---------------------------------------------------------------
 
110
        String EffectExporter::createTexcoordSementicFromMapchannel( int mapChannel )
 
111
        {
 
112
                return TEXCOORD_BASE + COLLADASW::Utils::toString ( mapChannel );
 
113
        }
 
114
 
 
115
    //---------------------------------------------------------------
 
116
    EffectExporter::EffectExporter ( COLLADASW::StreamWriter * streamWriter, ExportSceneGraph * exportSceneGraph, DocumentExporter * documentExporter )
 
117
            : COLLADASW::LibraryEffects ( streamWriter )
 
118
            , Extra(streamWriter, documentExporter)
 
119
            , mExportSceneGraph ( exportSceneGraph )
 
120
            , mDocumentExporter ( documentExporter )
 
121
            , mTextureExporter ( documentExporter )
 
122
            , mAnimationExporter( documentExporter->getAnimationExporter() )
 
123
            , mImageIdList()
 
124
            , mCopyImageCounter( 0 )
 
125
    {}
 
126
 
 
127
    //---------------------------------------------------------------
 
128
    void EffectExporter::doExport()
 
129
    {
 
130
        mExportedEffectIdList = & ( mDocumentExporter->getMaterialExporter() ->getEffectIdList() );
 
131
 
 
132
        exportEffect ( mExportSceneGraph->getRootExportNode() );
 
133
        closeLibrary();
 
134
    }
 
135
 
 
136
    //---------------------------------------------------------------
 
137
    void EffectExporter::exportEffect ( ExportNode* exportNode )
 
138
    {
 
139
                if ( !exportNode->getIsInVisualScene() && !exportNode->getIsReferenced() )
 
140
                        return;
 
141
 
 
142
        INode * iNode = exportNode->getINode();
 
143
        Mtl * material = iNode->GetMtl();
 
144
 
 
145
        // If the node has material export it. If not, export the wire color.
 
146
 
 
147
        if ( material )
 
148
        {
 
149
            exportEffect ( exportNode, material );
 
150
        }
 
151
 
 
152
        else 
 
153
        {
 
154
                        // export wire frame material only for meshes
 
155
                        if ( exportNode->getType() == ExportNode::MESH )
 
156
                        {
 
157
                                exportColorEffect ( exportNode, iNode->GetWireColor() );
 
158
                        }
 
159
        }
 
160
 
 
161
        //export the child nodes materials
 
162
        size_t numberOfChildren = exportNode->getNumberOfChildren();
 
163
 
 
164
        for ( size_t i = 0; i < numberOfChildren; ++i )
 
165
            exportEffect ( exportNode->getChild ( i ) );
 
166
    }
 
167
 
 
168
    //---------------------------------------------------------------
 
169
    void EffectExporter::exportEffect ( ExportNode* exportNode, Mtl* material )
 
170
    {
 
171
 
 
172
                // check for XRefs
 
173
                if (XRefFunctions::isXRefMaterial(material))
 
174
                {
 
175
                        if ( mDocumentExporter->getOptions().getIncludeXRefs() )
 
176
                        {
 
177
                                // we don't export XRef materials, but remember them for later use
 
178
                                material = XRefFunctions::getXRefMaterialSource(material);
 
179
                        }
 
180
                        else
 
181
                        {
 
182
                                assert(false);
 
183
//                              xRefedMaterialList.push_back(mat);
 
184
                                return;
 
185
                        }
 
186
                }
 
187
 
 
188
 
 
189
        if ( material->IsMultiMtl() )
 
190
        {
 
191
            // This material type is used for meshes with multiple materials:
 
192
            // only export the individual materials.
 
193
 
 
194
            for ( int j = 0; j < material->NumSubMtls(); j++ )
 
195
            {
 
196
                Mtl* submat = material->GetSubMtl ( j );
 
197
 
 
198
                if ( submat )
 
199
                    exportEffect ( exportNode, submat );
 
200
            }
 
201
        }
 
202
 
 
203
        else
 
204
        {
 
205
            // add <material> node for this material to the library
 
206
            exportSimpleEffect ( exportNode, material );
 
207
        }
 
208
    }
 
209
 
 
210
    //---------------------------------------------------------------
 
211
    void EffectExporter::exportSimpleEffect ( ExportNode* exportNode, Mtl* baseMaterial )
 
212
    {
 
213
        // check if this is not an XRef
 
214
 
 
215
        if ( XRefFunctions::isXRefMaterial ( baseMaterial ) )
 
216
        {
 
217
            if ( mDocumentExporter->getOptions().getIncludeXRefs() )
 
218
            {
 
219
                // don't generate the FCDMaterial
 
220
                                baseMaterial = XRefFunctions::getXRefMaterialSource( baseMaterial );
 
221
            }
 
222
 
 
223
            else
 
224
            {
 
225
                                return ;
 
226
            }
 
227
        }
 
228
 
 
229
 
 
230
        EffectMap::iterator it = mEffectMap.find ( baseMaterial );
 
231
 
 
232
        if ( it != mEffectMap.end() )
 
233
        {
 
234
            exportNode->addSymbol ( baseMaterial, it->second );
 
235
            return ;
 
236
        }
 
237
 
 
238
 
 
239
                String materialName = NativeString(baseMaterial->GetName().data());
 
240
        // Add it to the exported materials list
 
241
        String effectId = mEffectIdList.addId ( materialName );
 
242
 
 
243
        exportNode->addSymbol ( baseMaterial, effectId );
 
244
 
 
245
        mEffectMap[ baseMaterial ] = effectId;
 
246
 
 
247
        mExportedEffectIdList->push_back ( EffectIdAndName(effectId, materialName) );
 
248
 
 
249
        openEffect ( effectId );
 
250
 
 
251
                setExtraTechnique(this);
 
252
 
 
253
                //COLLADASW::EffectProfile effectCommonProfile ( LibraryEffects::mSW );
 
254
 
 
255
 
 
256
        // Write out the custom attributes
 
257
        //  ExportCustomAttributes(baseMaterial, material);
 
258
 
 
259
        /// @TODO Handle other types of material properly
 
260
        // does the material have an HLSL profile?
 
261
        //bool itHasHardwareShader = false;
 
262
        IDxMaterial* dxm = static_cast<IDxMaterial*> ( baseMaterial->GetInterface( IDXMATERIAL_INTERFACE ) );
 
263
 
 
264
#ifdef MAX_2010_OR_NEWER
 
265
 #ifdef UNICODE
 
266
        std::string effectFileNameString;
 
267
        const char* effectFileName = NULL;
 
268
 
 
269
        if (dxm)
 
270
        {
 
271
            COLLADABU::StringUtils::wideString2utf8String(dxm->GetEffectFile().GetFileName().data());
 
272
                    effectFileName = effectFileNameString.c_str();
 
273
        }
 
274
 #else
 
275
                const char* effectFileName = dxm ? dxm->GetEffectFile().GetFileName().data() : 0;
 
276
 #endif
 
277
#else
 
278
                const char* effectFileName = dxm ? dxm->GetEffectFilename() : 0;
 
279
#endif
 
280
 
 
281
        if ( effectFileName && *effectFileName )
 
282
        {
 
283
            /*
 
284
            if ( baseMaterial->NumSubMtls() > 0 && baseMaterial->GetSubMtl( 0 ) )
 
285
            {
 
286
                // Create common profile
 
287
                Mtl * workingMaterial = baseMaterial->GetSubMtl ( 0 );
 
288
                //   ExportCustomAttributes(workingMaterial, material);
 
289
                //    exportCommonEffect((FCDEffectStandard*)matEffect->AddProfile(FUDaeProfileType::COMMON), workingMaterial);
 
290
                exportCommonEffect ( effectCommonProfile, exportNode, workingMaterial, effectId );
 
291
            }
 
292
            */
 
293
 
 
294
            // Create HLSL profile and add the effect instantiation elements
 
295
            COLLADASW::EffectProfile effectHLSLProfile ( LibraryEffects::mSW );
 
296
 
 
297
            COLLADASW::URI  shaderFxFileUri ( COLLADASW::URI::nativePathToUri ( effectFileName ) );
 
298
            effectHLSLProfile.setInclude ( shaderFxFileUri, shaderFxFileUri.getPathFileBase() );
 
299
            exportHLSLEffect ( effectHLSLProfile, exportNode, baseMaterial, effectId );
 
300
            //itHasHardwareShader = true;
 
301
        }
 
302
 
 
303
        //  else if (baseMaterial->ClassID() == COLLADASW_EFFECT_ID)
 
304
        //  {
 
305
        //   exportColladaEffect(material, (ColladaEffect*)baseMaterial);
 
306
        //  }
 
307
 
 
308
        else
 
309
        {
 
310
            // Create common profile
 
311
            COLLADASW::EffectProfile effectCommonProfile ( LibraryEffects::mSW );
 
312
            exportCommonEffect ( effectCommonProfile, exportNode, baseMaterial, effectId );
 
313
            addEffectProfile ( effectCommonProfile );
 
314
 
 
315
        }
 
316
 
 
317
        //addEffectProfile ( effectCommonProfile );
 
318
        
 
319
        //if ( itHasHardwareShader )
 
320
        //{
 
321
        //    effectHLSLProfile.openProfile ();
 
322
        //    effectHLSLProfile.addProfileElements ();
 
323
 
 
324
        //    exportEffectParameters ( shaderNode, cgEffect );
 
325
 
 
326
        //    // Find if effect parameter is used by any program of the selected technique
 
327
        //    CGtechnique cgTechnique = cgGetFirstTechnique ( cgEffect );
 
328
        //    while ( cgTechnique )
 
329
        //    {
 
330
        //        exportTechnique ( cgTechnique );
 
331
        //        cgTechnique = cgGetNextTechnique ( cgTechnique );
 
332
        //    }
 
333
 
 
334
        //    effectHLSLProfile.closeProfile ();
 
335
        //}
 
336
 
 
337
                addExtraTechniques(ElementWriter::mSW);
 
338
 
 
339
        closeEffect();
 
340
 
 
341
    }
 
342
 
 
343
    //---------------------------------------------------------------
 
344
    void EffectExporter::exportCommonEffect ( COLLADASW::EffectProfile & effectProfile, ExportNode* exportNode, Mtl* material, const String & effectId, float weight, bool inited )
 
345
    {
 
346
        // Export all submaterials first.
 
347
        int subMaterialCount = material->NumSubMtls();
 
348
 
 
349
        for ( int i = 0; i < subMaterialCount; ++i )
 
350
        {
 
351
            Mtl* subMaterial = material->GetSubMtl ( i );
 
352
            float subMtlWeight = weight;
 
353
 
 
354
            if ( material->ClassID() == CompositeMtl::classID )
 
355
            {
 
356
                IParamBlock2 * pblock = material->GetParamBlock ( 0 );
 
357
 
 
358
                if ( pblock != NULL )
 
359
                {
 
360
                    if ( !pblock->GetInt ( CompositeMtl::compmat_map_on ) )
 
361
                        subMtlWeight = 0;
 
362
                    else
 
363
                        subMtlWeight *= pblock->GetFloat ( CompositeMtl::compmat_amount ) / 100.0f;
 
364
                }
 
365
            }
 
366
 
 
367
            if ( subMaterial != NULL )
 
368
            {
 
369
                exportCommonEffect ( effectProfile, exportNode, subMaterial, effectId, subMtlWeight, inited );
 
370
                inited = true;
 
371
            }
 
372
        }
 
373
 
 
374
        Class_ID materialId = material->ClassID();
 
375
 
 
376
        if ( materialId.PartA() == DMTL2_CLASS_ID || materialId.PartA() == DMTL_CLASS_ID )
 
377
        {
 
378
            exportStandardEffect ( effectProfile, exportNode, ( StdMat2* ) material, effectId, weight, inited );
 
379
        }
 
380
 
 
381
        else
 
382
        {
 
383
            // This must be some strange 'RayTrace' or render-only material
 
384
            // Export whatever information we can from the Max material interface
 
385
            exportUnknownEffect ( effectProfile, exportNode, material, effectId );
 
386
        }
 
387
    }
 
388
 
 
389
    //---------------------------------------------------------------
 
390
    void logEffectParameters ( 
 
391
        Mtl* material 
 
392
        )
 
393
    {
 
394
        int numParamBlocks = material->NumParamBlocks();
 
395
 
 
396
        for ( int i = 0; i < numParamBlocks; i++ )
 
397
        {
 
398
            IParamBlock2 * pblock = material->GetParamBlock ( i );
 
399
            int parameterCount = pblock->NumParams();
 
400
 
 
401
            fprintf( stdout, "Param block = %i;\n", i );
 
402
 
 
403
            for ( int j = 0; j < parameterCount; j++ )
 
404
            {
 
405
                ParamID parameterID = pblock->IndextoID( j );
 
406
                ParamType2 parameterType = pblock->GetParameterType( parameterID );
 
407
                ParamDef parameterDef = pblock->GetParamDef( parameterID );
 
408
 
 
409
#ifdef UNICODE
 
410
                std::string paramNameString = COLLADABU::StringUtils::wideString2utf8String(parameterDef.int_name);
 
411
                                const char* paramName = paramNameString.c_str();
 
412
#else
 
413
                                const char* paramName = parameterDef.int_name;
 
414
#endif
 
415
                fprintf( stdout, "\tParam name = %s; Type = %i;\n", paramName, (int)parameterType );
 
416
            }
 
417
        }
 
418
    }
 
419
 
 
420
    void EffectExporter::exportHLSLEffect ( COLLADASW::EffectProfile & effectProfile, ExportNode* exportNode, Mtl* material, const String & effectId, float weight, bool inited )
 
421
    {
 
422
        // Export all submaterials first.
 
423
        int subMaterialCount = material->NumSubMtls();
 
424
        logEffectParameters( material );
 
425
 
 
426
        /*
 
427
        for ( int i = 0; i < subMaterialCount; ++i )
 
428
        {
 
429
            Mtl* subMaterial = material->GetSubMtl ( i );
 
430
            float subMtlWeight = weight;
 
431
 
 
432
            if ( material->ClassID() == CompositeMtl::classID )
 
433
            {
 
434
                IParamBlock2 * pblock = material->GetParamBlock ( 0 );
 
435
 
 
436
                if ( pblock != NULL )
 
437
                {
 
438
                    if ( !pblock->GetInt ( CompositeMtl::compmat_map_on ) )
 
439
                        subMtlWeight = 0;
 
440
                    else
 
441
                        subMtlWeight *= pblock->GetFloat ( CompositeMtl::compmat_amount ) / 100.0f;
 
442
                }
 
443
            }
 
444
 
 
445
            if ( subMaterial != NULL )
 
446
            {
 
447
                exportHLSLEffect ( effectProfile, exportNode, subMaterial, effectId, subMtlWeight, inited );
 
448
                inited = true;
 
449
            }
 
450
        }
 
451
 
 
452
        Class_ID materialId = material->ClassID();
 
453
 
 
454
        if ( materialId.PartA() == DMTL2_CLASS_ID || materialId.PartA() == DMTL_CLASS_ID )
 
455
        */
 
456
        {
 
457
            HwShaderExporter hwShaderExporter ( mDocumentExporter );
 
458
            hwShaderExporter.exportPluginHwShaderNode ( effectId, &effectProfile, exportNode, ( StdMat2* ) material, weight );
 
459
        }
 
460
    }
 
461
 
 
462
    //---------------------------------------------------------------
 
463
    void EffectExporter::exportStandardEffect ( COLLADASW::EffectProfile & effectProfile, ExportNode* exportNode, StdMat2* material, const String & effectId, float weight, bool inited )
 
464
    {
 
465
        assert ( material != 0 );
 
466
 
 
467
        // TODO ensure that effect id unique
 
468
        //  String effectId = mEffectIdList.addId(material->GetName().data());
 
469
 
 
470
#if 0
 
471
 
 
472
        EffectMap::iterator effectIterator = mEffectMap.find ( ( Mtl* ) material );
 
473
 
 
474
 
 
475
        if ( effectIterator != mEffectMap.end() )
 
476
        {
 
477
            exportNode->addSymbol ( ( Mtl* ) material, effectId );
 
478
            return ;
 
479
        }
 
480
 
 
481
#endif
 
482
        exportNode->addSymbol ( material, NativeString(material->GetName().data()) );
 
483
 
 
484
        mEffectMap[ material ] = effectId;
 
485
 
 
486
        Shader* shader = material->GetShader();
 
487
 
 
488
        TimeValue animationStart = mDocumentExporter->getOptions().getAnimationStart();
 
489
 
 
490
        if ( !inited )
 
491
        {
 
492
            effectProfile.setShaderType ( maxShaderToShaderType ( shader->ClassID() ) );
 
493
        }
 
494
 
 
495
        // Retrieve the interesting parameter blocks
 
496
        IParamBlock2* shaderParameters = ( IParamBlock2* ) shader->GetReference ( 0 );
 
497
 
 
498
        IParamBlock2* extendedParameters = ( IParamBlock2* ) material->GetReference ( StandardMaterial::EXTENDED_PB_REF );
 
499
 
 
500
        TimeValue initTime = mDocumentExporter->getOptions().getAnimationStart();
 
501
 
 
502
        if ( !inited )
 
503
        {
 
504
                        ScaleConversionFunctor scaleConversion(weight);
 
505
 
 
506
            // effectProfile.setShaderType(COLLADASW::EffectProfile::PHONG);
 
507
                        bool isAmbientAnimated = mAnimationExporter->addAnimatedParameter(shaderParameters, ShaderParameterIndices::AMBIENT_COLOR, effectId, effectProfile.getAmbientDefaultSid(), COLOR_PARAMETERS, true, &scaleConversion);
 
508
            effectProfile.setAmbient ( maxColor2ColorOrTexture ( shader->GetAmbientClr ( animationStart ), weight ), isAmbientAnimated );
 
509
 
 
510
                        bool isDiffuseAnimated = mAnimationExporter->addAnimatedParameter(shaderParameters, ShaderParameterIndices::DIFFUSE_COLOR, effectId, effectProfile.getDiffuseDefaultSid(), COLOR_PARAMETERS, true, &scaleConversion);
 
511
            effectProfile.setDiffuse ( maxColor2ColorOrTexture ( shader->GetDiffuseClr ( animationStart ), weight ), isDiffuseAnimated );
 
512
 
 
513
                        effectProfile.setTransparent ( COLLADASW::ColorOrTexture ( COLLADASW::Color::WHITE ) );
 
514
 
 
515
                        bool isOpacityAnimated = mAnimationExporter->addAnimatedParameter(extendedParameters, ExtendedParameterIndices::OPACITY, effectId, effectProfile.getSpecularDefaultSid(), COLOR_PARAMETERS);
 
516
            effectProfile.setTransparency ( material->GetOpacity ( animationStart ) * weight );
 
517
 
 
518
            effectProfile.setReflective ( COLLADASW::ColorOrTexture ( COLLADASW::Color::BLACK ) );
 
519
 
 
520
                        bool isSpecularAnimated = mAnimationExporter->addAnimatedParameter(shaderParameters, ShaderParameterIndices::SPECULAR_COLOR, effectId, effectProfile.getSpecularDefaultSid(), COLOR_PARAMETERS, true, &scaleConversion);
 
521
                        effectProfile.setSpecular ( maxColor2ColorOrTexture ( shader->GetSpecularClr ( animationStart ), weight ), isSpecularAnimated );
 
522
 
 
523
                        //bool isGlossinessAnimated = mAnimationExporter->addAnimatedParameter(shaderParameters, ShaderParameterIndices::GLOSSINESS, effectId, effectProfile.getShininessDefaultSid(), 0, true, &ConversionFunctors::toPercent);
 
524
                        //effectProfile.setShininess ( ConversionFunctors::toPercent(shader->GetGlossiness ( animationStart )) * weight, isGlossinessAnimated );
 
525
 
 
526
                        bool isSpecularLevelAnimated = mAnimationExporter->addAnimatedParameter(shaderParameters, ShaderParameterIndices::SPECULAR_LEVEL, effectId, effectProfile.getShininessDefaultSid(), 0, true, &ConversionFunctors::toPercent);
 
527
                        float specularLevel = shader->GetSpecularLevel ( animationStart );
 
528
                        effectProfile.setShininess ( specularLevel * weight, isSpecularLevelAnimated );
 
529
 
 
530
                        bool useEmissionColor = shader->IsSelfIllumClrOn() != false;
 
531
                        if (useEmissionColor)
 
532
                        {
 
533
                                bool isEmissionAnimated = mAnimationExporter->addAnimatedParameter(shaderParameters, ShaderParameterIndices::SELF_ILLUMINATION_COLOR, effectId, effectProfile.getEmissionDefaultSid(), COLOR_PARAMETERS, true, &scaleConversion);
 
534
                                effectProfile.setEmission( maxColor2ColorOrTexture ( shader->GetSelfIllumClr ( animationStart ), weight ), isEmissionAnimated );
 
535
                        }
 
536
                        else
 
537
                        {
 
538
                                bool isEmissionAnimated = mAnimationExporter->addAnimatedParameter(shaderParameters, ShaderParameterIndices::SELF_ILLUMINATION_COLOR, effectId, effectProfile.getEmissionDefaultSid(), COLOR_PARAMETERS);
 
539
                                effectProfile.setEmission( maxColor2ColorOrTexture ( shader->GetSelfIllumClr ( animationStart ) ), isEmissionAnimated );
 
540
                        }
 
541
 
 
542
                        addParamBlockAnimatedExtraParameters(SHADER_ELEMENT, SHADER_PARAMETERS, SHADER_PARAMETER_COUNT, shaderParameters, effectId);
 
543
                        
 
544
                        addParamBlockAnimatedExtraParameters(EXTENDED_SHADER_ELEMENT, EXTENDED_SHADER_PARAMETERS, EXTENDED_SHADER_PARAMETER_COUNT, extendedParameters, effectId);
 
545
        }
 
546
 
 
547
        // Export child maps
 
548
        int numSubTexMaps = material->NumSubTexmaps();
 
549
 
 
550
        for ( int i = 0; i < numSubTexMaps; i++ )
 
551
        {
 
552
            Channel channel = maxIdToEffectChannel ( material, i );
 
553
 
 
554
            if ( channel == EffectExporter::UNKNOWN )
 
555
                continue;
 
556
 
 
557
            Texmap* map = material->GetSubTexmap ( i );
 
558
 
 
559
            // special cases
 
560
            switch ( channel )
 
561
            {
 
562
 
 
563
            case EMISSION:
 
564
 
 
565
       /*         if ( !material->GetSelfIllumColorOn() )     // Emission
 
566
                {
 
567
                    // emission factor
 
568
                    //    ANIM->ExportProperty(_T("self_illum_level"), shaderParameters, FSStandardMaterial::shdr_self_illum_amnt, 0, stdProfile->GetEmissionFactorParam()->GetValue(), NULL);
 
569
                    //TODO: check what this is good for
 
570
                    //stdProfile->SetIsEmissionFactor(true);
 
571
                    continue;
 
572
                }*/
 
573
 
 
574
                break;
 
575
 
 
576
            case TRANSPARENt:
 
577
                effectProfile.setOpaque ( getOpacity ( map ) );
 
578
                break;
 
579
            }
 
580
 
 
581
            // Calculate weight here.  Let execution continue
 
582
            // even if map is disabled, in order to manage colour blending
 
583
            float colorAmount, mapAmount = 0;
 
584
 
 
585
            bool exportThisMap = material->GetMapState ( i ) == 2;
 
586
 
 
587
            if ( exportThisMap )
 
588
            {
 
589
                mapAmount = material->GetTexmapAmt ( i, 0 );
 
590
                colorAmount = weight * ( 1.0f - mapAmount );
 
591
                mapAmount *= weight;
 
592
            }
 
593
 
 
594
            else
 
595
                colorAmount = weight;
 
596
 
 
597
            // If our id maps to a colour value, modulate that by our colourAmount.
 
598
            // TODO: add this later
 
599
            switch ( channel )
 
600
            {
 
601
 
 
602
            case AMBIENT:
 
603
                blendColor ( effectProfile.getAmbient(), material->GetAmbient ( initTime ), colorAmount );
 
604
                break;
 
605
 
 
606
            case DIFFUSE:
 
607
                blendColor ( effectProfile.getDiffuse(), material->GetDiffuse ( initTime ), colorAmount );
 
608
                break;
 
609
 
 
610
            case SPECULAR:
 
611
                blendColor ( effectProfile.getSpecular(), material->GetSpecular ( initTime ), colorAmount );
 
612
                break;
 
613
            }
 
614
 
 
615
            // export now.
 
616
 
 
617
            if ( exportThisMap )
 
618
                exportMap (material, channel, map, effectProfile, weight * mapAmount );
 
619
        }
 
620
    }
 
621
 
 
622
    //---------------------------------------------------------------
 
623
    void EffectExporter::exportMap ( Mtl * material, unsigned int index, Texmap* texMap, COLLADASW::EffectProfile & profile, float weight )
 
624
    {
 
625
        if ( !texMap )
 
626
            return ;
 
627
 
 
628
        //if (weight <= 0) return;
 
629
 
 
630
        // Get any weight control directly on this texmap
 
631
        float amount = weight;
 
632
 
 
633
        Control* weightControl = 0;
 
634
 
 
635
        if ( texMap  && GetIBitmapTextInterface ( texMap ) != 0 )
 
636
        {
 
637
            try
 
638
            {
 
639
                BitmapTex * bmTex = ( BitmapTex* ) texMap;
 
640
                TextureOutput* texOut = bmTex->GetTexout();
 
641
                IParamBlock* params = ( IParamBlock* ) texOut->GetReference ( TextureOutputIDs::param_block_ref_id );
 
642
 
 
643
                if ( index == ID_BU )
 
644
                {
 
645
                    weightControl = params->GetController ( TextureOutputIDs::bump_amount );
 
646
                    amount *= params->GetFloat ( TextureOutputIDs::bump_amount );
 
647
                }
 
648
 
 
649
                else
 
650
                {
 
651
                    weightControl = params->GetController ( TextureOutputIDs::output_amount );
 
652
                    amount *= params->GetFloat ( TextureOutputIDs::output_amount );
 
653
                }
 
654
            }
 
655
 
 
656
            catch ( ... )
 
657
            {
 
658
                /// @TODO error handling
 
659
            }
 
660
        }
 
661
 
 
662
        // Export image
 
663
                String fullFileName;
 
664
        String imageId = exportImage ( texMap, fullFileName );
 
665
 
 
666
        if ( !imageId.empty() )
 
667
        {
 
668
            COLLADASW::Texture texture ( imageId );
 
669
 
 
670
            // Create the sampler
 
671
            String samplerSid = imageId + COLLADASW::Sampler::SAMPLER_SID_SUFFIX;
 
672
            String surfaceSid = imageId + COLLADASW::Sampler::SURFACE_SID_SUFFIX;
 
673
            COLLADASW::Sampler sampler( COLLADASW::Sampler::SAMPLER_TYPE_2D, samplerSid, surfaceSid );
 
674
                        sampler.setImageId( imageId );
 
675
                        //sampler.setFormat( FORMAT );
 
676
            //texture.setSampler( sampler );
 
677
 
 
678
            int mapChannel = 1;
 
679
 
 
680
            if ( texMap )
 
681
            {
 
682
                                mapChannel = texMap->GetMapChannel();
 
683
 
 
684
                                UVGen* uvCoordinatesGenerator = texMap->GetTheUVGen();
 
685
                                if (uvCoordinatesGenerator && uvCoordinatesGenerator->ClassID().PartA() == STDUV_CLASS_ID)
 
686
                                {
 
687
                                        StdUVGen* uvGenParameters = (StdUVGen*)uvCoordinatesGenerator;
 
688
                                        int uvFlags = uvGenParameters->GetTextureTiling();
 
689
                                        
 
690
                                        sampler.setWrapS(COLLADASW::Sampler::WRAP_MODE_CLAMP);
 
691
                                        sampler.setWrapT(COLLADASW::Sampler::WRAP_MODE_CLAMP);
 
692
 
 
693
                                        if ( uvFlags & U_WRAP )
 
694
                                        {
 
695
                                                //Indicates the texture map is tiled in the U direction. 
 
696
                                                sampler.setWrapS(COLLADASW::Sampler::WRAP_MODE_WRAP);
 
697
                                        }
 
698
                                        if ( uvFlags & V_WRAP )
 
699
                                        {
 
700
                                                //Indicates the texture map is tiled in the V direction. 
 
701
                                                sampler.setWrapT(COLLADASW::Sampler::WRAP_MODE_WRAP);
 
702
                                        }
 
703
                                        if ( uvFlags & U_MIRROR )
 
704
                                        {
 
705
                                                //Indicates the texture map is mirrored in the U direction. 
 
706
                                                sampler.setWrapS(COLLADASW::Sampler::WRAP_MODE_MIRROR);
 
707
                                        }
 
708
                                        if ( uvFlags & V_MIRROR )
 
709
                                        {
 
710
                                                //Indicates the texture map is mirrored in the V direction. 
 
711
                                                sampler.setWrapT(COLLADASW::Sampler::WRAP_MODE_MIRROR);
 
712
                                        }
 
713
 
 
714
                                        IParamBlock* uvParams = (IParamBlock*)uvGenParameters->GetReference(StdUVGenEnums::pblock);     
 
715
 
 
716
 
 
717
                                        
 
718
/*
 
719
                                        float rotationAngle = uvParams->GetFloat(StdUVGenEnums::w_angle);
 
720
 
 
721
                                        String textureFileName;
 
722
                                        String textureDir;
 
723
                                        DocumentExporter::splitFilePath(fullFileName, textureDir, textureFileName);
 
724
                                        COLLADASW::TextureModifier textureModifier(fullFileName, mDocumentExporter->getOutputDir() + textureFileName);  
 
725
                                
 
726
                                        textureModifier.setRotationAngle(rotationAngle);
 
727
 
 
728
                                        textureModifier.performModifications();
 
729
*/
 
730
                                        mMaterialChannelPairParamBlockMap[MaterialChannelPair(material, index)] = uvParams;
 
731
 
 
732
                                }
 
733
 
 
734
 
 
735
                // TODO: add extra tag
 
736
            }
 
737
                        
 
738
                        texture.setSampler( sampler );
 
739
 
 
740
                        String semantic = createTexcoordSementicFromMapchannel( mapChannel );
 
741
 
 
742
            texture.setTexcoord ( semantic );
 
743
 
 
744
            //TODO: extra tag
 
745
 
 
746
            switch ( index )
 
747
            {
 
748
 
 
749
            case AMBIENT:
 
750
                profile.setAmbient ( COLLADASW::ColorOrTexture ( texture ) );
 
751
                break;
 
752
                        case DIFFUSE:
 
753
                profile.setDiffuse ( COLLADASW::ColorOrTexture ( texture ) );
 
754
                break;
 
755
            case SPECULAR:
 
756
                profile.setSpecular ( COLLADASW::ColorOrTexture ( texture ) );
 
757
                break;
 
758
                        case SPECULAR_LEVEL: 
 
759
                                texture.setProfileName(Extra::TECHNIQUE_PROFILE_3DSMAX);
 
760
                                texture.setChildElementName("specularLevel");
 
761
                                profile.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture)); 
 
762
                                break;
 
763
                        case SHININESS:         // Glossiness
 
764
                                texture.setProfileName(Extra::TECHNIQUE_PROFILE_3DSMAX);
 
765
                                texture.setChildElementName("gloss");
 
766
                                profile.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture)); 
 
767
                                break;
 
768
            case EMISSION:              // Self-illumination
 
769
                profile.setEmission ( COLLADASW::ColorOrTexture ( texture ) );
 
770
                break;
 
771
                        case TRANSPARENt:               // Opacity
 
772
                profile.setTransparent ( COLLADASW::ColorOrTexture ( texture ) );
 
773
                break;
 
774
            case FILTER:
 
775
                                texture.setProfileName(Extra::TECHNIQUE_PROFILE_3DSMAX);
 
776
                                texture.setChildElementName("filter");
 
777
                                profile.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture)); 
 
778
                                break;
 
779
                        case BUMP: 
 
780
                                {
 
781
                                        texture.setProfileName(Extra::TECHNIQUE_PROFILE_3DSMAX);
 
782
                                        texture.setChildElementName("bump");
 
783
                                        COLLADASW::EffectProfile::StringPairList attributes;
 
784
                                        attributes.push_back(std::make_pair(DAE_BUMP_TYPE_ATTRIBUTE, DAE_BUMP_TYPE_HEIGHTFIELD));
 
785
                                        profile.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture), attributes); 
 
786
                                        break;
 
787
                                }
 
788
                        case REFLECTION: 
 
789
                                profile.setReflective( COLLADASW::ColorOrTexture ( texture ) );
 
790
                                break;
 
791
                        case REFRACTION:
 
792
                                texture.setProfileName(Extra::TECHNIQUE_PROFILE_3DSMAX);
 
793
                                texture.setChildElementName("refraction");
 
794
                                profile.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture)); 
 
795
                                break;
 
796
            case DISPLACEMENT: 
 
797
                                texture.setProfileName(Extra::TECHNIQUE_PROFILE_3DSMAX);
 
798
                                texture.setChildElementName("displacement");
 
799
                                profile.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture)); 
 
800
                                break;
 
801
            default:
 
802
                ;
 
803
                //@TODO error handling
 
804
            }
 
805
 
 
806
        }
 
807
 
 
808
        // Export any and all submaps
 
809
        float subAmount = amount;
 
810
 
 
811
        int numSubTex = texMap->NumSubTexmaps();
 
812
 
 
813
        for ( int subIdx = 0; subIdx < numSubTex; subIdx++ )
 
814
        {
 
815
            Texmap* subMap = texMap->GetSubTexmap ( subIdx );
 
816
 
 
817
            // Handle special cases.
 
818
            Class_ID mapClassId = texMap->ClassID();
 
819
 
 
820
            if ( mapClassId.PartB() == 0 )
 
821
            {
 
822
                switch ( mapClassId.PartA() )
 
823
                {
 
824
 
 
825
                case MIX_CLASS_ID:
 
826
                {
 
827
                    IParamBlock2 * mixParams = texMap->GetParamBlock ( 0 );
 
828
 
 
829
                    if ( !mixParams )
 
830
                        break;
 
831
 
 
832
                    Color color;
 
833
 
 
834
                    switch ( subIdx )
 
835
                    {
 
836
 
 
837
                    case 0:
 
838
                        subAmount = amount;
 
839
                        color = mixParams->GetColor ( MixMap::mix_color1 );
 
840
                        break;
 
841
 
 
842
                    case 1:
 
843
                        subAmount = amount * mixParams->GetFloat ( MixMap::mix_mix );
 
844
                        color = mixParams->GetColor ( MixMap::mix_color2 );
 
845
                        break;
 
846
 
 
847
                    case 2:
 
848
                        // Scale to 0, as this isn't an actual texture, but a mix modifier
 
849
                        // In that case, we want to keep a texture reference for the user
 
850
                        // to figure out if they want
 
851
                        subAmount = 0;
 
852
                        break;
 
853
                    }
 
854
 
 
855
                    // Handle the simple case, which is blending colors.
 
856
 
 
857
                    if ( subMap == NULL && subAmount > 0 )
 
858
                    {
 
859
                        switch ( index )
 
860
                        {
 
861
 
 
862
                        case AMBIENT:
 
863
                            blendColor ( profile.getAmbient(), color, subAmount );
 
864
                            break;
 
865
 
 
866
                        case DIFFUSE:
 
867
                            blendColor ( profile.getDiffuse(), color, subAmount );
 
868
                            break;
 
869
 
 
870
                        case SPECULAR:
 
871
                            blendColor ( profile.getSpecular(), color, subAmount );
 
872
                            break;
 
873
                        }
 
874
                    }
 
875
                }
 
876
 
 
877
                break;
 
878
                }
 
879
            }
 
880
 
 
881
            else
 
882
                subAmount = amount;
 
883
 
 
884
            if ( subMap != NULL )
 
885
            {
 
886
                if ( texMap->SubTexmapOn ( subIdx ) == 0 )
 
887
                    subAmount = 0;
 
888
 
 
889
                exportMap (material, index, subMap, profile, subAmount );
 
890
            }
 
891
        }
 
892
    }
 
893
 
 
894
    //---------------------------------------------------------------
 
895
    void EffectExporter::exportUnknownEffect ( COLLADASW::EffectProfile & effectProfile, ExportNode* exportNode, Mtl* material, const String & effectId )
 
896
    {
 
897
        assert ( material != 0 );
 
898
 
 
899
        /* TODO: think about this*/
 
900
 
 
901
        if ( effectProfile.getShaderType() == COLLADASW::EffectProfile::UNSPECIFIED )
 
902
        {
 
903
            float specularLevel = material->GetShinStr();
 
904
            bool isPhong = specularLevel > 0.2f;
 
905
            effectProfile.setShaderType ( isPhong ? COLLADASW::EffectProfile::PHONG : COLLADASW::EffectProfile::BLINN );
 
906
        }
 
907
 
 
908
        if ( material->GetSelfIllumColorOn() && !effectProfile.getEmission().isValid() )
 
909
            effectProfile.setEmission ( maxColor2ColorOrTexture ( material->GetSelfIllumColor() ) );
 
910
 
 
911
        if ( !effectProfile.getAmbient().isValid() )
 
912
            effectProfile.setAmbient ( maxColor2ColorOrTexture ( material->GetAmbient() ) );
 
913
 
 
914
        if ( !effectProfile.getDiffuse().isValid() )
 
915
            effectProfile.setDiffuse ( maxColor2ColorOrTexture ( material->GetDiffuse() ) );
 
916
 
 
917
 
 
918
        if ( effectProfile.getShaderType() == COLLADASW::EffectProfile::PHONG )
 
919
        {
 
920
            if ( !effectProfile.getSpecular().isValid() )
 
921
                effectProfile.setSpecular ( maxColor2ColorOrTexture ( material->GetSpecular() ) );
 
922
 
 
923
            /// TODO: think about this
 
924
            if ( effectProfile.getShininess() < 0 )
 
925
                effectProfile.setShininess ( material->GetShininess() * 100.0f );
 
926
 
 
927
            /* if (!material->GetSelfIllumColorOn())
 
928
             {
 
929
              stdProfile->SetIsEmissionFactor(true);
 
930
              float emissionFactor = material->GetSelfIllum();
 
931
              stdProfile->SetEmissionFactor(emissionFactor);
 
932
             }*/
 
933
 
 
934
            // stdProfile->SetSpecularFactor(specularLevel);
 
935
        }
 
936
 
 
937
        exportNode->addSymbol ( material, NativeString(material->GetName().data()) );
 
938
 
 
939
        mEffectMap[ material ] = effectId;
 
940
    }
 
941
 
 
942
    //---------------------------------------------------------------
 
943
    void EffectExporter::exportColorEffect ( ExportNode* exportNode, DWORD color )
 
944
    {
 
945
        String effectId = getEffectId ( color );
 
946
 
 
947
        if ( find ( mWireFrameColorEffectList.begin(), mWireFrameColorEffectList.end(), color ) == mWireFrameColorEffectList.end() )
 
948
        {
 
949
            String effectId = getEffectId ( color );
 
950
 
 
951
            openEffect ( effectId );
 
952
                        setExtraTechnique(this);
 
953
 
 
954
                        COLLADASW::EffectProfile effectProfile ( LibraryEffects::mSW );
 
955
            effectProfile.setShaderType ( COLLADASW::EffectProfile::PHONG );
 
956
            COLLADASW::Color commonColor ( GetRValue ( color ) / 255.0f, GetGValue ( color ) / 255.0f, GetBValue ( color ) / 255.0f );
 
957
            effectProfile.setAmbient ( COLLADASW::ColorOrTexture ( commonColor ) );
 
958
            effectProfile.setDiffuse ( COLLADASW::ColorOrTexture ( commonColor ) );
 
959
            effectProfile.setTransparent ( COLLADASW::ColorOrTexture ( COLLADASW::Color::WHITE ) );
 
960
            effectProfile.setTransparency ( 1.0 );
 
961
            effectProfile.setReflective ( COLLADASW::ColorOrTexture ( COLLADASW::Color::BLACK ) );
 
962
            effectProfile.setSpecular ( COLLADASW::ColorOrTexture ( COLLADASW::Color::WHITE ) );
 
963
            effectProfile.setShininess ( 10.0 );
 
964
 
 
965
            addEffectProfile ( effectProfile );
 
966
 
 
967
                        addExtraTechniques(ElementWriter::mSW);
 
968
 
 
969
            closeEffect();
 
970
 
 
971
            mWireFrameColorEffectList.push_back ( color );
 
972
        }
 
973
 
 
974
        exportNode->setWireFrameColor ( color );
 
975
    }
 
976
 
 
977
    //---------------------------------------------------------------
 
978
    String EffectExporter::getEffectId ( DWORD color )
 
979
    {
 
980
        std::ostringstream name;
 
981
        name << COLOR_EFFECT_ID_PREFIX << "R" << ( int ) GetRValue ( color ) << "G" << ( int ) GetGValue ( color )
 
982
        << "B" << ( int ) GetBValue ( color );
 
983
        return name.str();
 
984
    }
 
985
 
 
986
        //---------------------------------------------------------------
 
987
        COLLADASW::Color EffectExporter::maxColor2Color ( const Color & color, double scale )
 
988
        {
 
989
                return  COLLADASW::Color ( color.r * scale, color.g * scale, color.b * scale, scale );
 
990
        }
 
991
 
 
992
 
 
993
    //---------------------------------------------------------------
 
994
    COLLADASW::ColorOrTexture EffectExporter::maxColor2ColorOrTexture ( const Color & color, double scale )
 
995
    {
 
996
        return COLLADASW::ColorOrTexture ( maxColor2Color( color, scale ) );
 
997
    }
 
998
 
 
999
    //---------------------------------------------------------------
 
1000
    EffectExporter::Channel EffectExporter::maxIdToEffectChannel ( StdMat2* material, int id )
 
1001
    {
 
1002
        assert ( material );
 
1003
 
 
1004
        // Order of channels depends on shader.
 
1005
        bool stdShader = true;
 
1006
        Shader* shader = material->GetShader();
 
1007
 
 
1008
        if ( shader )
 
1009
        {
 
1010
            Class_ID shaderClassId = shader->ClassID();
 
1011
            unsigned long partA = shaderClassId.PartA();
 
1012
 
 
1013
            if ( shaderClassId.PartB() != 0 ||
 
1014
                    ! (
 
1015
                        partA == EffectExporter::STD2_PHONG_CLASS_ID ||
 
1016
                        partA == EffectExporter::STD2_BLINN_SHADER_CLASS_ID ||
 
1017
                        partA == EffectExporter::STD2_METAL_SHADER_CLASS_ID ||
 
1018
                        partA == EffectExporter::STD2_ANISOTROPIC_SHADER_CLASS_ID ||
 
1019
                        partA == EffectExporter::STD2_MULTI_LAYER_SHADER_CLASS_ID ||
 
1020
                        partA == EffectExporter::STD2_OREN_NAYER_BLINN_CLASS_ID
 
1021
                    )
 
1022
               )
 
1023
            {
 
1024
                stdShader = false;
 
1025
            }
 
1026
        }
 
1027
 
 
1028
        if ( !stdShader )
 
1029
        {
 
1030
            // First attempt for a non-max shader is name-matching.
 
1031
            // this is because StdIDToChannel may need some extra help
 
1032
            // if for some weird reason there are several different texture
 
1033
            // slots for the same effect.  Quite why that happens is
 
1034
            // completely beyond me, but it does happen...  Also, as it
 
1035
            // turns out, it is better not to trust the 3rd party implementations
 
1036
            TSTR subName = material->GetSubTexmapSlotName ( id );
 
1037
 
 
1038
            if ( subName.Length() > 0 )
 
1039
            {
 
1040
                String upperName = NativeString(subName.data());
 
1041
                std::transform ( upperName.begin(), upperName.end(), upperName.begin(), toupper );
 
1042
                size_t firstSpace = upperName.find ( ' ' );
 
1043
 
 
1044
                if ( firstSpace != String::npos )
 
1045
                    upperName.resize ( firstSpace );
 
1046
 
 
1047
                if ( upperName == "BASE" )
 
1048
                    return EffectExporter::DIFFUSE;
 
1049
                else if ( upperName == "GLOSS" )
 
1050
                    return EffectExporter::SPECULAR;
 
1051
                else
 
1052
                {
 
1053
                    EffectExporter::Channel channel = EffectExporter::channelFromString ( upperName );
 
1054
 
 
1055
                    if ( channel != EffectExporter::UNKNOWN )
 
1056
                        return channel;
 
1057
                }
 
1058
            }
 
1059
        }
 
1060
 
 
1061
#ifdef _DEBUG
 
1062
        else
 
1063
        {
 
1064
            // What do we have here, ay?
 
1065
            TSTR subName = material->GetSubTexmapSlotName ( id );
 
1066
            subName;
 
1067
        }
 
1068
 
 
1069
#endif
 
1070
 
 
1071
        // If we are here, we are either a std max mtl, or a
 
1072
        // non-std mtl we couldnt match a name to.
 
1073
        int classId = -1;
 
1074
 
 
1075
        for ( int i = 0; i < NTEXMAPS; i++ )
 
1076
        {
 
1077
            //int x = material->StdIDToChannel(i);
 
1078
 
 
1079
            if ( material->StdIDToChannel ( i ) == id )
 
1080
            {
 
1081
                classId = i;
 
1082
                break;
 
1083
            }
 
1084
        }
 
1085
 
 
1086
        switch ( classId )
 
1087
        {
 
1088
 
 
1089
        case ID_AM:
 
1090
            return EffectExporter::AMBIENT;
 
1091
 
 
1092
        case ID_DI:
 
1093
            return EffectExporter::DIFFUSE;
 
1094
 
 
1095
        case ID_SP:
 
1096
            return EffectExporter::SPECULAR;
 
1097
 
 
1098
        case ID_SH:
 
1099
            return EffectExporter::SHININESS;
 
1100
 
 
1101
        case ID_SS:
 
1102
            return EffectExporter::SPECULAR_LEVEL;
 
1103
 
 
1104
        case ID_SI:
 
1105
            return EffectExporter::EMISSION;
 
1106
 
 
1107
        case ID_OP:
 
1108
            return EffectExporter::TRANSPARENt;
 
1109
 
 
1110
        case ID_FI:
 
1111
            return EffectExporter::FILTER;
 
1112
 
 
1113
        case ID_BU:
 
1114
            return EffectExporter::BUMP;
 
1115
 
 
1116
        case ID_RL:
 
1117
            return EffectExporter::REFLECTION;
 
1118
 
 
1119
        case ID_RR:
 
1120
            return EffectExporter::REFRACTION;
 
1121
 
 
1122
        case ID_DP:
 
1123
            return EffectExporter::DISPLACEMENT;
 
1124
 
 
1125
        default:
 
1126
            return EffectExporter::UNKNOWN;
 
1127
        }
 
1128
 
 
1129
    };
 
1130
 
 
1131
    //---------------------------------------------------------------
 
1132
    EffectExporter::Channel EffectExporter::channelFromString ( const String & value )
 
1133
    {
 
1134
        if ( value == DAE_AMBIENT_TEXTURE_CHANNEL )
 
1135
            return EffectExporter::AMBIENT;
 
1136
        else if ( value == DAE_BUMP_TEXTURE_CHANNEL )
 
1137
            return EffectExporter::BUMP;
 
1138
        else if ( value == DAE_DIFFUSE_TEXTURE_CHANNEL )
 
1139
            return EffectExporter::DIFFUSE;
 
1140
        else if ( value == DAE_DISPLACEMENT_TEXTURE_CHANNEL )
 
1141
            return EffectExporter::DISPLACEMENT;
 
1142
        else if ( value == DAE_EMISSION_TEXTURE_CHANNEL )
 
1143
            return EffectExporter::EMISSION;
 
1144
        else if ( value == DAE_FILTER_TEXTURE_CHANNEL )
 
1145
            return EffectExporter::FILTER;
 
1146
 
 
1147
        //  else if (value == DAE_OPACITY_TEXTURE_CHANNEL) return OPACITY;
 
1148
        else if ( value == DAE_REFLECTION_TEXTURE_CHANNEL )
 
1149
            return EffectExporter::REFLECTION;
 
1150
        else if ( value == DAE_REFRACTION_TEXTURE_CHANNEL )
 
1151
            return EffectExporter::REFRACTION;
 
1152
        else if ( value == DAE_SHININESS_TEXTURE_CHANNEL )
 
1153
            return EffectExporter::SHININESS;
 
1154
        else if ( value == DAE_SPECULAR_TEXTURE_CHANNEL )
 
1155
            return EffectExporter::SPECULAR;
 
1156
        else if ( value == DAE_SPECULARLEVEL_TEXTURE_CHANNEL )
 
1157
            return EffectExporter::SPECULAR_LEVEL;
 
1158
        else if ( value == DAE_TRANSPARENT_TEXTURE_CHANNEL )
 
1159
            return EffectExporter::TRANSPARENt;
 
1160
        else
 
1161
            return UNKNOWN;
 
1162
    }
 
1163
 
 
1164
    //---------------------------------------------------------------
 
1165
    COLLADASW::EffectProfile::Opaque EffectExporter::getOpacity ( Texmap *texMap )
 
1166
    {
 
1167
        // Only one transparency factor is supported, so retrieve only the first texture from this bucket.
 
1168
 
 
1169
        if ( texMap == NULL )
 
1170
            return COLLADASW::EffectProfile::A_ONE;
 
1171
 
 
1172
        BitmapTex* bmap = GetIBitmapTextInterface ( texMap );
 
1173
 
 
1174
        BOOL isAlphaTransparency = true;
 
1175
 
 
1176
        if ( bmap != NULL )
 
1177
            isAlphaTransparency = bmap->GetAlphaAsMono ( TRUE );
 
1178
 
 
1179
        // As far as my tests are concerned, the only real way to get alpha-transparency is through
 
1180
        // the mono-channel output as Alpha.
 
1181
        return isAlphaTransparency ? COLLADASW::EffectProfile::A_ONE : COLLADASW::EffectProfile::RGB_ZERO;
 
1182
    }
 
1183
 
 
1184
    //---------------------------------------------------------------
 
1185
    COLLADASW::EffectProfile::ShaderType EffectExporter::maxShaderToShaderType ( Class_ID id )
 
1186
    {
 
1187
        switch ( id.PartA() )
 
1188
        {
 
1189
 
 
1190
        case StandardMaterial::STD2_BLINN_SHADER_CLASS_ID:
 
1191
 
 
1192
        case StandardMaterial::STD2_OREN_NAYER_BLINN_CLASS_ID:
 
1193
 
 
1194
        case StandardMaterial::STD2_METAL_SHADER_CLASS_ID:
 
1195
            return COLLADASW::EffectProfile::BLINN;
 
1196
 
 
1197
        case StandardMaterial::STD2_PHONG_CLASS_ID:
 
1198
            return COLLADASW::EffectProfile::PHONG;
 
1199
 
 
1200
        default:
 
1201
            return COLLADASW::EffectProfile::PHONG;
 
1202
        }
 
1203
    }
 
1204
 
 
1205
    //---------------------------------------------------------------
 
1206
    String EffectExporter::exportImage ( Texmap* map, String& fullFileName  )
 
1207
    {
 
1208
        if ( !map  )
 
1209
            return EMPTY_STRING;
 
1210
 
 
1211
        if ( map->ClassID() == Class_ID ( BMTEX_CLASS_ID, 0x00 ) )
 
1212
        {
 
1213
            BitmapTex * baseBitmap = ( BitmapTex* ) map;
 
1214
 
 
1215
            if ( !baseBitmap )
 
1216
                return EMPTY_STRING;
 
1217
 
 
1218
            // get a valid filename
 
1219
            BitmapInfo bitmapInfo;
 
1220
 
 
1221
            bitmapInfo.SetName ( baseBitmap->GetMapName() );
 
1222
 
 
1223
            return exportImage ( bitmapInfo, fullFileName );
 
1224
        }
 
1225
 
 
1226
        else if ( map->ClassID() == Class_ID ( MIX_CLASS_ID, 0x00 ) )
 
1227
        {
 
1228
            return EMPTY_STRING;
 
1229
        }
 
1230
 
 
1231
        // not recognized
 
1232
        return EMPTY_STRING;
 
1233
    }
 
1234
 
 
1235
    //---------------------------------------------------------------
 
1236
    String EffectExporter::exportImage ( BitmapInfo& bitmapInfo, String& fullFileName )
 
1237
    {
 
1238
                const TCHAR * fileNamePtr = bitmapInfo.Name();
 
1239
 
 
1240
                String fileName;
 
1241
                if ( fileNamePtr )
 
1242
                        fileName = NativeString(fileNamePtr);
 
1243
 
 
1244
                static const String noneString("none"); 
 
1245
                if ( !fileName.empty() && !StringUtils::equals(fileName, noneString) )
 
1246
        {
 
1247
 
 
1248
            BMMGetFullFilename ( &bitmapInfo );
 
1249
            NativeString fullNativeFileName  = NativeString(bitmapInfo.Name());
 
1250
                        fullFileName = fullNativeFileName;
 
1251
                        COLLADABU::URI fullFileNameURI = URI::nativePathToUri( fullNativeFileName.toUtf8String() );
 
1252
                        if ( fullFileNameURI.getScheme().empty() )
 
1253
                                fullFileNameURI.setScheme(COLLADASW::URI::SCHEME_FILE);
 
1254
 
 
1255
            // Export the equivalent <image> node in the image library and add
 
1256
            // the <init_from> element to the sampler's surface definition.
 
1257
            // "None" is a special Max token, to indicate no texture assigned
 
1258
            ExportedImageMap::iterator it = mExportedImageMap.find ( fullFileNameURI );
 
1259
 
 
1260
            if ( it == mExportedImageMap.end() )
 
1261
            {
 
1262
                // generate an interesting name: strip the filename away from the filepath.
 
1263
                size_t slashIndex = fullFileName.rfind ( '/' );
 
1264
                size_t backSlashIndex = fullFileName.rfind ( '\\' );
 
1265
 
 
1266
                                ImageInfo imageInfo;
 
1267
 
 
1268
                                if ( slashIndex == String::npos )
 
1269
                    slashIndex = backSlashIndex;
 
1270
                else if ( backSlashIndex != String::npos && backSlashIndex > slashIndex )
 
1271
                    slashIndex = backSlashIndex;
 
1272
 
 
1273
                imageInfo.imageId = ( slashIndex != String::npos ) ? fullFileName.substr ( slashIndex + 1 ) : fullFileName;
 
1274
                                imageInfo.imageId = COLLADASW::Utils::replaceDot ( COLLADASW::Utils::checkID(imageInfo.imageId) );
 
1275
                                imageInfo.imageId = mImageIdList.addId( imageInfo.imageId );
 
1276
 
 
1277
                                if ( mDocumentExporter->getOptions().getCopyImages() )
 
1278
                                {
 
1279
                                        // we need to copy the image in  output directory/images
 
1280
                                        COLLADASW::URI imageTargetPath = createTargetURI(fullFileNameURI);
 
1281
                                        // Copy the texture, if it isn't already there...
 
1282
                                        bool exists = COLLADABU::Utils::fileExistsAndIsReadable( imageTargetPath.toNativePath() );
 
1283
                                        if( !exists )
 
1284
                                        {
 
1285
                                                try 
 
1286
                                                {
 
1287
                                                        // Create the target directory, if necessary. 
 
1288
                                                        // Note: some systems (window$) requires the string to be 
 
1289
                                                        // enclosed in quotes when a space is present.
 
1290
                                                        COLLADASW::URI imageTargetPathDir ( imageTargetPath.getPathDir() );
 
1291
                                                        exists = COLLADABU::Utils::createDirectoryIfNeeded( imageTargetPathDir.toNativePath() );
 
1292
 
 
1293
                                                        if( exists )
 
1294
                                                        {
 
1295
                                                                // Throws: basic_filesystem_error<Path> if
 
1296
                                                                // from_fp.empty() || to_fp.empty() ||!exists(from_fp) || !is_regular(from_fp) || exists(to_fp)
 
1297
                                                                exists = COLLADABU::Utils::copyFile( fullFileNameURI.toNativePath(), imageTargetPath.toNativePath() );
 
1298
                                                        }
 
1299
                                                }
 
1300
                                                catch ( ... )
 
1301
                                                {
 
1302
                                                        exists = false;
 
1303
                                                }
 
1304
 
 
1305
                                                if( !exists )
 
1306
                                                {
 
1307
                                                        // todo handle error
 
1308
                                                }
 
1309
                                        }
 
1310
 
 
1311
                                        if ( mDocumentExporter->getOptions().getExportRelativePaths() )
 
1312
                                        {
 
1313
                                                bool success = true;
 
1314
                                                imageInfo.fileLocation = imageTargetPath.getRelativeTo(mDocumentExporter->getOutputFileUri(),success, true);
 
1315
                                        }
 
1316
                                        else
 
1317
                                        {
 
1318
                                                imageInfo.fileLocation = imageTargetPath;
 
1319
                                        }
 
1320
                                }
 
1321
                                else
 
1322
                                {
 
1323
                                        if ( mDocumentExporter->getOptions().getExportRelativePaths() )
 
1324
                                        {
 
1325
                                                bool success = true;
 
1326
                                                imageInfo.fileLocation = fullFileNameURI.getRelativeTo(mDocumentExporter->getOutputFileUri(),success, true);
 
1327
                                        }
 
1328
                                        else
 
1329
                                        {
 
1330
                                                imageInfo.fileLocation = fullFileNameURI;
 
1331
                                        }
 
1332
                                }
 
1333
 
 
1334
                // image not exported
 
1335
                mExportedImageMap[ fullFileNameURI ] = imageInfo;
 
1336
                                return imageInfo.imageId;
 
1337
            }
 
1338
            else
 
1339
                        {
 
1340
                return it->second.imageId;
 
1341
                        }
 
1342
 
 
1343
        }
 
1344
 
 
1345
        return EMPTY_STRING;
 
1346
    }
 
1347
 
 
1348
        // ------------------------------------------------------------
 
1349
        COLLADASW::URI EffectExporter::createTargetURI ( const COLLADASW::URI& sourceUri )
 
1350
        {
 
1351
                // Target file
 
1352
                const COLLADABU::URI& outputFile = mDocumentExporter->getOutputFileUri();
 
1353
                
 
1354
                String relativePath = mDocumentExporter->getOptions().getImageDirectory();
 
1355
                relativePath.append("/");
 
1356
                relativePath.append( COLLADABU::Utils::toString( mCopyImageCounter++ ) );
 
1357
                relativePath.append("_");
 
1358
                relativePath.append( sourceUri.getPathFile() );
 
1359
 
 
1360
                COLLADASW::URI targetUri ( outputFile, relativePath);
 
1361
 
 
1362
                // Get the pure file name of the source file and set 
 
1363
                // the source file name to the target path
 
1364
//              targetUri.setPathFile ( sourceUri.getPathFile () );
 
1365
                targetUri.setScheme ( COLLADASW::URI::SCHEME_FILE );
 
1366
 
 
1367
                // Generate the target file name
 
1368
                return targetUri;
 
1369
        }
 
1370
 
 
1371
 
 
1372
    //---------------------------------------------------------------
 
1373
    void EffectExporter::blendColor ( COLLADASW::ColorOrTexture & colorOrTexture, Color blendColor, double ammount )
 
1374
    {
 
1375
        if ( colorOrTexture.isColor() )
 
1376
        {
 
1377
            COLLADASW::Color & color = colorOrTexture.getColor();
 
1378
 
 
1379
            color.set ( color.getRed() + ( blendColor[ 0 ] - color.getRed() ) * ammount,
 
1380
                        color.getGreen() + ( blendColor[ 1 ] - color.getGreen() ) * ammount,
 
1381
                        color.getBlue() + ( blendColor[ 2 ] - color.getBlue() ) * ammount,
 
1382
                        color.getAlpha()
 
1383
                      );
 
1384
        }
 
1385
    }
 
1386
 
 
1387
 
 
1388
 
 
1389
        bool EffectExporter::MaterialChannelPair::operator<( const EffectExporter::MaterialChannelPair & rhs ) const
 
1390
        {
 
1391
                if ( mMaterial < rhs.mMaterial )
 
1392
                        return true;
 
1393
                if ( mMaterial > rhs.mMaterial )
 
1394
                        return false;
 
1395
 
 
1396
                if ( mChannel < rhs.mChannel )
 
1397
                        return true;
 
1398
                if ( mChannel > rhs.mChannel )
 
1399
                        return false;
 
1400
 
 
1401
                return false;
 
1402
        }
 
1403
}