root/OpenSceneGraph/trunk/src/osgPlugins/dae/daeRMaterials.cpp @ 13041

Revision 13041, 51.0 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Copyright 2006 Sony Computer Entertainment Inc.
3 *
4 * Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
5 * file except in compliance with the License. You may obtain a copy of the License at:
6 * http://research.scea.com/scea_shared_source_license.html
7 *
8 * Unless required by applicable law or agreed to in writing, software distributed under the License
9 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10 * implied. See the License for the specific language governing permissions and limitations under the
11 * License.
12 */
13
14#include "daeReader.h"
15#include "ReaderWriterDAE.h"
16
17#include <dae.h>
18#include <dae/daeSIDResolver.h>
19#include <dae/domAny.h>
20#include <dom/domCOLLADA.h>
21#include <dom/domProfile_COMMON.h>
22#include <dom/domConstants.h>
23
24#include <osg/BlendColor>
25#include <osg/BlendFunc>
26#include <osg/Texture2D>
27#include <osg/TexEnv>
28#include <osg/LightModel>
29#include <osgDB/Registry>
30#include <osgDB/ReadFile>
31
32#include <sstream>
33
34using namespace osgDAE;
35
36template <typename T>
37void daeReader::getTransparencyCounts(daeDatabase* database, int& zero, int& one) const
38{
39    std::vector<T*> constantVec;
40    database->typeLookup(constantVec);
41
42    for (size_t i = 0; i < constantVec.size(); ++i)
43    {
44        if (const domCommon_transparent_type* pTransparent = constantVec[i]->getTransparent())
45        {
46            domFx_opaque_enum opaque = pTransparent->getOpaque();
47            if (opaque == FX_OPAQUE_ENUM_RGB_ZERO)
48            {
49                ++one;
50                continue;
51            }
52        }
53
54        if (const domCommon_float_or_param_type* pTransparency = constantVec[i]->getTransparency())
55        {
56            float transparency;
57
58            domFloat transparencyParam = 1.0;
59            if (pTransparency->getFloat())
60            {
61                transparency = pTransparency->getFloat()->getValue();
62            }
63            else if (pTransparency->getParam() &&
64                GetFloatParam(pTransparency->getParam()->getRef(), transparencyParam))
65            {
66                transparency = transparencyParam;
67            }
68            else
69            {
70                continue;
71            }
72
73            if (transparency < 0.01f)
74            {
75                ++zero;
76            }
77            else if (transparency > 0.99f)
78            {
79                ++one;
80            }
81        }
82
83    }
84
85}
86
87bool daeReader::findInvertTransparency(daeDatabase* database) const
88{
89    int zero = 0, one = 0;
90    getTransparencyCounts<domProfile_COMMON::domTechnique::domConstant>(database, zero, one);
91    getTransparencyCounts<domProfile_COMMON::domTechnique::domLambert>(database, zero, one);
92    getTransparencyCounts<domProfile_COMMON::domTechnique::domPhong>(database, zero, one);
93    getTransparencyCounts<domProfile_COMMON::domTechnique::domBlinn>(database, zero, one);
94
95    return zero > one;
96}
97
98// <bind_material>
99// elements:
100// 0..*    <param>
101//        name
102//        sid
103//        semantic
104//        type
105// 1    <technique_common>
106//        0..*    <instance_material>
107//                symbol
108//                target
109//                sid
110//                name
111// 0..*    <technique>
112//        profile
113// 0..* <extra>
114//        id
115//        name
116//        type
117void daeReader::processBindMaterial( domBind_material *bm, domGeometry *geom, osg::Geode *geode, osg::Geode *cachedGeode )
118{
119    if (bm->getTechnique_common() == NULL )
120    {
121        OSG_WARN << "No COMMON technique for bind_material" << std::endl;
122        return;
123    }
124
125    for (size_t i =0; i < geode->getNumDrawables(); i++)
126    {
127        osg::Drawable* drawable = geode->getDrawable(i);
128        std::string materialName = drawable->getName();
129        osg::Geometry *cachedGeometry = dynamic_cast<osg::Geometry*>(cachedGeode->getDrawable(i)->asGeometry());
130
131        domInstance_material_Array &ima = bm->getTechnique_common()->getInstance_material_array();
132        std::string symbol;
133        bool found = false;
134        for ( size_t j = 0; j < ima.getCount(); j++)
135        {
136            symbol = ima[j]->getSymbol();
137            if (symbol.compare(materialName) == 0)
138            {
139                found = true;
140                domMaterial *mat = daeSafeCast< domMaterial >(getElementFromURI( ima[j]->getTarget()));
141                if (mat)
142                {
143                    // Check material cache if this material already exists
144                    osg::StateSet* ss;
145                    domMaterialStateSetMap::iterator iter = _materialMap.find( mat );
146                    if (iter != _materialMap.end() )
147                    {
148                        // Reuse material
149                        ss = iter->second.get();
150                    }
151                    else
152                    {
153                        // Create new material
154                        ss = new osg::StateSet;
155                        processMaterial(ss, mat);
156                        _materialMap.insert(std::make_pair(mat, ss));
157                    }
158                    drawable->setStateSet(ss);
159                    // Need to process bind_vertex_inputs here
160                    // 1. Clear the texcoord arrays and associated texcoord vertex indices
161                    // from the current (cloned) drawable.
162                    osg::Geometry *clonedGeometry = drawable->asGeometry();
163                    if (NULL == clonedGeometry)
164                    {
165                        OSG_WARN << "Failed to convert drawable to geometry object" << std::endl;
166                        break;
167                    }
168                    clonedGeometry->getTexCoordArrayList().clear();
169
170                    // 2. For each possible texture unit find the correct texcoord array and
171                    // indices from the cached drawable and place in the cloned drawable
172                    // in the correct texture unit slot
173                    unsigned int textureUnit(0);
174                    if (copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], AMBIENT_OCCLUSION_UNIT, textureUnit)) ++textureUnit;
175                    if (copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], MAIN_TEXTURE_UNIT     , textureUnit)) ++textureUnit;
176                    if (copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], TRANSPARENCY_MAP_UNIT , textureUnit)) ++textureUnit;
177                }
178                else
179                {
180                    OSG_WARN << "Failed to locate <material> with id " << ima[i]->getTarget().getURI() << std::endl;
181                }
182
183                break;
184            }
185        }
186        if (!found)
187        {
188            OSG_WARN << "Failed to locate <instance_material> with symbol " << materialName << std::endl;
189        }
190    }
191}
192
193// <material>
194// attributes:
195// 0..1    id
196// 0..1    name
197// elements:
198// 0..1 <asset>
199// 1    <instance_effect>
200// 0..* <extra>
201void    daeReader::processMaterial(osg::StateSet *ss, domMaterial *mat )
202{
203    _currentInstance_effect = mat->getInstance_effect();
204    if (mat && mat->getName()) {
205        ss->setName(mat->getName());
206    }
207    domEffect *effect = daeSafeCast< domEffect >( getElementFromURI( _currentInstance_effect->getUrl() ) );
208    if (effect)
209    {
210        processEffect(ss, effect);
211
212        //TODO: process all of the setParams that could happen here in the material. ESP. the textures
213    }
214    else
215    {
216        OSG_WARN << "Failed to locate effect " << mat->getInstance_effect()->getUrl().getURI() << std::endl;
217    }
218}
219
220// <effect>
221// attributes:
222// 1    id
223// 0..1    name
224// elements:
225// 0..1 <asset>
226// 0..* <annotate>
227// 0..* <image>
228// 0..* <newparam>
229// 1..*    <fx_profile_abstract>
230// 0..* <extra>
231void daeReader::processEffect(osg::StateSet *ss, domEffect *effect )
232{
233    bool hasCOMMON = false;
234
235    for ( size_t i = 0; i < effect->getFx_profile_abstract_array().getCount(); i++ )
236    {
237        domProfile_COMMON *pc = daeSafeCast< domProfile_COMMON >( effect->getFx_profile_abstract_array()[i] );
238        if (pc != NULL )
239        {
240            if (hasCOMMON )
241            {
242                OSG_WARN << "Effect already has a profile_COMMON. Skipping this one" << std::endl;
243                continue;
244            }
245            _currentEffect = effect;
246            processProfileCOMMON(ss, pc);
247            hasCOMMON = true;
248            continue;
249        }
250
251        OSG_WARN << "unsupported effect profile " << effect->getFx_profile_abstract_array()[i]->getTypeName() << std::endl;
252    }
253}
254
255// <profile_COMMON>
256// elements:
257// 0..* <image>, <newparam>
258// 1    <technique>
259//        attributes:
260//        elements:
261//        0..1    <asset>
262//        0..*    <image>, <newparam>
263//        1        <constant>, <lambert>, <phong>, <blinn>
264//        0..*    <extra>
265// 0..* <extra>
266void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc )
267{
268    domProfile_COMMON::domTechnique *teq = pc->getTechnique();
269
270    domProfile_COMMON::domTechnique::domConstant *c = teq->getConstant();
271    domProfile_COMMON::domTechnique::domLambert *l = teq->getLambert();
272    domProfile_COMMON::domTechnique::domPhong *p = teq->getPhong();
273    domProfile_COMMON::domTechnique::domBlinn *b = teq->getBlinn();
274
275    ss->setMode( GL_CULL_FACE, osg::StateAttribute::ON ); // Cull Back faces
276
277    // See if there are any extra's that are supported by OpenSceneGraph
278    const domExtra_Array& ExtraArray = pc->getExtra_array();
279    size_t NumberOfExtras = ExtraArray.getCount();
280    size_t CurrentExtra;
281    for (CurrentExtra = 0; CurrentExtra < NumberOfExtras; CurrentExtra++)
282    {
283        const domTechnique_Array& TechniqueArray = ExtraArray[CurrentExtra]->getTechnique_array();
284        size_t NumberOfTechniques = TechniqueArray.getCount();
285        size_t CurrentTechnique;
286        for (CurrentTechnique = 0; CurrentTechnique < NumberOfTechniques; CurrentTechnique++)
287        {
288            //  <technique profile="GOOGLEEARTH">
289            //      <double_sided>0</double_sided>
290            //  </technique>
291            if (strcmp(TechniqueArray[CurrentTechnique]->getProfile(), "GOOGLEEARTH") == 0)
292            {
293                const daeElementRefArray& ElementArray = TechniqueArray[CurrentTechnique]->getContents();
294                size_t NumberOfElements = ElementArray.getCount();
295                size_t CurrentElement;
296                for (CurrentElement = 0; CurrentElement < NumberOfElements; CurrentElement++)
297                {
298                    domAny* pAny = (domAny*)ElementArray[CurrentElement].cast();
299                    if (strcmp(pAny->getElementName(), "double_sided") == 0)
300                    {
301                        daeString Value = pAny->getValue();
302                        if (strcmp(Value, "1") == 0)
303                            ss->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
304                    }
305                }
306            }
307        }
308    }
309
310    osg::ref_ptr< osg::Material > mat = new osg::Material();
311    // <blinn>
312    // elements:
313    // 0..1 <emission>
314    // 0..1 <ambient>
315    // 0..1 <diffuse>
316    // 0..1 <specular>
317    // 0..1 <shininess>
318    // 0..1 <reflective>
319    // 0..1 <reflectivity>
320    // 0..1 <transparent>
321    // 0..1 <transparency>
322    // 0..1 <index_of_refraction>
323    if (b != NULL )
324    {
325        osg::Texture2D *EmissionStateAttribute = NULL;
326        osg::Texture2D *AmbientStateAttribute = NULL;
327        osg::Texture2D *DiffuseStateAttribute = NULL;
328        processColorOrTextureType(ss, b->getEmission(), osg::Material::EMISSION, mat.get(), NULL, &EmissionStateAttribute );
329        if (NULL != EmissionStateAttribute)
330            OSG_WARN << "Currently no support for <texture> in Emission channel " << std::endl;
331
332        processColorOrTextureType(ss, b->getAmbient(), osg::Material::AMBIENT, mat.get(), NULL,  &AmbientStateAttribute );
333
334        processColorOrTextureType(ss, b->getDiffuse(), osg::Material::DIFFUSE, mat.get(), NULL, &DiffuseStateAttribute );
335        if (DiffuseStateAttribute != NULL )
336        {
337            if (AmbientStateAttribute != NULL )
338            {
339                // Set the ambient and diffuse colour white so that the incoming fragment colour ends up as a
340                // lit white colour. I modulate both textures onto this to approximate the lighting equation.
341                // Using a zero diffuse and then an ADD of the diffuse texture seems overlit to me.
342                mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
343                mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
344                // Use the ambient texture map as an occlusion map.
345                unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? AMBIENT_OCCLUSION_UNIT : 0);
346                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
347                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
348                ss->setTextureAttribute( textureUnit, AmbientStateAttribute );
349                // Modulate in the diffuse texture
350                textureUnit = _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 1;
351                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
352                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
353                ss->setTextureAttribute( textureUnit, DiffuseStateAttribute );
354            }
355            else
356            {
357                // Set the diffuse colour white so that the incoming fragment colour ends up as the global diffuse lighting colour
358                // plus any constant ambient contribution after the lighting calculation. This means that I am modulating the the
359                // ambient with the texture as well but I cannot see a way of avoiding that.
360                mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
361                unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0);
362                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
363                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
364                ss->setTextureAttribute( textureUnit, DiffuseStateAttribute );
365            }
366        }
367        else
368        {
369            if (NULL != AmbientStateAttribute  )
370                OSG_WARN << "Ambient occlusion map only supported when diffuse texture also specified" << std::endl;
371        }
372
373        if (processColorOrTextureType(ss, b->getSpecular(), osg::Material::SPECULAR, mat.get(), b->getShininess() ) && (NULL != DiffuseStateAttribute) )
374        {
375            // Diffuse texture will defeat specular highlighting
376            // So postpone specular - Not sure if I should do this here
377            // beacuse it will override any global light model states
378            osg::LightModel* lightmodel = new osg::LightModel;
379            lightmodel->setColorControl(osg::LightModel::SEPARATE_SPECULAR_COLOR);
380            ss->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
381        }
382
383        processTransparencySettings(b->getTransparent(), b->getTransparency(), ss, mat.get(), _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0 );
384    }
385    // <phong>
386    // elements:
387    // 0..1 <emission>
388    // 0..1 <ambient>
389    // 0..1 <diffuse>
390    // 0..1 <specular>
391    // 0..1 <shininess>
392    // 0..1 <reflective>
393    // 0..1 <reflectivity>
394    // 0..1 <transparent>
395    // 0..1 <transparency>
396    // 0..1 <index_of_refraction>
397    else if (p != NULL )
398    {
399        osg::Texture2D *EmissionStateAttribute = NULL;
400        osg::Texture2D *AmbientStateAttribute = NULL;
401        osg::Texture2D *DiffuseStateAttribute = NULL;
402        processColorOrTextureType(ss, p->getEmission(), osg::Material::EMISSION, mat.get(), NULL, &EmissionStateAttribute );
403        if (NULL != EmissionStateAttribute)
404            OSG_WARN << "Currently no support for <texture> in Emission channel " << std::endl;
405
406        processColorOrTextureType(ss, p->getAmbient(), osg::Material::AMBIENT, mat.get(), NULL,  &AmbientStateAttribute );
407
408        processColorOrTextureType(ss, p->getDiffuse(), osg::Material::DIFFUSE, mat.get(), NULL, &DiffuseStateAttribute );
409        if (DiffuseStateAttribute != NULL )
410        {
411            if (AmbientStateAttribute != NULL )
412            {
413                // Set the ambient and diffuse colour white so that the incoming fragment colour ends up as a
414                // lit white colour. I modulate both textures onto this to approximate the lighting equation.
415                // Using a zero diffuse and then an ADD of the diffuse texture seems overlit to me.
416                mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
417                mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
418                // Use the ambient texture map as an occlusion map.
419                unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? AMBIENT_OCCLUSION_UNIT : 0);
420                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
421                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
422                ss->setTextureAttribute( textureUnit, AmbientStateAttribute );
423                // Modulate in the diffuse texture
424                textureUnit = _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 1;
425                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
426                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
427                ss->setTextureAttribute( textureUnit, DiffuseStateAttribute );
428            }
429            else
430            {
431                // Set the diffuse colour white so that the incoming fragment colour ends up as the global diffuse lighting colour
432                // plus any constant ambient contribution after the lighting calculation. This means that I am modulating the the
433                // ambient with the texture as well but I cannot see a way of avoiding that.
434                mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
435                unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0);
436                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
437                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
438                ss->setTextureAttribute( textureUnit, DiffuseStateAttribute );
439            }
440        }
441        else
442        {
443            if (NULL != AmbientStateAttribute  )
444                OSG_WARN << "Ambient occlusion map only supported when diffuse texture also specified" << std::endl;
445        }
446
447        if (processColorOrTextureType(ss, p->getSpecular(), osg::Material::SPECULAR, mat.get(), p->getShininess() ) && (NULL != DiffuseStateAttribute) )
448        {
449            // Diffuse texture will defeat specular highlighting
450            // So postpone specular - Not sure if I should do this here
451            // beacuse it will override any global light model states
452            osg::LightModel* lightmodel = new osg::LightModel;
453            lightmodel->setColorControl(osg::LightModel::SEPARATE_SPECULAR_COLOR);
454            ss->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
455        }
456
457        processTransparencySettings(p->getTransparent(), p->getTransparency(), ss, mat.get(), _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0 );
458    }
459    // <lambert>
460    // elements:
461    // 0..1 <emission>
462    // 0..1 <ambient>
463    // 0..1 <diffuse>
464    // 0..1 <reflective>
465    // 0..1 <reflectivity>
466    // 0..1 <transparent>
467    // 0..1 <transparency>
468    // 0..1 <index_of_refraction>
469    else if (l != NULL )
470    {
471        osg::Texture2D *EmissionStateAttribute = NULL;
472        osg::Texture2D *AmbientStateAttribute = NULL;
473        osg::Texture2D *DiffuseStateAttribute = NULL;
474        processColorOrTextureType(ss, l->getEmission(), osg::Material::EMISSION, mat.get(), NULL, &EmissionStateAttribute );
475        if (NULL != EmissionStateAttribute)
476            OSG_WARN << "Currently no support for <texture> in Emission channel " << std::endl;
477
478        processColorOrTextureType(ss, l->getAmbient(), osg::Material::AMBIENT, mat.get(), NULL,  &AmbientStateAttribute);
479
480        processColorOrTextureType(ss, l->getDiffuse(), osg::Material::DIFFUSE, mat.get(), NULL, &DiffuseStateAttribute );
481        if (DiffuseStateAttribute != NULL )
482        {
483            if (AmbientStateAttribute != NULL )
484            {
485                // Set the ambient and diffuse colour white so that the incoming fragment colour ends up as a
486                // lit white colour. I modulate both textures onto this to approximate the lighting equation.
487                // Using a zero diffuse and then an ADD of the diffuse texture seems overlit to me.
488                mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
489                mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
490                // Use the ambient texture map as an occlusion map.
491                unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? AMBIENT_OCCLUSION_UNIT : 0);
492                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
493                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
494                ss->setTextureAttribute( textureUnit, AmbientStateAttribute );
495                // Modulate in the diffuse texture
496                textureUnit = _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 1;
497                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
498                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
499                ss->setTextureAttribute( textureUnit, DiffuseStateAttribute );
500            }
501            else
502            {
503                // Set the diffuse colour white so that the incoming fragment colour ends up as the global diffuse lighting colour
504                // plus any constant ambient contribution after the lighting calculation. This means that I am modulating the the
505                // ambient with the texture as well but I cannot see a way of avoiding that.
506                mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
507                unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0);
508                ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
509                ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) );
510                ss->setTextureAttribute( textureUnit, DiffuseStateAttribute );
511            }
512        }
513        else
514        {
515            if (NULL != AmbientStateAttribute  )
516                OSG_WARN << "Ambient occlusion map only supported when diffuse texture also specified" << std::endl;
517        }
518
519        processTransparencySettings(l->getTransparent(), l->getTransparency(), ss, mat.get(), _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0 );
520    }
521    // <constant>
522    // elements:
523    // 0..1 <emission>
524    // 0..1 <reflective>
525    // 0..1 <reflectivity>
526    // 0..1 <transparent>
527    // 0..1 <transparency>
528    // 0..1 <index_of_refraction>
529    else if (c != NULL )
530    {
531        osg::Texture2D *sa = NULL;
532        processColorOrTextureType(ss, c->getEmission(), osg::Material::EMISSION, mat.get(), NULL, &sa );
533        if (sa != NULL )
534        {
535            unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0);
536            ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE );
537            ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::REPLACE) );
538            ss->setTextureAttribute( textureUnit, sa );
539        }
540
541        // Use the emission colour as the main colour in transparency calculations
542        mat->setDiffuse(osg::Material::FRONT_AND_BACK, mat->getEmission(osg::Material::FRONT_AND_BACK));
543
544        processTransparencySettings(c->getTransparent(), c->getTransparency(), ss, mat.get(), _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0 );
545
546        // Kill the lighting
547        mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0, 0.0, 0.0, 1.0));
548        mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0, 0.0, 0.0, 1.0));
549    }
550    ss->setAttribute( mat.get() );
551}
552
553// colorOrTexture
554// 1  of
555//         <color>
556//        <param>
557//        attributes:
558//        1        ref
559//        <texture>
560//        attributes:
561//        1        texture
562//        1        texcoord
563//        0..*    extra
564bool daeReader::processColorOrTextureType(const osg::StateSet* ss,
565                                          domCommon_color_or_texture_type *cot,
566                                          osg::Material::ColorMode channel,
567                                          osg::Material *mat,
568                                          domCommon_float_or_param_type *fop,
569                                          osg::Texture2D **sa,
570                                          bool blinn)
571{
572    if (cot == NULL )
573    {
574        return false;
575    }
576    bool retVal = false;
577
578    std::string texCoordSet;
579
580    //osg::StateAttribute *sa = NULL;
581    //TODO: Make all channels process <param ref=""> type of value
582    if (channel == osg::Material::EMISSION )
583    {
584        if (cot->getColor() != NULL )
585        {
586            domFloat4 &f4 = cot->getColor()->getValue();
587            mat->setEmission( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) );
588            retVal = true;
589        }
590        else if (cot->getParam() != NULL)
591        {
592            domFloat4 f4;
593            if (GetFloat4Param(cot->getParam()->getRef(), f4))
594            {
595                mat->setEmission( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) );
596                retVal = true;
597            }
598        }
599        else if (cot->getTexture() != NULL)
600        {
601            if (sa != NULL)
602            {
603                *sa = processTexture( cot->getTexture(), ss, MAIN_TEXTURE_UNIT);
604                retVal = true;
605            }
606            else
607                OSG_WARN << "Currently no support for <texture> in Emission channel " << std::endl;
608        }
609        else
610        {
611            OSG_WARN << "Missing <color>, <param> or <texture> in Emission channel " << std::endl;
612        }
613    }
614    else if (channel == osg::Material::AMBIENT )
615    {
616        if (cot->getColor() != NULL )
617        {
618            domFloat4 &f4 = cot->getColor()->getValue();
619            mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) );
620            retVal = true;
621        }
622        else if (cot->getParam() != NULL)
623        {
624            domFloat4 f4;
625            if (cot->getParam()->getRef() != 0 && GetFloat4Param(cot->getParam()->getRef(), f4))
626            {
627                mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) );
628                retVal = true;
629            }
630        }
631        else if (cot->getTexture() != NULL)
632        {
633            if (sa != NULL)
634                *sa = processTexture( cot->getTexture(), ss, AMBIENT_OCCLUSION_UNIT);
635            else
636            {
637                OSG_WARN << "Currently no support for <texture> in Ambient channel " << std::endl;
638                mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( 0.2f, 0.2f, 0.2f, 1.0f ) );
639            }
640            retVal = true;
641       }
642        else
643        {
644            OSG_WARN << "Missing <color>, <param> or <texture> in Ambient channel " << std::endl;
645        }
646    }
647    else if (channel == osg::Material::DIFFUSE )
648    {
649        if (cot->getColor() != NULL )
650        {
651            domFloat4 &f4 = cot->getColor()->getValue();
652            mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) );
653            retVal = true;
654        }
655        else if (cot->getTexture() != NULL)
656        {
657            if (sa != NULL)
658                *sa = processTexture( cot->getTexture(), ss, MAIN_TEXTURE_UNIT);
659            else
660            {
661                OSG_WARN << "Currently no support for <texture> in Diffuse channel " << std::endl;
662                mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 0.8f, 0.8f, 0.8f, 1.0f ) );
663            }
664            domExtra *extra = cot->getTexture()->getExtra();
665            if (extra != NULL && extra->getType() != NULL && strcmp( extra->getType(), "color" ) == 0 )
666            {
667                //the extra data for osg. Diffuse color can happen with a texture.
668                for ( unsigned int i = 0; i < extra->getTechnique_array().getCount(); i++ )
669                {
670                    domTechnique *teq = extra->getTechnique_array()[i];
671                    if (strcmp( teq->getProfile(), "SCEI" ) == 0 )
672                    {
673                        osg::Vec4 col;
674                        domAny *dcol = (domAny*)(daeElement*)teq->getContents()[0];
675                        std::istringstream diffuse_colour((const char *)dcol->getValue());
676                        diffuse_colour >> col.r() >> col.g() >> col.b() >> col.a();
677                        mat->setDiffuse( osg::Material::FRONT_AND_BACK, col );
678                        break;
679                    }
680                }
681            }
682            retVal = true;
683        }
684        else if (cot->getParam() != NULL)
685        {
686            domFloat4 f4;
687            if (GetFloat4Param(cot->getParam()->getRef(), f4))
688            {
689                mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) );
690                retVal = true;
691            }
692        }
693        else
694        {
695            OSG_WARN << "Missing <color>, <param> or <texture> in Diffuse channel " << std::endl;
696        }
697    }
698    else if (channel == osg::Material::SPECULAR )
699    {
700        if (cot->getColor() != NULL )
701        {
702            domFloat4 &f4 = cot->getColor()->getValue();
703            mat->setSpecular( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) );
704            retVal = true;
705        }
706        else if (cot->getParam() != NULL)
707        {
708            domFloat4 f4;
709            if (GetFloat4Param(cot->getParam()->getRef(), f4))
710            {
711                mat->setSpecular( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) );
712                retVal = true;
713            }
714        }
715        else if (cot->getTexture() != NULL)
716        {
717            OSG_WARN << "Currently no support for <texture> in Specular channel " << std::endl;
718        }
719        else
720        {
721            OSG_WARN << "Missing <color>, <param> or <texture> in Specular channel " << std::endl;
722        }
723
724        if (fop != NULL && fop->getFloat() != NULL )
725        {
726            float shininess = fop->getFloat()->getValue();
727            if (blinn)
728            {
729                // If the blinn mode is in the range [0,1] rescale it to [0,128]
730                if (shininess < 1)
731                    shininess *= 128.0f;
732            }
733            mat->setShininess( osg::Material::FRONT_AND_BACK, shininess );
734        }
735    }
736
737    return retVal;
738}
739
740bool daeReader::GetFloat4Param(xsNCName Reference, domFloat4 &f4) const
741{
742    std::string MyReference = Reference;
743
744    MyReference.insert(0, "./");
745    daeSIDResolver Resolver(_currentEffect, MyReference.c_str());
746    daeElement *el = Resolver.getElement();
747    if (NULL == el)
748            return false;
749
750    if (NULL != _currentInstance_effect)
751    {
752        // look here first for setparams
753        // I am sure there must be a better way of doing this
754        // Maybe the Collada DAE guys can give us a parameter management mechanism !
755        const domInstance_effect::domSetparam_Array& SetParamArray = _currentInstance_effect->getSetparam_array();
756        size_t NumberOfSetParams = SetParamArray.getCount();
757        for (size_t i = 0; i < NumberOfSetParams; i++)
758        {
759            // Just do a simple comaprison of the ref strings for the time being
760            if (0 == strcmp(SetParamArray[i]->getRef(), Reference))
761            {
762                if (NULL != SetParamArray[i]->getFx_basic_type_common() && (NULL != SetParamArray[i]->getFx_basic_type_common()->getFloat4()))
763                {
764                    f4 = SetParamArray[i]->getFx_basic_type_common()->getFloat4()->getValue();
765                    return true;
766                }
767            }
768        }
769    }
770
771    domCommon_newparam_type *cnp = daeSafeCast< domCommon_newparam_type >( el );
772    domFx_newparam_common *npc = daeSafeCast< domFx_newparam_common >( el );
773    if ((cnp != NULL) && (NULL != cnp->getFloat4()))
774    {
775        f4 = cnp->getFloat4()->getValue();
776        return true;
777    }
778    else if ((npc != NULL) && (NULL != npc->getFx_basic_type_common()) && (NULL != npc->getFx_basic_type_common()->getFloat4()))
779    {
780        f4 = npc->getFx_basic_type_common()->getFloat4()->getValue();
781        return true;
782    }
783    else
784        return false;
785}
786
787bool daeReader::GetFloatParam(xsNCName Reference, domFloat &f) const
788{
789    std::string MyReference = Reference;
790
791    MyReference.insert(0, "./");
792    daeSIDResolver Resolver(_currentEffect, MyReference.c_str());
793    daeElement *el = Resolver.getElement();
794    if (NULL == el)
795        return false;
796
797    if (NULL != _currentInstance_effect)
798    {
799        // look here first for setparams
800        // I am sure there must be a better way of doing this
801        // Maybe the Collada DAE guys can give us a parameter management mechanism !
802        const domInstance_effect::domSetparam_Array& SetParamArray = _currentInstance_effect->getSetparam_array();
803        size_t NumberOfSetParams = SetParamArray.getCount();
804        for (size_t i = 0; i < NumberOfSetParams; i++)
805        {
806            // Just do a simple comaprison of the ref strings for the time being
807            if (0 == strcmp(SetParamArray[i]->getRef(), Reference))
808            {
809                if (NULL != SetParamArray[i]->getFx_basic_type_common() && (NULL != SetParamArray[i]->getFx_basic_type_common()->getFloat()))
810                {
811                    f = SetParamArray[i]->getFx_basic_type_common()->getFloat()->getValue();
812                    return true;
813                }
814            }
815        }
816    }
817
818    domCommon_newparam_type *cnp = daeSafeCast< domCommon_newparam_type >( el );
819    domFx_newparam_common *npc = daeSafeCast< domFx_newparam_common >( el );
820    if ((cnp != NULL) && (NULL != cnp->getFloat()))
821    {
822        f = cnp->getFloat()->getValue();
823        return true;
824    }
825    else if ((npc != NULL) && (NULL != npc->getFx_basic_type_common()) && (NULL != npc->getFx_basic_type_common()->getFloat()))
826    {
827        f = npc->getFx_basic_type_common()->getFloat()->getValue();
828        return true;
829    }
830    else
831        return false;
832}
833
834osg::Texture::WrapMode getWrapMode(domFx_sampler_wrap_common domWrap)
835{
836    switch (domWrap)
837    {
838    case FX_SAMPLER_WRAP_COMMON_WRAP:
839        return osg::Texture::REPEAT;
840    case FX_SAMPLER_WRAP_COMMON_MIRROR:
841        return osg::Texture::MIRROR;
842    case FX_SAMPLER_WRAP_COMMON_CLAMP:
843        return osg::Texture::CLAMP_TO_EDGE;
844    case FX_SAMPLER_WRAP_COMMON_NONE:
845    case FX_SAMPLER_WRAP_COMMON_BORDER:
846        return osg::Texture::CLAMP_TO_BORDER;
847    default:
848        OSG_WARN << "Unrecognised domFx_sampler_wrap_common." << std::endl;
849    }
850    return osg::Texture::CLAMP;
851}
852
853osg::Texture::FilterMode getFilterMode(domFx_sampler_filter_common domFilter, bool allowMipMap)
854{
855    switch (domFilter)
856    {
857    case FX_SAMPLER_FILTER_COMMON_NONE:
858    case FX_SAMPLER_FILTER_COMMON_NEAREST:
859        return osg::Texture::NEAREST;
860    case FX_SAMPLER_FILTER_COMMON_LINEAR:
861        return osg::Texture::LINEAR;
862    case FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_NEAREST:
863        return allowMipMap ? osg::Texture::NEAREST_MIPMAP_NEAREST : osg::Texture::NEAREST;
864    case FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_NEAREST:
865        return allowMipMap ? osg::Texture::LINEAR_MIPMAP_NEAREST : osg::Texture::LINEAR;
866    case FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_LINEAR:
867        return allowMipMap ? osg::Texture::NEAREST_MIPMAP_LINEAR : osg::Texture::NEAREST;
868    case FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_LINEAR:
869        return allowMipMap ? osg::Texture::LINEAR_MIPMAP_LINEAR : osg::Texture::LINEAR;
870    default:
871        OSG_WARN << "Unrecognised domFx_sampler_filter_common." << std::endl;
872    }
873    return osg::Texture::LINEAR;
874}
875
876std::string daeReader::processImagePath(const domImage* pDomImage) const
877{
878    if (pDomImage == NULL)
879    {
880        OSG_WARN << "Could not locate image for texture" << std::endl;
881        return std::string();
882    }
883
884    //Got a sampler and a surface and an imaged. Time to create the texture stuff for osg
885    if (pDomImage->getInit_from())
886    {
887        pDomImage->getInit_from()->getValue().validate();
888        if (strcmp(pDomImage->getInit_from()->getValue().getProtocol(), "file") == 0)
889        {
890            std::string path = pDomImage->getInit_from()->getValue().pathDir() +
891                pDomImage->getInit_from()->getValue().pathFile();
892            path = ReaderWriterDAE::ConvertColladaCompatibleURIToFilePath(path);
893            if (path.empty())
894            {
895                OSG_WARN << "Unable to get path from URI." << std::endl;
896                return std::string();
897            }
898#ifdef WIN32
899            // If the path has a drive specifier or a UNC name then strip the leading /
900            if (path.size() > 2 && (path[2] == ':' || (path[1] == '/' && path[2] == '/')))
901                return path.substr(1, std::string::npos);
902#endif
903            return path;
904        }
905        else
906        {
907            OSG_WARN << "Only images with a \"file\" scheme URI are supported in this version." << std::endl;
908        }
909    }
910    else
911    {
912        OSG_WARN << "Embedded image data is not supported in this version." << std::endl;
913    }
914    return std::string();
915}
916
917float luminance(const osg::Vec4& color)
918{
919    return
920        color.r() * 0.212671f +
921        color.g() * 0.715160f +
922        color.b() * 0.072169f;
923}
924
925osg::Image* daeReader::processImageTransparency(const osg::Image* srcImg, domFx_opaque_enum opaque, float transparency) const
926{
927    int s = srcImg->s();
928    int t = srcImg->t();
929    unsigned char* pixels = new unsigned char [s * t];
930
931    if (opaque == FX_OPAQUE_ENUM_RGB_ZERO)
932    {
933        for (int i = 0; i < t; ++i)
934        {
935            for (int j = 0; j < s; ++j)
936            {
937                osg::Vec4 color(srcImg->getColor(j, i));
938
939                pixels[i * s + j] = static_cast<unsigned char>(
940                    (1.0f - luminance(color) * transparency) * 255.0f);
941            }
942        }
943    }
944    else
945    {
946        bool texHasAlpha = false;
947        switch (srcImg->getPixelFormat())
948        {
949        case GL_ALPHA:
950        case GL_LUMINANCE_ALPHA:
951        case GL_RGBA:
952        case GL_BGRA:
953            texHasAlpha = true;
954        }
955
956        if (texHasAlpha)
957        {
958            for (int i = 0; i < t; ++i)
959            {
960                for (int j = 0; j < s; ++j)
961                {
962                    osg::Vec4 color(srcImg->getColor(j, i));
963
964                    pixels[i * s + j] = static_cast<unsigned char>(
965                        color.a() * transparency * 255.0f);
966                }
967            }
968        }
969        else
970        {
971            for (int i = 0; i < t; ++i)
972            {
973                for (int j = 0; j < s; ++j)
974                {
975                    osg::Vec4 color(srcImg->getColor(j, i));
976
977                    pixels[i * s + j] = static_cast<unsigned char>(
978                        luminance(color) * transparency * 255.0f);
979                }
980            }
981        }
982    }
983
984    osg::Image* transparentImage = new osg::Image;
985    transparentImage->setWriteHint(osg::Image::STORE_INLINE);
986    transparentImage->setImage(s, t, 1, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, pixels, osg::Image::USE_NEW_DELETE);
987
988    return transparentImage;
989}
990
991osg::Texture2D* daeReader::processTexture(
992    domCommon_color_or_texture_type_complexType::domTexture *tex,
993    const osg::StateSet* ss, TextureUnitUsage tuu,
994    domFx_opaque_enum opaque, float transparency)
995{
996    TextureParameters parameters;
997    parameters.transparent = tuu == TRANSPARENCY_MAP_UNIT;
998    parameters.opaque = opaque;
999    parameters.transparency = transparency;
1000
1001    //find the newparam for the sampler based on the texture attribute
1002    domFx_sampler2D_common *sampler = NULL;
1003    domFx_surface_common *surface = NULL;
1004    domImage *dImg = NULL;
1005
1006    std::string target = std::string("./") + std::string(tex->getTexture());
1007    OSG_NOTICE<<"processTexture("<<target<<")"<<std::endl;
1008
1009    daeSIDResolver res1( _currentEffect, target.c_str() );
1010    daeElement *el = res1.getElement();
1011
1012    if (el == NULL )
1013    {
1014        OSG_WARN << "Could not locate newparam for texture sampler2D \"" << tex->getTexture() <<
1015            "\". Checking if data does incorrect linking straight to the image" << std::endl;
1016        _dae->getDatabase()->getElement( (daeElement**)&dImg, 0, tex->getTexture(), "image" );
1017        if (dImg != NULL )
1018        {
1019            OSG_WARN << "Direct image link found. Data is incorrect but will continue to load texture" << std::endl;
1020        }
1021    }
1022    else
1023    {
1024        domCommon_newparam_type *cnp = daeSafeCast< domCommon_newparam_type >( el );
1025        domFx_newparam_common *npc = daeSafeCast< domFx_newparam_common >( el );
1026
1027        if (cnp != NULL )
1028        {
1029            sampler = cnp->getSampler2D();
1030        }
1031        else if (npc != NULL )
1032        {
1033            sampler = npc->getFx_basic_type_common()->getSampler2D();
1034        }
1035
1036        if (sampler == NULL )
1037        {
1038            OSG_WARN << "Wrong newparam type. Expected sampler2D" << std::endl;
1039            return NULL;
1040        }
1041
1042        //find the newparam for the surface based on the sampler2D->source value
1043        target = std::string("./") + std::string( sampler->getSource()->getValue() );
1044        daeSIDResolver res2( _currentEffect, target.c_str() );
1045        el = res2.getElement();
1046        if (el == NULL )
1047        {
1048            OSG_WARN << "Could not locate newparam for source " << sampler->getSource()->getValue() << std::endl;
1049            return NULL;
1050        }
1051        cnp = daeSafeCast< domCommon_newparam_type >( el );
1052        npc = daeSafeCast< domFx_newparam_common >( el );
1053
1054        if (cnp != NULL )
1055        {
1056            surface = cnp->getSurface();
1057        }
1058        else if (npc != NULL )
1059        {
1060            surface = npc->getFx_basic_type_common()->getSurface();
1061        }
1062
1063        if (surface == NULL )
1064        {
1065            OSG_WARN << "Wrong newparam type. Expected surface" << std::endl;
1066            return NULL;
1067        }
1068
1069        //look for the domImage based on the surface initialization stuff
1070        daeIDRef &ref = surface->getFx_surface_init_common()->getInit_from_array()[0]->getValue();
1071        dImg = daeSafeCast< domImage >( getElementFromIDRef( ref ) );
1072    }
1073
1074    parameters.filename = processImagePath(dImg);
1075    if (parameters.filename.empty())
1076    {
1077        return NULL;
1078    }
1079
1080    //set texture parameters
1081    if (sampler)
1082    {
1083        if (sampler->getWrap_s())
1084        {
1085            parameters.wrap_s = getWrapMode(sampler->getWrap_s()->getValue());
1086        }
1087        if (sampler->getWrap_t())
1088        {
1089            parameters.wrap_t = getWrapMode(sampler->getWrap_s()->getValue());
1090        }
1091
1092        if (sampler->getMinfilter() && sampler->getMinfilter()->getValue() != FX_SAMPLER_FILTER_COMMON_NONE)
1093        {
1094            parameters.filter_min = getFilterMode(sampler->getMinfilter()->getValue(), true);
1095        }
1096        if (sampler->getMagfilter() && sampler->getMagfilter()->getValue() != FX_SAMPLER_FILTER_COMMON_NONE)
1097        {
1098            parameters.filter_mag = getFilterMode(sampler->getMagfilter()->getValue(), false);
1099        }
1100
1101        if (sampler->getBorder_color() != NULL )
1102        {
1103            const domFloat4& col = sampler->getBorder_color()->getValue();
1104            parameters.border.set(col[0], col[1], col[2], col[3]);
1105        }
1106    }
1107
1108    osg::Texture2D* t2D = NULL;
1109    TextureParametersMap::const_iterator mapIt = _textureParamMap.find(parameters);
1110    if (mapIt != _textureParamMap.end())
1111    {
1112        t2D = mapIt->second.get();
1113    }
1114    else
1115    {
1116        osg::ref_ptr<osg::Image> img = osgDB::readRefImageFile(parameters.filename);
1117
1118        if (!img.valid())
1119        {
1120            _textureParamMap[parameters] = NULL;
1121            return NULL;
1122        }
1123
1124        OSG_INFO<<"  processTexture(..) - readImage("<<parameters.filename<<")"<<std::endl;
1125
1126        if (tuu == TRANSPARENCY_MAP_UNIT)
1127        {
1128            img = processImageTransparency(img.get(), opaque, transparency);
1129        }
1130
1131        t2D = new osg::Texture2D(img.get());
1132
1133        t2D->setWrap( osg::Texture::WRAP_S, parameters.wrap_s);
1134        t2D->setWrap( osg::Texture::WRAP_T, parameters.wrap_t);
1135        t2D->setFilter( osg::Texture::MIN_FILTER, parameters.filter_min);
1136        t2D->setFilter( osg::Texture::MAG_FILTER, parameters.filter_mag);
1137        t2D->setBorderColor(parameters.border);
1138
1139        _textureParamMap[parameters] = t2D;
1140    }
1141
1142    _texCoordSetMap[TextureToCoordSetMap::key_type(ss, tuu)] = tex->getTexcoord();
1143
1144    return t2D;
1145}
1146
1147
1148/*
1149Collada 1.4.1 Specification (2nd Edition) Patch Release Notes: Revision C Release notes
1150
1151In <blinn>, <constant>, <lambert>, and <phong>, the child element <transparent> now has an
1152optional opaque attribute whose valid values are:
1153• A_ONE (the default): Takes the transparency information from the color’s alpha channel, where the value 1.0 is opaque.
1154• RGB_ZERO: Takes the transparency information from the color’s red, green, and blue channels, where the value 0.0 is opaque,
1155with each channel modulated independently.
1156In the Specification, this is described in the “FX Reference” chapter in the
1157common_color_or_texture_type entry, along with a description of how transparency works in the
1158“Getting Started with COLLADA FX” chapter in the “Determining Transparency” section.
1159
1160
1161Collada Digital Asset Schema Release 1.5.0 Release Notes
1162
1163The <transparent> element’s opaque attribute now allows, in addition to A_ONE and RGB_ZERO, the following values:
1164• A_ZERO: Takes the transparency information from the color’s alpha channel, where the value 0.0 is opaque.
1165• RGB_ONE: Takes the transparency information from the color’s red, green, and blue channels, where the value 1.0
1166* is opaque, with each channel modulated independently.
1167* When we update to a version of the dom using that schema we will need to modify the code below
1168*/
1169
1170void daeReader::processTransparencySettings( domCommon_transparent_type *ctt,
1171                                            domCommon_float_or_param_type *pTransparency,
1172                                            osg::StateSet *ss,
1173                                            osg::Material *material,
1174                                            unsigned int diffuseTextureUnit  )
1175{
1176    if (ss == NULL)
1177        return;
1178
1179    if (NULL == ctt && NULL == pTransparency)
1180        return;
1181
1182    float transparency = 1.0f;
1183    if (pTransparency)
1184    {
1185        if (pTransparency->getFloat())
1186        {
1187            transparency = pTransparency->getFloat()->getValue();
1188        }
1189        else if (pTransparency->getParam())
1190        {
1191            domFloat transparencyParam;
1192            if (GetFloatParam(pTransparency->getParam()->getRef(), transparencyParam))
1193            {
1194                transparency = transparencyParam;
1195            }
1196        }
1197
1198        if (_invertTransparency)
1199        {
1200            transparency = 1.0f - transparency;
1201        }
1202    }
1203
1204    osg::Texture2D* pTransparentTexture = NULL;
1205    osg::Vec4 transparentColor(transparency, transparency, transparency, transparency);
1206
1207    // Fix up defaults according to "Determining Transparency" chapter of 1.4.1 spec
1208    domFx_opaque_enum opaque = FX_OPAQUE_ENUM_A_ONE;
1209    if (ctt)
1210    {
1211        opaque = ctt->getOpaque();
1212        if (ctt->getColor())
1213        {
1214            const domFx_color_common& domColorValue = ctt->getColor()->getValue();
1215            transparentColor.set(
1216                domColorValue.get(0),
1217                domColorValue.get(1),
1218                domColorValue.get(2),
1219                domColorValue.get(3));
1220
1221            if (opaque == FX_OPAQUE_ENUM_RGB_ZERO)
1222            {
1223                transparentColor.set(
1224                    1.0f - transparentColor.r() * transparency,
1225                    1.0f - transparentColor.g() * transparency,
1226                    1.0f - transparentColor.b() * transparency,
1227                    1.0f - luminance(transparentColor) * transparency);
1228            }
1229            else
1230            {
1231                float a = transparentColor.a() * transparency;
1232                transparentColor.set(a, a, a, a);
1233            }
1234        }
1235        else if (ctt->getTexture())
1236        {
1237            pTransparentTexture = processTexture(ctt->getTexture(), ss, TRANSPARENCY_MAP_UNIT, opaque, transparency);
1238        }
1239    }
1240
1241    if (pTransparentTexture)
1242    {
1243        ss->setTextureAttributeAndModes(TRANSPARENCY_MAP_UNIT, pTransparentTexture);
1244        ss->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
1245    }
1246    else
1247    {
1248        bool strictTransparency = _pluginOptions.strictTransparency;
1249        if (!strictTransparency)
1250        {
1251            const osg::Texture* pMainTexture = dynamic_cast<osg::Texture*>(
1252                ss->getTextureAttribute(diffuseTextureUnit, osg::StateAttribute::TEXTURE));
1253            bool haveTranslucentTexture = pMainTexture &&
1254                pMainTexture->getImage(0) && pMainTexture->getImage(0)->isImageTranslucent();
1255            strictTransparency = !haveTranslucentTexture;
1256        }
1257
1258        if (strictTransparency)
1259        {
1260            if (transparentColor == osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f))
1261            {
1262                return;
1263            }
1264
1265            ss->setAttributeAndModes(new osg::BlendColor(transparentColor));
1266            ss->setAttributeAndModes(new osg::BlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR));
1267        }
1268        else
1269        {
1270            ss->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
1271        }
1272    }
1273
1274    ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
1275}
1276
1277bool daeReader::copyTextureCoordinateSet(const osg::StateSet* ss, const osg::Geometry* cachedGeometry, osg::Geometry* clonedGeometry, const domInstance_material* im, TextureUnitUsage tuu, unsigned int textureUnit)
1278{
1279    unsigned int localTextureUnit( _pluginOptions.usePredefinedTextureUnits ? tuu : textureUnit);
1280    if (!ss->getTextureAttribute(localTextureUnit, osg::StateAttribute::TEXTURE))
1281        return false;
1282
1283    const std::string& texCoordSetName = _texCoordSetMap
1284        [TextureToCoordSetMap::key_type(ss, tuu)];
1285    if (texCoordSetName.empty()) return false;
1286
1287    const domInstance_material::domBind_vertex_input_Array &bvia = im->getBind_vertex_input_array();
1288    size_t k;
1289    for (k = 0; k < bvia.getCount(); k++)
1290    {
1291        if (!strcmp(bvia[k]->getSemantic(), texCoordSetName.c_str()) && !strcmp(bvia[k]->getInput_semantic(), COMMON_PROFILE_INPUT_TEXCOORD))
1292        {
1293            unsigned set = bvia[k]->getInput_set();
1294            if (set < cachedGeometry->getNumTexCoordArrays())
1295            {
1296            clonedGeometry->setTexCoordData(localTextureUnit, cachedGeometry->getTexCoordData(set));
1297            }
1298            else
1299            {
1300                OSG_WARN << "Texture coordinate set " << set << " not found." << std::endl;
1301            }
1302            break;
1303        }
1304    }
1305    if (k == bvia.getCount())
1306    {
1307        OSG_WARN << "Failed to find matching <bind_vertex_input> for " << texCoordSetName << std::endl;
1308        if (cachedGeometry->getNumTexCoordArrays())
1309        {
1310        clonedGeometry->setTexCoordData(localTextureUnit, cachedGeometry->getTexCoordData(0));
1311        }
1312    }
1313    return true;
1314}
Note: See TracBrowser for help on using the browser.