1 /*
2     Copyright (c) 2008-2009 NetAllied Systems GmbH
3 
4 	This file is part of COLLADAStreamWriter.
5 
6     Licensed under the MIT Open Source License,
7     for details please see LICENSE file or the website
8     http://www.opensource.org/licenses/mit-license.php
9 */
10 
11 #include "COLLADASWEffectProfile.h"
12 #include "COLLADASWExtra.h"
13 #include "COLLADASWTechnique.h"
14 #include "COLLADASWParamTemplate.h"
15 #include <algorithm>
16 
17 namespace COLLADASW
18 {
19 
20     const String EffectProfile::DEFAULT_TECHNIQUE_SID = "common";
21 
22 
23     //---------------------------------------------------------------
EffectProfile(StreamWriter * streamWriter,const String & effectProfileId)24     EffectProfile::EffectProfile ( StreamWriter* streamWriter, const String& effectProfileId )
25     : ElementWriter ( streamWriter )
26     , mEffectProfileId ( effectProfileId )
27     , mTechniqueSid ( DEFAULT_TECHNIQUE_SID )
28     , mProfileType ( EffectProfile::COMMON )
29     , mShaderType ( EffectProfile::UNSPECIFIED )
30     , mReflectivity ( -1 )
31     , mOpaque ( UNSPECIFIED_OPAQUE )
32     , mTransparency ( -1 )
33     , mIndexOfRefraction ( -1 )
34     , mShininess ( -1 )
35     , mTransparentSid (  )
36     , mEmissionSid (  )
37     , mAmbientSid (  )
38     , mDiffuseSid (  )
39     , mSpecularSid (  )
40     , mReflectiveSid (  )
41     , mShininessSid (  )
42     , mReflectivitySid (  )
43     , mTransparencySid (  )
44     , mIndexOfRefractionSid (  )
45     , mExtraTechniqueColorOrTextureEntries (  )
46     , mIncludeSid ( "" )
47     {}
48 
49     //---------------------------------------------------------------
addProfileElements()50     void EffectProfile::addProfileElements ()
51     {
52         switch ( mProfileType )
53         {
54         case EffectProfile::COMMON:
55             addProfileCommon ();
56             break;
57         case EffectProfile::CG:
58             addProfileCG ();
59             break;
60         case EffectProfile::GLSL:
61             addProfileGLSL ();
62             break;
63         case EffectProfile::GLES:
64             addProfileGLES ();
65             break;
66         }
67     }
68 
69     //---------------------------------------------------------------
openProfile()70     void EffectProfile::openProfile ()
71     {
72         mProfileCloser = mSW->openElement ( getProfileTypeName( mProfileType ) );
73         mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_ID, getEffectProfileId () );
74     }
75 
76     //---------------------------------------------------------------
closeProfile()77     void EffectProfile::closeProfile ()
78     {
79 		// Export the user defined profile extra data elements.
80         mProfileExtra.addExtraTechniques ( mSW );
81 
82         // Close the current profile.
83         mProfileCloser.close();
84     }
85 
86     //---------------------------------------------------------------
addProfileCG()87     void EffectProfile::addProfileCG ()
88     {
89         if ( !mCode.empty() )
90         {
91             mSW->openElement ( CSWC::CSW_ELEMENT_CODE );
92             if ( !mCodeSid.empty() )
93                 mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_SID, mCodeSid );
94             mSW->appendText ( Utils::translateToXML ( mCode ) );
95             mSW->closeElement();
96         }
97 
98         if ( !mIncludeSid.empty() )
99         {
100             mSW->openElement ( CSWC::CSW_ELEMENT_INCLUDE );
101             mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_SID, mIncludeSid );
102             mSW->appendURIAttribute ( CSWC::CSW_ATTRIBUTE_URL, mIncludeURI.getURIString() );
103             mSW->closeElement ();
104         }
105     }
106 
107     //---------------------------------------------------------------
addProfileGLSL()108     void EffectProfile::addProfileGLSL ()
109     {
110         if ( !mCode.empty() )
111         {
112             mSW->openElement ( CSWC::CSW_ELEMENT_CODE );
113             if ( !mCodeSid.empty() )
114                 mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_SID, mCodeSid );
115             mSW->appendText ( Utils::translateToXML ( mCode ) );
116             mSW->closeElement();
117         }
118 
119         if ( !mIncludeSid.empty() )
120         {
121             mSW->openElement ( CSWC::CSW_ELEMENT_INCLUDE );
122             mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_SID, mIncludeSid );
123             mSW->appendURIAttribute ( CSWC::CSW_ATTRIBUTE_URL, mIncludeURI.getURIString() );
124             mSW->closeElement ();
125         }
126     }
127 
128     //---------------------------------------------------------------
addProfileGLES()129     void EffectProfile::addProfileGLES ()
130     {
131 
132     }
133 
134     //---------------------------------------------------------------
addProfileCommon()135     void EffectProfile::addProfileCommon ()
136     {
137         addSamplers();
138 
139         if ( !mTechniqueSid.empty() )
140         {
141             mSW->openElement ( CSWC::CSW_ELEMENT_TECHNIQUE );
142             mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_SID, mTechniqueSid );
143 
144             if ( mShaderType != EffectProfile::UNSPECIFIED )
145             {
146                 TagCloser shaderTypeCloser = mSW->openElement ( getShaderTypeName ( mShaderType ) );
147 
148                 addColorOrTexture ( CSWC::CSW_ELEMENT_EMISSION, mEmission, mEmissionSid );
149                 addColorOrTexture ( CSWC::CSW_ELEMENT_AMBIENT, mAmbient, mAmbientSid );
150                 addColorOrTexture ( CSWC::CSW_ELEMENT_DIFFUSE, mDiffuse, mDiffuseSid );
151                 addColorOrTexture ( CSWC::CSW_ELEMENT_SPECULAR, mSpecular, mSpecularSid );
152                 addFloat ( CSWC::CSW_ELEMENT_SHININESS, mShininess, mShininessSid );
153                 addColorOrTexture ( CSWC::CSW_ELEMENT_REFLECTIVE, mReflective, mReflectiveSid );
154                 addFloat ( CSWC::CSW_ELEMENT_REFLECTIVITY, mReflectivity, mReflectivitySid );
155                 addColorOrTexture ( CSWC::CSW_ELEMENT_TRANSPARENT, mTransparent, mTransparentSid, StringPairList(), mOpaque );
156                 addFloat ( CSWC::CSW_ELEMENT_TRANSPARENCY, mTransparency, mTransparencySid );
157                 addFloat ( CSWC::CSW_ELEMENT_INDEX_OF_REFRACTION, mIndexOfRefraction, mIndexOfRefractionSid );
158 
159                 shaderTypeCloser.close ();
160             }
161 
162             // Adds extra technique tags to the current effect and writes the child elements with the
163             // given colorOrTexture element in the tags.
164             addExtraTechniqueColorOrTextures ( mExtraTechniqueColorOrTextureEntries );
165 
166             // Export the user defined technique extra data elements.
167             mProfileTechniqueExtra.addExtraTechniques ( mSW );
168 
169             // CSWC::CSW_ELEMENT_TECHNIQUE
170             mSW->closeElement ();
171         }
172     }
173 
174     //---------------------------------------------------------------
addExtraTechniqueColorOrTextures(const ExtraColorOrTextureEntryByProfileName & entriesByProfileName) const175     void EffectProfile::addExtraTechniqueColorOrTextures (
176 		const ExtraColorOrTextureEntryByProfileName& entriesByProfileName ) const
177     {
178 		if ( !entriesByProfileName.empty() )
179 		{
180 			// Open the extra tag
181 			COLLADASW::Extra colladaExtra ( mSW );
182 			colladaExtra.openExtra();
183 
184 			for ( ExtraColorOrTextureEntryByProfileName::const_iterator it = entriesByProfileName.begin();
185 				it != entriesByProfileName.end(); ++it )
186 			{
187 				const String& profileName = it->first;
188 				const std::vector<ExtraColorOrTextureEntry>& entries = it->second;
189 
190 				// Open the technique tag
191 				COLLADASW::Technique colladaTechnique ( mSW );
192 				colladaTechnique.openTechnique( profileName );
193 
194 				for ( std::vector<ExtraColorOrTextureEntry>::const_iterator it = entries.begin(); it != entries.end(); ++it )
195 				{
196 					const ExtraColorOrTextureEntry& entry = *it;
197 
198 					if ( entry.colorOrTexture.isTexture() )
199 					{
200 						const Texture& texture = entry.colorOrTexture.getTexture();
201 
202 						const String& childElement = texture.getChildElementName();
203 
204 						// Add the texture
205 						addColorOrTexture( childElement, entry.colorOrTexture, entry.elementSid, entry.attributes  );
206 					}
207 				}
208 
209 				// Close the technique tag
210 				colladaTechnique.closeTechnique();
211 			}
212 
213 			// Close the extra tag
214 			colladaExtra.closeExtra();
215 		}
216 	}
217 
218     //---------------------------------------------------------------
addSamplers()219     void EffectProfile::addSamplers()
220     {
221         addSampler ( mEmission );
222         addSampler ( mAmbient );
223         addSampler ( mDiffuse );
224         addSampler ( mSpecular );
225         addSampler ( mReflective );
226         addSampler ( mTransparent );
227 		for ( ExtraColorOrTextureEntryByProfileName::const_iterator it = mExtraTechniqueColorOrTextureEntries.begin();
228 				it != mExtraTechniqueColorOrTextureEntries.end(); ++it )
229 		{
230 			const std::vector<ExtraColorOrTextureEntry>& entries = it->second;
231 
232 			for ( std::vector<ExtraColorOrTextureEntry>::const_iterator it = entries.begin(); it != entries.end(); ++it )
233 			{
234 				const ExtraColorOrTextureEntry& entry = *it;
235 
236 				if ( entry.colorOrTexture.isTexture() )
237 				{
238 					addSampler( entry.colorOrTexture );
239 				}
240 			}
241 		}
242     }
243 
244 
245     //---------------------------------------------------------------
addSampler(const ColorOrTexture & colorOrTexture)246     void EffectProfile::addSampler ( const ColorOrTexture& colorOrTexture )
247     {
248         // Don't implement double textures!
249         if ( colorOrTexture.isTexture() )
250         {
251             // TODO: add COLLADASW 1.5 texture
252             const Texture& texture = colorOrTexture.getTexture();
253 
254             // Have a look, if we have this surface already written.
255             std::vector<String>::const_iterator iter;
256             iter = find ( mSampledImages.begin(), mSampledImages.end(), texture.getImageId() );
257             if ( iter == mSampledImages.end() )
258             {
259                 // Push the id of the image in the list of sampled surface image ids
260                 mSampledImages.push_back ( texture.getImageId() );
261 
262 				texture.getSampler().addInNewParam ( mSW );
263             }
264 
265         }
266     }
267 
268 
269     //---------------------------------------------------------------
getShaderTypeName(ShaderType shaderType)270     const String& EffectProfile::getShaderTypeName ( ShaderType shaderType )
271     {
272         switch ( shaderType )
273         {
274         case EffectProfile::CONSTANT:
275             return CSWC::CSW_ELEMENT_CONSTANT;
276         case EffectProfile::LAMBERT:
277             return CSWC::CSW_ELEMENT_LAMBERT;
278         case EffectProfile::PHONG:
279             return CSWC::CSW_ELEMENT_PHONG;
280         case EffectProfile::BLINN:
281             return CSWC::CSW_ELEMENT_BLINN;
282         default:
283             return CSWC::EMPTY_STRING;
284         }
285     }
286 
287     //---------------------------------------------------------------
getProfileTypeName(ProfileType profileType)288     const String& EffectProfile::getProfileTypeName ( ProfileType profileType )
289     {
290         switch ( profileType )
291         {
292         case EffectProfile::COMMON:
293             return CSWC::CSW_ELEMENT_PROFILE_COMMON;
294         case EffectProfile::CG:
295             return CSWC::CSW_ELEMENT_PROFILE_CG;
296         case EffectProfile::GLES:
297             return CSWC::CSW_ELEMENT_PROFILE_GLES;
298         case EffectProfile::GLSL:
299             return CSWC::CSW_ELEMENT_PROFILE_GLSL;
300         default:
301             return CSWC::EMPTY_STRING;
302         }
303     }
304 
305     //---------------------------------------------------------------
getOpaqueString(Opaque opaque)306     const String& EffectProfile::getOpaqueString ( Opaque opaque )
307     {
308         switch ( opaque )
309         {
310         case A_ONE:
311             return CSWC::CSW_OPAQUE_TYPE_A_ONE;
312         case RGB_ZERO:
313             return CSWC::CSW_OPAQUE_TYPE_RGB_ZERO;
314         case RGB_ONE:
315             return CSWC::CSW_OPAQUE_TYPE_RGB_ONE;
316         case A_ZERO:
317             return CSWC::CSW_OPAQUE_TYPE_A_ZERO;
318         default:
319             return EMPTY_STRING;
320         }
321     }
322 
323     //---------------------------------------------------------------
addColorOrTexture(const String & elementName,const ColorOrTexture & colorOrTexture,const String & elementSid,StringPairList attributes,Opaque opaque) const324     void EffectProfile::addColorOrTexture (
325         const String& elementName,
326         const ColorOrTexture& colorOrTexture,
327         const String& elementSid,
328 		StringPairList attributes,
329         Opaque opaque
330 		) const
331     {
332         bool isColor = colorOrTexture.isColor();
333         bool isTexture =  colorOrTexture.isTexture();
334         if ( ! ( isColor || isTexture ) ) return;
335 
336         mSW->openElement ( elementName );
337 
338         if ( opaque != UNSPECIFIED_OPAQUE )
339             mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_OPAQUE, getOpaqueString ( opaque ) );
340 
341 		for ( StringPairList::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
342 		{
343 			const std::pair<String, String>& pair = *it;
344 			const String& attributeName = pair.first;
345 			const String& attributeValue = pair.second;
346 			mSW->appendAttribute ( attributeName, attributeValue );
347 		}
348 
349         if ( isTexture )
350         {
351             const Texture& texture = colorOrTexture.getTexture();
352 
353             mSW->openElement ( CSWC::CSW_ELEMENT_TEXTURE );
354             mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_TEXTURE, texture.getSamplerSid() );
355             mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_TEXCOORD, texture.getTexcoord() );
356 
357             texture.addExtraTechniques ( mSW );
358 
359             mSW->closeElement();
360         }
361         else if ( isColor )
362         {
363             mSW->openElement ( CSWC::CSW_ELEMENT_COLOR );
364             if ( !elementSid.empty() )
365                 mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_SID, elementSid );
366             const Color& color = colorOrTexture.getColor();
367             mSW->appendValues ( color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha() );
368             mSW->closeElement();
369         }
370 
371         mSW->closeElement();
372     }
373 
374     //---------------------------------------------------------------
addFloat(const String & elementName,const double & number,const String & elementSid) const375     void EffectProfile::addFloat (
376         const String& elementName,
377         const double& number,
378         const String& elementSid ) const
379     {
380         if ( number >= 0 )
381         {
382             mSW->openElement ( elementName );
383             mSW->openElement ( CSWC::CSW_ELEMENT_FLOAT );
384             if ( !elementSid.empty() )
385                 mSW->appendAttribute( CSWC::CSW_ATTRIBUTE_SID, elementSid );
386             mSW->appendValues ( number );
387             mSW->closeElement ();
388             mSW->closeElement ();
389         }
390     }
391 
openTechnique(const String & techniqueSid)392     void EffectProfile::openTechnique( const String& techniqueSid )
393     {
394         mTechniqueCloser = mSW->openElement ( CSWC::CSW_ELEMENT_TECHNIQUE );
395         mSW->appendAttribute ( CSWC::CSW_ATTRIBUTE_SID, techniqueSid );
396     }
397 
closeTechnique()398     void EffectProfile::closeTechnique()
399     {
400         mTechniqueCloser.close ();
401     }
402 
setTechniqueSid(const String & techniqueSid)403     void EffectProfile::setTechniqueSid( const String& techniqueSid )
404     {
405         mTechniqueSid = techniqueSid;
406     }
407 
getTechniqueSid() const408     const String& EffectProfile::getTechniqueSid() const
409     {
410         return mTechniqueSid;
411     }
412 
setShaderType(ShaderType shaderType)413     void EffectProfile::setShaderType( ShaderType shaderType )
414     {
415         mShaderType = shaderType;
416     }
417 
getShaderType() const418     COLLADASW::EffectProfile::ShaderType EffectProfile::getShaderType() const
419     {
420         return mShaderType;
421     }
422 
getCode() const423     const String& EffectProfile::getCode() const
424     {
425         return mCode;
426     }
427 
setInclude(const URI & includeUri,const String & sid)428     void EffectProfile::setInclude ( const URI &includeUri, const String &sid/*="" */ )
429     {
430         mIncludeURI = includeUri; mIncludeSid = sid;
431     }
432 
setCode(const String & code,const String & sid)433     void EffectProfile::setCode ( const String &code, const String &sid/*="" */ )
434     {
435         mCode = code; mCodeSid = sid;
436     }
437 
setEmission(const ColorOrTexture & emission,const bool useDefaultSid,const String & sid)438     void EffectProfile::setEmission ( const ColorOrTexture& emission, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
439     {
440         mEmission = emission;
441         if ( useDefaultSid ) mEmissionSid = CSWC::CSW_ELEMENT_EMISSION;
442         else mEmissionSid = sid;
443     }
444 
getEmissionDefaultSid()445     const String& EffectProfile::getEmissionDefaultSid()
446     {
447         return CSWC::CSW_ELEMENT_EMISSION;
448     }
449 
getEmission()450     ColorOrTexture& EffectProfile::getEmission()
451     {
452         return mEmission;
453     }
454 
setAmbient(const ColorOrTexture & ambient,const bool useDefaultSid,const String & sid)455     void EffectProfile::setAmbient( const ColorOrTexture& ambient, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
456     {
457         mAmbient = ambient;
458         if ( useDefaultSid ) mAmbientSid = CSWC::CSW_ELEMENT_AMBIENT;
459         else mAmbientSid = sid;
460     }
461 
getAmbientDefaultSid()462     const String& EffectProfile::getAmbientDefaultSid()
463     {
464         return CSWC::CSW_ELEMENT_AMBIENT;
465     }
466 
getAmbient()467     ColorOrTexture& EffectProfile::getAmbient()
468     {
469         return mAmbient;
470     }
471 
setDiffuse(const ColorOrTexture & diffuse,const bool useDefaultSid,const String & sid)472     void EffectProfile::setDiffuse( const ColorOrTexture& diffuse, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
473     {
474         mDiffuse = diffuse;
475         if ( useDefaultSid ) mDiffuseSid = CSWC::CSW_ELEMENT_DIFFUSE;
476         else mDiffuseSid = sid;
477     }
478 
getDiffuseDefaultSid()479     const String& EffectProfile::getDiffuseDefaultSid()
480     {
481         return CSWC::CSW_ELEMENT_DIFFUSE;
482     }
483 
getDiffuse()484     ColorOrTexture& EffectProfile::getDiffuse()
485     {
486         return mDiffuse;
487     }
488 
setSpecular(const ColorOrTexture & specular,const bool useDefaultSid,const String & sid)489     void EffectProfile::setSpecular( const ColorOrTexture& specular, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
490     {
491         mSpecular = specular;
492         if ( useDefaultSid ) mSpecularSid = CSWC::CSW_ELEMENT_SPECULAR;
493         else mSpecularSid = sid;
494     }
495 
getSpecularDefaultSid()496     const String& EffectProfile::getSpecularDefaultSid()
497     {
498         return CSWC::CSW_ELEMENT_SPECULAR;
499     }
500 
getSpecular()501     ColorOrTexture& EffectProfile::getSpecular()
502     {
503         return mSpecular;
504     }
505 
setShininess(double shininess,const bool useDefaultSid,const String & sid)506     void EffectProfile::setShininess( double shininess, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
507     {
508         mShininess = shininess;
509         if ( useDefaultSid ) mShininessSid = CSWC::CSW_ELEMENT_SHININESS;
510         else mShininessSid = sid;
511     }
512 
getShininess() const513     double EffectProfile::getShininess() const
514     {
515         return mShininess;
516     }
517 
setReflective(const ColorOrTexture & reflective,const bool useDefaultSid,const String & sid)518     void EffectProfile::setReflective( const ColorOrTexture& reflective, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
519     {
520         mReflective = reflective;
521         if ( useDefaultSid ) mReflectiveSid = CSWC::CSW_ELEMENT_REFLECTIVE;
522         else mReflectiveSid = sid;
523     }
524 
getReflectiveDefaultSid()525     const String& EffectProfile::getReflectiveDefaultSid()
526     {
527         return CSWC::CSW_ELEMENT_REFLECTIVE;
528     }
529 
getReflective()530     ColorOrTexture& EffectProfile::getReflective()
531     {
532         return mReflective;
533     }
534 
setReflectivity(double reflectivity,const bool useDefaultSid,const String & sid)535     void EffectProfile::setReflectivity( double reflectivity, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
536     {
537         mReflectivity = reflectivity;
538         if ( useDefaultSid ) mReflectivitySid = CSWC::CSW_ELEMENT_REFLECTIVITY;
539         else mReflectivitySid = sid;
540     }
541 
getReflectivityDefaultSid()542     const String& EffectProfile::getReflectivityDefaultSid()
543     {
544         return CSWC::CSW_ELEMENT_REFLECTIVITY;
545     }
546 
setTransparent(const ColorOrTexture & transparent,const bool useDefaultSid,const String & sid)547     void EffectProfile::setTransparent( const ColorOrTexture& transparent, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
548     {
549         mTransparent = transparent;
550         if ( useDefaultSid ) mTransparentSid = CSWC::CSW_ELEMENT_TRANSPARENT;
551         else mTransparentSid = sid;
552     }
553 
getTransparentDefaultSid()554     const String& EffectProfile::getTransparentDefaultSid()
555     {
556         return CSWC::CSW_ELEMENT_TRANSPARENT;
557     }
558 
getTransparent()559     ColorOrTexture& EffectProfile::getTransparent()
560     {
561         return mTransparent;
562     }
563 
setOpaque(Opaque opaque)564     void EffectProfile::setOpaque( Opaque opaque )
565     {
566         mOpaque = opaque;
567     }
568 
getOpaque()569     COLLADASW::EffectProfile::Opaque EffectProfile::getOpaque()
570     {
571         return mOpaque;
572     }
573 
setTransparency(double transparency,const bool useDefaultSid,const String & sid)574     void EffectProfile::setTransparency( double transparency, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
575     {
576         mTransparency = transparency;
577         if ( useDefaultSid ) mTransparencySid = CSWC::CSW_ELEMENT_TRANSPARENCY;
578         else mTransparencySid = sid;
579     }
580 
setIndexOfRefraction(double indexOfRefrection,const bool useDefaultSid,const String & sid)581     void EffectProfile::setIndexOfRefraction( double indexOfRefrection, const bool useDefaultSid /*= false*/, const String& sid /*= "" */ )
582     {
583         mIndexOfRefraction = indexOfRefrection;
584         if ( useDefaultSid ) mIndexOfRefractionSid = CSWC::CSW_ELEMENT_INDEX_OF_REFRACTION;
585         else mIndexOfRefractionSid = sid;
586     }
587 
getIndexOfRefractionSid()588     const String& EffectProfile::getIndexOfRefractionSid()
589     {
590         return CSWC::CSW_ELEMENT_INDEX_OF_REFRACTION;
591     }
592 
addExtraTechniqueColorOrTexture(const ColorOrTexture & colorOrTexture,const StringPairList & attributes,const String & sid)593     void EffectProfile::addExtraTechniqueColorOrTexture( const ColorOrTexture& colorOrTexture, const StringPairList& attributes , const String& sid /*= "" */)
594     {
595 		ExtraColorOrTextureEntry entry;
596 		entry.colorOrTexture = colorOrTexture;
597 		entry.elementSid = sid;
598 		entry.attributes = attributes;
599 		if ( entry.colorOrTexture.isTexture() )
600 		{
601 			const String& profileName = entry.colorOrTexture.getTexture().getProfileName();
602 	        mExtraTechniqueColorOrTextureEntries[profileName].push_back( entry );
603 		}
604     }
605 } //namespace COLLADASW
606