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

Revision 9759, 60.0 kB (checked in by robert, 6 years ago)

From Roland Smeenk, "Attached are two small fixes:
-I changed the SET of COLLADA_BOOST_INCLUDE_DIR to use findpath, so users may override this setting if they choose not to build against to precompiled boost libraries delivered with the Collada DOM.

-Changed daeRMaterials.cpp to prevent a compiler warning about a potentially uninitialized variable."

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