1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2009 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
40 #pragma GCC diagnostic ignored "-Wold-style-cast"
43 #include "OSGColladaEffect.h"
45 #if defined(OSG_WITH_COLLADA) || defined(OSG_DO_DOC)
47 #include "OSGColladaLog.h"
48 #include "OSGColladaGlobal.h"
49 #include "OSGColladaImage.h"
50 #include "OSGColladaInstanceEffect.h"
51 #include "OSGColladaMaterial.h"
52 #include "OSGColladaSampler2D.h"
54 #include "OSGGeometry.h"
55 #include "OSGChunkMaterial.h"
56 #include "OSGBlendChunk.h"
57 #include "OSGDepthChunk.h"
58 #include "OSGMaterialChunk.h"
59 #include "OSGTextureEnvChunk.h"
61 #include "OSGColladaDomProfileHandler.h"
62 #include "OSGColladaExtraHandler.h"
63 #include "OSGColladaHandlerFactory.h"
65 #include <dom/domEffect.h>
66 #include <dom/domInstance_effect.h>
67 #include <dom/domProfile_COMMON.h>
68 #include <dom/domProfile_GLSL.h>
69 #include <dom/domProfile_CG.h>
71 // It is not clear what is the best way to handle <transparent>/<texture>, so
72 // OSG_COLLADA_TRANSPARENT_MODE allows choosing between implementations
73 // to experiment. See below for what the modes do.
75 #define OSG_COLLADA_TRANSPARENT_MODE 1
76 // #define OSG_COLLADA_TRANSPARENT_MODE 2
80 ColladaInstInfoTransitPtr
ColladaEffect::ColladaEffectInstInfo::create(
81 ColladaMaterial
*colInstParent
,
82 ColladaInstanceEffect
*colInst
)
84 return ColladaInstInfoTransitPtr(
85 new ColladaEffectInstInfo(colInstParent
, colInst
));
88 void ColladaEffect::ColladaEffectInstInfo::process(void)
90 SFATAL
<< "ColladaEffectInstInfo::process called!" << std::endl
;
93 ColladaEffect::ColladaEffectInstInfo::ColladaEffectInstInfo(
94 ColladaMaterial
*colInstParent
,
95 ColladaInstanceEffect
*colInst
) :
97 Inherited(colInstParent
,
102 ColladaEffect::ColladaEffectInstInfo::~ColladaEffectInstInfo(void)
106 // ===========================================================================
108 ColladaElementRegistrationHelper
ColladaEffect::_regHelper(
109 &ColladaEffect::create
,
113 ColladaElementTransitPtr
ColladaEffect::create(daeElement
*elem
,
114 ColladaGlobal
*global
)
116 return ColladaElementTransitPtr(new ColladaEffect(elem
, global
));
119 void ColladaEffect::read(ColladaElement
*colElemParent
)
121 OSG_COLLADA_LOG(("ColladaEffect::read\n"));
123 domEffectRef effect
= getDOMElementAs
<domEffect
>();
124 const domImage_Array
&images
= effect
->getImage_array();
126 readImageArray(images
);
128 const domFx_newparam_common_Array
&newParams
= effect
->getNewparam_array();
130 for(UInt32 i
= 0; i
< newParams
.getCount(); ++i
)
132 if(newParams
[i
]->getFx_basic_type_common() == NULL
)
134 SWARNING
<< "ColladaEffect::read: <newparam> ["
135 << newParams
[i
]->getSid()
136 << "] without contents encountered, ignored."
141 // must read surface params before sampler params, because
142 // a samplers <source> can refer to a surface
143 domFx_surface_commonRef paramSurface
=
144 newParams
[i
]->getFx_basic_type_common()->getSurface();
146 if(paramSurface
!= NULL
)
150 param
.surface
= paramSurface
;
151 param
.colSurface
= dynamic_pointer_cast
<ColladaSurface
>(
152 ColladaElementFactory::the()->create(
153 paramSurface
, getGlobal()));
155 param
.colSurface
->read(this);
157 _surfaceParams
[newParams
[i
]->getSid()] = param
;
161 domFx_sampler2D_commonRef paramSampler2D
=
162 newParams
[i
]->getFx_basic_type_common()->getSampler2D();
164 if(paramSampler2D
!= NULL
)
166 ParamSampler2D param
;
168 param
.sampler2D
= paramSampler2D
;
169 param
.colSampler2D
= dynamic_pointer_cast
<ColladaSampler2D
>(
170 ColladaElementFactory::the()->create(
171 paramSampler2D
, getGlobal()));
173 param
.colSampler2D
->setEffect(this);
174 param
.colSampler2D
->read (this);
176 _sampler2DParams
[newParams
[i
]->getSid()] = param
;
181 const domFx_profile_abstract_Array
&profiles
=
182 effect
->getFx_profile_abstract_array();
184 ColladaDomProfileHandlerRefPtr pDomProfHandler
;
186 for(UInt32 i
= 0; i
< profiles
.getCount(); ++i
)
188 const domExtra_Array
*pProfileExtras
= NULL
;
190 if(domProfile_COMMON::ID() == profiles
[i
]->typeID())
192 domProfile_COMMON
*pProfile
=
193 daeSafeCast
<domProfile_COMMON
>(profiles
[i
]);
197 readProfileCommon(pProfile
);
199 pProfileExtras
= &(pProfile
->getExtra_array());
202 else if(domProfile_GLSL::ID() == profiles
[i
]->typeID())
205 ColladaHandlerFactory::the()->createDomProfileHandler(
206 domProfile_GLSL::ID());
208 domProfile_GLSL
*pProfile
=
209 daeSafeCast
<domProfile_GLSL
>(profiles
[i
]);
213 if(pDomProfHandler
!= NULL
)
215 pDomProfHandler
->readProfile(pProfile
);
219 readProfileGLSL(pProfile
);
222 pProfileExtras
= &(pProfile
->getExtra_array());
225 else if(domProfile_CG::ID() == profiles
[i
]->typeID())
228 ColladaHandlerFactory::the()->createDomProfileHandler(
229 domProfile_CG::ID());
231 domProfile_CG
*pProfile
= daeSafeCast
<domProfile_CG
>(profiles
[i
]);
235 if(pDomProfHandler
!= NULL
)
237 pDomProfHandler
->readProfile(pProfile
);
241 readProfileCG(pProfile
);
244 pProfileExtras
= &(pProfile
->getExtra_array());
248 if(_extraHandlers
.size() == 0)
251 for(UInt32 j
= 0; j
< pProfileExtras
->getCount(); ++j
)
253 ExtraHandlerStoreIt ehIt
= _extraHandlers
.begin();
254 ExtraHandlerStoreConstIt ehEnd
= _extraHandlers
.end ();
256 for(; ehIt
!= ehEnd
; ++ehIt
)
258 (*ehIt
)->readProfileExtraElements(this, (*pProfileExtras
)[j
]);
264 Material
*ColladaEffect::createInstance(ColladaInstInfo
*colInstInfo
)
266 OSG_COLLADA_LOG(("ColladaEffect::createInstance\n"));
268 MaterialUnrecPtr retVal
= NULL
;
269 domEffectRef effect
= getDOMElementAs
<domEffect
>();
271 ColladaInstanceEffectRefPtr colInstEffect
=
272 dynamic_cast<ColladaInstanceEffect
*>(colInstInfo
->getColInst());
274 domInstance_effectRef instEffect
=
275 colInstInfo
->getColInst()->getDOMElementAs
<domInstance_effect
>();
277 const domFx_profile_abstract_Array
&profiles
=
278 effect
->getFx_profile_abstract_array();
280 ColladaDomProfileHandlerRefPtr pDomProfHandler
;
282 for(UInt32 i
= 0; i
< profiles
.getCount(); ++i
)
284 const domExtra_Array
*pProfileExtras
= NULL
;
286 if(domProfile_COMMON::ID() == profiles
[i
]->typeID())
288 domProfile_COMMON
*pProfile
=
289 daeSafeCast
<domProfile_COMMON
>(profiles
[i
]);
293 retVal
= createInstanceProfileCommon(pProfile
,
297 pProfileExtras
= &(pProfile
->getExtra_array());
300 else if(domProfile_GLSL::ID() == profiles
[i
]->typeID())
303 ColladaHandlerFactory::the()->createDomProfileHandler(
304 domProfile_GLSL::ID());
306 domProfile_GLSL
*pProfile
=
307 daeSafeCast
<domProfile_GLSL
>(profiles
[i
]);
311 if(pDomProfHandler
!= NULL
)
313 pDomProfHandler
->createInstProfile(pProfile
,
319 retVal
= createInstanceProfileGLSL(pProfile
,
324 pProfileExtras
= &(pProfile
->getExtra_array());
327 else if(domProfile_CG::ID() == profiles
[i
]->typeID())
330 ColladaHandlerFactory::the()->createDomProfileHandler(
331 domProfile_CG::ID());
333 domProfile_CG
*pProfile
= daeSafeCast
<domProfile_CG
>(profiles
[i
]);
337 if(pDomProfHandler
!= NULL
)
339 pDomProfHandler
->createInstProfile(pProfile
,
345 retVal
= createInstanceProfileCG(pProfile
,
350 pProfileExtras
= &(pProfile
->getExtra_array());
354 if(_extraHandlers
.size() == 0 || pProfileExtras
->getCount() == 0)
357 ExtraHandlerStoreIt ehIt
= _extraHandlers
.begin();
358 ExtraHandlerStoreConstIt ehEnd
= _extraHandlers
.end ();
360 for(; ehIt
!= ehEnd
; ++ehIt
)
362 (*ehIt
)->instProfileExtraElements(this,
367 editInstStore().push_back(retVal
);
372 /*! Return parameter of the effect (\c <newparam> tags) with the given
376 daeElement
*ColladaEffect::findDOMParam(const std::string
&name
) const
378 ParamSampler2DMapConstIt sampler2DIt
= _sampler2DParams
.find(name
);
380 if(sampler2DIt
!= _sampler2DParams
.end())
382 return sampler2DIt
->second
.sampler2D
;
385 ParamSurfaceMapConstIt surfaceIt
= _surfaceParams
.find(name
);
387 if(surfaceIt
!= _surfaceParams
.end())
389 return surfaceIt
->second
.surface
;
395 /*! Return the loader element for the parameter of the effect (\c
396 <newparam> tags) with the given \a name.
399 ColladaElement
*ColladaEffect::findParam(const std::string
&name
) const
401 ParamSampler2DMapConstIt sampler2DIt
= _sampler2DParams
.find(name
);
403 if(sampler2DIt
!= _sampler2DParams
.end())
405 return sampler2DIt
->second
.colSampler2D
;
408 ParamSurfaceMapConstIt surfaceIt
= _surfaceParams
.find(name
);
410 if(surfaceIt
!= _surfaceParams
.end())
412 return surfaceIt
->second
.colSurface
;
418 void ColladaEffect::setTexture(
419 TextureTarget eTarget
,
420 ColladaTexture
*pColTexture
,
421 domCommon_color_or_texture_type::domTexture
*pDomTexture
)
423 ParamTexture oTexParam
;
425 oTexParam
.colTexture
= pColTexture
;
426 oTexParam
.texture
= pDomTexture
;
428 _textures
[eTarget
] = oTexParam
;
431 ColladaEffect::ColladaEffect(daeElement
*elem
,
432 ColladaGlobal
*global
) :
441 _textures
.resize(ColladaEffect::LastTexture
);
443 ColladaHandlerFactory::the()->createExtraHandlers(_extraHandlers
);
446 ColladaEffect::~ColladaEffect(void)
450 void ColladaEffect::readImageArray(const domImage_Array
&images
)
452 for(UInt32 i
= 0; i
< images
.getCount(); ++i
)
454 ColladaImageRefPtr colImg
= getUserDataAs
<ColladaImage
>(images
[i
]);
458 colImg
= dynamic_pointer_cast
<ColladaImage
>(
459 ColladaElementFactory::the()->create(
468 void ColladaEffect::readNewParams(const CommonParamArray
&newParams
)
470 for(UInt32 i
= 0; i
< newParams
.getCount(); ++i
)
472 // must read surface params before sampler params, because their
473 // <source> element can refer to a surface
475 domFx_surface_commonRef paramSurface
=
476 newParams
[i
]->getSurface();
478 if(paramSurface
!= NULL
)
482 param
.surface
= paramSurface
;
483 param
.colSurface
= dynamic_pointer_cast
<ColladaSurface
>(
484 ColladaElementFactory::the()->create(
485 paramSurface
, getGlobal()));
487 param
.colSurface
->read(this);
489 _surfaceParams
[newParams
[i
]->getSid()] = param
;
493 domFx_sampler2D_commonRef paramSampler2D
=
494 newParams
[i
]->getSampler2D();
496 if(paramSampler2D
!= NULL
)
498 ParamSampler2D param
;
500 param
.sampler2D
= paramSampler2D
;
501 param
.colSampler2D
= dynamic_pointer_cast
<ColladaSampler2D
>(
502 ColladaElementFactory::the()->create(
503 paramSampler2D
, getGlobal()));
505 param
.colSampler2D
->setEffect(this);
506 param
.colSampler2D
->read (this);
508 _sampler2DParams
[newParams
[i
]->getSid()] = param
;
512 // param is unhandled if we get to here
513 SWARNING
<< "ColladaEffect::readProfileCommon: Unhandled <newparam> ["
514 << newParams
[i
]->getSid() << "]."
520 /*! Fills internal data structures for \c <profile_COMMON>.
521 This mainly collects relevant parameters so they can be looked up
522 efficiently when creating an instance of this effect.
525 void ColladaEffect::readProfileCommon(domProfile_COMMON
*prof
)
529 SWARNING
<< "ColladaEffect::readProfileCommon: No DOM element or "
530 << "incorrect type." << std::endl
;
534 readImageArray(prof
->getImage_array ());
535 readNewParams (prof
->getNewparam_array());
537 domProfile_COMMON::domTechniqueRef tech
= prof
->getTechnique();
539 readNewParams (tech
->getNewparam_array());
540 readImageArray(tech
->getImage_array ());
543 if(tech
->getConstant() != NULL
)
545 OSG_COLLADA_LOG(("ColladaEffect::readProfileCommon: "
546 "using <constant> shader\n"));
548 domProfile_COMMON::domTechnique::domConstantRef constant
=
552 readTextureParams((constant
->getEmission() != NULL
) ?
553 constant
->getEmission()->getTexture() : NULL
,
556 readTextureParams((constant
->getTransparent() != NULL
) ?
557 constant
->getTransparent()->getTexture() : NULL
,
560 else if(tech
->getLambert() != NULL
)
562 OSG_COLLADA_LOG(("ColladaEffect::readProfileCommon: "
563 "using <lambert> shader\n"));
565 domProfile_COMMON::domTechnique::domLambertRef lambert
=
568 readTextureParams((lambert
->getEmission() != NULL
) ?
569 lambert
->getEmission()->getTexture() : NULL
,
572 readTextureParams((lambert
->getAmbient() != NULL
) ?
573 lambert
->getAmbient() ->getTexture() : NULL
,
576 readTextureParams((lambert
->getDiffuse() != NULL
) ?
577 lambert
->getDiffuse() ->getTexture() : NULL
,
580 readTextureParams((lambert
->getTransparent() != NULL
) ?
581 lambert
->getTransparent()->getTexture() : NULL
,
584 else if(tech
->getPhong() != NULL
)
586 OSG_COLLADA_LOG(("ColladaEffect::readProfileCommon: "
587 "using <phong> shader\n"));
589 domProfile_COMMON::domTechnique::domPhongRef phong
= tech
->getPhong();
591 readTextureParams((phong
->getEmission() != NULL
) ?
592 phong
->getEmission()->getTexture() : NULL
,
595 readTextureParams((phong
->getAmbient() != NULL
) ?
596 phong
->getAmbient() ->getTexture() : NULL
,
599 readTextureParams((phong
->getDiffuse() != NULL
) ?
600 phong
->getDiffuse() ->getTexture() : NULL
,
603 readTextureParams((phong
->getSpecular() != NULL
) ?
604 phong
->getSpecular() ->getTexture() : NULL
,
607 readTextureParams((phong
->getTransparent() != NULL
) ?
608 phong
->getTransparent()->getTexture() : NULL
,
611 else if(tech
->getBlinn() != NULL
)
613 OSG_COLLADA_LOG(("ColladaEffect::readProfileCommon: "
614 "using <blinn> shader\n"));
616 domProfile_COMMON::domTechnique::domBlinnRef blinn
= tech
->getBlinn();
618 readTextureParams((blinn
->getEmission() != NULL
) ?
619 blinn
->getEmission()->getTexture() : NULL
,
622 readTextureParams((blinn
->getAmbient() != NULL
) ?
623 blinn
->getAmbient() ->getTexture() : NULL
,
626 readTextureParams((blinn
->getDiffuse() != NULL
) ?
627 blinn
->getDiffuse() ->getTexture() : NULL
,
630 readTextureParams((blinn
->getSpecular() != NULL
) ?
631 blinn
->getSpecular() ->getTexture() : NULL
,
634 readTextureParams((blinn
->getTransparent() != NULL
) ?
635 blinn
->getTransparent()->getTexture() : NULL
,
639 const domExtra_Array
&techniqueExtras
= tech
->getExtra_array();
641 if(_extraHandlers
.size() == 0)
644 for(UInt32 i
= 0; i
< techniqueExtras
.getCount(); ++i
)
646 ExtraHandlerStoreIt ehIt
= _extraHandlers
.begin();
647 ExtraHandlerStoreConstIt ehEnd
= _extraHandlers
.end ();
649 for(; ehIt
!= ehEnd
; ++ehIt
)
651 (*ehIt
)->readTechniqueExtraElements(this, techniqueExtras
[i
]);
656 void ColladaEffect::readTextureParams(
657 domCommon_color_or_texture_type::domTexture
*texture
,
658 TextureTarget target
)
663 ParamTexture oTexParam
;
665 oTexParam
.colTexture
=
666 dynamic_pointer_cast
<ColladaTexture
>(
667 ColladaElementFactory::the()->create(texture
,
670 oTexParam
.texture
= texture
;
672 oTexParam
.colTexture
->setEffect(this);
673 oTexParam
.colTexture
->read (this);
675 _textures
[target
] = oTexParam
;
678 void ColladaEffect::readProfileGLSL(domProfile_GLSL
*prof
)
680 SWARNING
<< "ColladaEffect::readProfileGLSL: NIY." << std::endl
;
683 void ColladaEffect::readProfileCG(domProfile_CG
*prof
)
685 SWARNING
<< "ColladaEffect::readProfileCG: Fallback NIY." << std::endl
;
688 /*! Create an OpenSG material that matches this \c <profile_COMMON>
689 material (to the extent possible).
692 MaterialTransitPtr
ColladaEffect::createInstanceProfileCommon(
693 domProfile_COMMON
*prof
,
695 domInstance_effect
*instEffect
)
697 OSG_COLLADA_LOG(("ColladaEffect::createInstanceProfileCommon\n"));
699 ColladaInstanceEffectRefPtr colInstEffect
=
700 getUserDataAs
<ColladaInstanceEffect
>(instEffect
);
702 domProfile_COMMON::domTechniqueRef tech
= prof
->getTechnique();
704 domCommon_color_or_texture_typeRef emission
= NULL
;
705 domCommon_color_or_texture_typeRef ambient
= NULL
;
706 domCommon_color_or_texture_typeRef diffuse
= NULL
;
707 domCommon_color_or_texture_typeRef specular
= NULL
;
708 domCommon_float_or_param_typeRef shininess
= NULL
;
709 domCommon_transparent_typeRef transparent
= NULL
;
710 domCommon_float_or_param_typeRef transparency
= NULL
;
712 if(tech
->getConstant() != NULL
)
714 OSG_COLLADA_LOG(("ColladaEffect::createInstanceProfileCommon: "
715 "using <constant> shader\n"));
717 domProfile_COMMON::domTechnique::domConstantRef constant
=
720 emission
= constant
->getEmission ();
721 transparent
= constant
->getTransparent ();
722 transparency
= constant
->getTransparency();
724 else if(tech
->getLambert() != NULL
)
726 OSG_COLLADA_LOG(("ColladaEffect::createInstanceProfileCommon: "
727 "using <lambert> shader\n"));
729 domProfile_COMMON::domTechnique::domLambertRef lambert
=
732 emission
= lambert
->getEmission ();
733 ambient
= lambert
->getAmbient ();
734 diffuse
= lambert
->getDiffuse ();
735 transparent
= lambert
->getTransparent ();
736 transparency
= lambert
->getTransparency();
738 else if(tech
->getPhong() != NULL
)
740 OSG_COLLADA_LOG(("ColladaEffect::createInstanceProfileCommon: "
741 "using <phong> shader\n"));
743 domProfile_COMMON::domTechnique::domPhongRef phong
=
746 emission
= phong
->getEmission ();
747 ambient
= phong
->getAmbient ();
748 diffuse
= phong
->getDiffuse ();
749 specular
= phong
->getSpecular ();
750 shininess
= phong
->getShininess ();
751 transparent
= phong
->getTransparent ();
752 transparency
= phong
->getTransparency();
754 else if(tech
->getBlinn() != NULL
)
756 OSG_COLLADA_LOG(("ColladaEffect::createInstanceProfileCommon: "
757 "using <blinn> shader\n"));
759 domProfile_COMMON::domTechnique::domBlinnRef blinn
=
762 emission
= blinn
->getEmission ();
763 ambient
= blinn
->getAmbient ();
764 diffuse
= blinn
->getDiffuse ();
765 specular
= blinn
->getSpecular ();
766 shininess
= blinn
->getShininess ();
767 transparent
= blinn
->getTransparent ();
768 transparency
= blinn
->getTransparency();
772 Real32 transVal
= 1.f
;
773 ChunkMaterialUnrecPtr mat
= ChunkMaterial::create();
774 MaterialChunkUnrecPtr matChunk
= MaterialChunk::create();
775 BlendChunkUnrecPtr blendChunk
= NULL
;
776 DepthChunkUnrecPtr depthChunk
= NULL
;
778 getGlobal()->getStatCollector()->getElem(
779 ColladaGlobal::statNMaterialCreated
)->inc();
781 // handle the "conventional" material attributes
782 handleProfileCommonEmission(emission
,
785 handleProfileCommonAmbient (ambient
,
793 handleProfileCommonDiffuse (diffuse
,
801 handleProfileCommonSpecular(specular
,
804 if(shininess
!= NULL
)
806 domCommon_float_or_param_type::domFloatRef value
;
807 domCommon_float_or_param_type::domParamRef param
;
809 fillFloatParam(shininess
, value
, param
);
813 Real32 shininessVal
= value
->getValue();
814 shininessVal
= osgClamp(0.f
, shininessVal
, 128.f
);
816 matChunk
->setShininess(shininessVal
);
818 else if(param
!= NULL
)
820 SWARNING
<< "ColladaEffect::createInstanceProfileCommon: "
821 << "<shininess>/<param> not supported."
826 if(transparency
!= NULL
)
828 // this only sets transVal to the value stored in the
829 // <transparency> tag.
831 domCommon_float_or_param_type::domFloatRef value
;
832 domCommon_float_or_param_type::domParamRef param
;
834 fillFloatParam(transparency
, value
, param
);
838 transVal
= value
->getValue();
840 if(getGlobal()->getOptions()->getInvertTransparency() == true)
841 transVal
= 1.f
- transVal
;
843 else if(param
!= NULL
)
845 SWARNING
<< "ColladaEffect::createInstanceProfileCommon: "
846 << "<transparency>/<param> not supported."
851 if(transparent
!= NULL
)
853 // this handles <transparent> and <transparency> tags
854 // (by considering the value of transVal) - since they are
855 // so closely related that they need to be handled together
857 domCommon_color_or_texture_type::domColorRef color
;
858 domCommon_color_or_texture_type::domParamRef param
;
859 domCommon_color_or_texture_type::domTextureRef texture
;
861 fillColorParamTex(transparent
, color
, param
, texture
);
865 Color4f
colVal(color
->getValue()[0],
866 color
->getValue()[1],
867 color
->getValue()[2],
868 color
->getValue()[3] );
870 domFx_opaque_enum opaque
= transparent
->getOpaque();
872 if(opaque
== FX_OPAQUE_ENUM_A_ONE
)
874 Color4f
constCol(colVal
[3] * transVal
,
875 colVal
[3] * transVal
,
876 colVal
[3] * transVal
,
877 colVal
[3] * transVal
);
879 if(constCol
[0] < (1.f
- TypeTraits
<Real32
>::getDefaultEps()))
881 if(blendChunk
== NULL
)
882 blendChunk
= BlendChunk::create();
884 blendChunk
->setSrcFactor (GL_CONSTANT_ALPHA
);
885 blendChunk
->setDestFactor(GL_ONE_MINUS_CONSTANT_ALPHA
);
887 blendChunk
->setColor (constCol
);
890 ("ColladaEffect::createInstanceProfileCommon: "
891 "src: GL_CONSTANT_ALPHA "
892 "dst: GL_ONE_MINUS_CONSTANT_ALPHA "
897 else if(opaque
== FX_OPAQUE_ENUM_RGB_ZERO
)
899 Color4f
constCol(colVal
[0] * transVal
,
900 colVal
[1] * transVal
,
901 colVal
[2] * transVal
,
902 luminance(colVal
) * transVal
);
904 if(constCol
[0] > TypeTraits
<Real32
>::getDefaultEps() ||
905 constCol
[1] > TypeTraits
<Real32
>::getDefaultEps() ||
906 constCol
[2] > TypeTraits
<Real32
>::getDefaultEps() )
908 if(blendChunk
== NULL
)
909 blendChunk
= BlendChunk::create();
911 blendChunk
->setSrcFactor (GL_ONE_MINUS_CONSTANT_COLOR
);
912 blendChunk
->setDestFactor(GL_CONSTANT_COLOR
);
914 blendChunk
->setColor (constCol
);
917 ("ColladaEffect::createInstanceProfileCommon: "
918 "src: GL_ONE_MINUS_CONSTANT_COLOR "
919 "dst: GL_CONSTANT_COLOR "
928 else if(param
!= NULL
)
930 SWARNING
<< "ColladaEffect::createInstanceProfileCommon: "
931 << "<transparent>/<param> not supported."
934 else if(texture
!= NULL
)
936 ColladaTexture
*pTex
= _textures
[TransparentTexture
].colTexture
;
940 xsNCName tcSemantic
=
941 _textures
[TransparentTexture
].texture
->getTexcoord();
943 addTexture(tcSemantic
,
950 // do we need a blend chunk?
953 if(blendChunk
== NULL
)
954 blendChunk
= BlendChunk::create();
956 #if defined(OSG_COLLADA_TRANSPARENT_MODE) && OSG_COLLADA_TRANSPARENT_MODE == 1
957 // Always use alpha test with low alpha value, standard
958 // blending, but enable depth writes
960 blendChunk
->setAlphaFunc (GL_GREATER
);
961 blendChunk
->setAlphaValue(0.1f
);
963 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
964 blendChunk
->setDestFactor(GL_ONE_MINUS_SRC_ALPHA
);
966 // force depth writing even for transparent object
967 if(depthChunk
== NULL
)
968 depthChunk
= DepthChunk::create();
970 #elif defined(OSG_COLLADA_TRANSPARENT_MODE) && OSG_COLLADA_TRANSPARENT_MODE == 2
971 // enable depth writes for textures with a "mask" alpha
972 // channel (only values are 0 and 1)
973 // standard blending otherwise
975 if(pTex
->hasBinaryAlpha())
978 "ColladaEffect::createInstanceProfileCommon: "
979 "<transparent>/<texture> using alpha test.\n"));
981 blendChunk
->setAlphaFunc (GL_GREATER
);
982 blendChunk
->setAlphaValue(0.5f
);
984 blendChunk
->setDestFactor(GL_ZERO
);
985 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
990 "ColladaEffect::createInstanceProfileCommon: "
991 "<transparent>/<texture> using blending.\n"));
993 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
994 blendChunk
->setDestFactor(GL_ONE_MINUS_SRC_ALPHA
);
996 #endif // OSG_COLLADA_TRANSPARENT_MODE
1001 SWARNING
<< "ColladaEffect::createInstanceProfileCommon: "
1002 << "<diffuse>/<texture> could not find sampler2D ["
1003 << texture
->getTexture() << "]."
1008 else if(transparency
!= NULL
)
1010 // handle only <transparency> tag case (no <transparent> tag)
1012 Color4f
constCol(transVal
, transVal
, transVal
, transVal
);
1014 if(constCol
[0] < (1.f
- TypeTraits
<Real32
>::getDefaultEps()))
1016 if(blendChunk
== NULL
)
1017 blendChunk
= BlendChunk::create();
1019 blendChunk
->setSrcFactor (GL_CONSTANT_ALPHA
);
1020 blendChunk
->setDestFactor(GL_ONE_MINUS_CONSTANT_ALPHA
);
1022 blendChunk
->setColor (constCol
);
1024 OSG_COLLADA_LOG(("ColladaEffect::createInstanceProfileCommon: "
1025 "src: GL_CONSTANT_ALPHA "
1026 "dst: GL_ONE_MINUS_CONSTANT_ALPHA "
1027 "%f\n", constCol
[0]));
1031 mat
->addChunk(matChunk
);
1033 if(blendChunk
!= NULL
)
1034 mat
->addChunk(blendChunk
);
1036 if(depthChunk
!= NULL
)
1037 mat
->addChunk(depthChunk
);
1039 return MaterialTransitPtr(mat
);
1042 MaterialTransitPtr
ColladaEffect::createInstanceProfileGLSL(
1043 domProfile_GLSL
*prof
,
1045 domInstance_effect
*instEffect
)
1047 SWARNING
<< "ColladaEffect::createInstanceProfileGLSL: NIY" << std::endl
;
1049 return MaterialTransitPtr();
1052 MaterialTransitPtr
ColladaEffect::createInstanceProfileCG(
1053 domProfile_CG
*prof
,
1055 domInstance_effect
*instEffect
)
1057 SWARNING
<< "ColladaEffect::createInstanceProfileCG: Fallback NIY"
1060 return MaterialTransitPtr();
1063 void ColladaEffect::handleProfileCommonEmission(
1064 domCommon_color_or_texture_type
*emission
,
1065 MaterialChunk
*matChunk
)
1067 if(emission
== NULL
)
1070 domCommon_color_or_texture_type::domColorRef color
;
1071 domCommon_color_or_texture_type::domParamRef param
;
1072 domCommon_color_or_texture_type::domTextureRef texture
;
1074 fillColorParamTex(emission
, color
, param
, texture
);
1078 Color4f
colVal(color
->getValue()[0],
1079 color
->getValue()[1],
1080 color
->getValue()[2],
1081 color
->getValue()[3] );
1083 matChunk
->setEmission(colVal
);
1085 else if(param
!= NULL
)
1087 SWARNING
<< "ColladaEffect::handleProfileCommonEmission: "
1088 << "<emission>/<param> not supported."
1091 else if(texture
!= NULL
)
1094 xsNCName texId
= texture
->getTexture ();
1095 xsNCName tcSemantic
= texture
->getTexcoord();
1098 SWARNING
<< "ColladaEffect::handleProfileCommonEmission: "
1099 << "<emission>/<texture> not supported."
1104 void ColladaEffect::handleProfileCommonAmbient(
1105 domCommon_color_or_texture_type
*ambient
,
1106 ColladaInstanceEffect
*colInstEffect
,
1108 MaterialChunk
*matChunk
,
1109 BlendChunkUnrecPtr
&blendChunk
,
1110 DepthChunkUnrecPtr
&depthChunk
,
1116 domCommon_color_or_texture_type::domColorRef color
;
1117 domCommon_color_or_texture_type::domParamRef param
;
1118 domCommon_color_or_texture_type::domTextureRef texture
;
1120 fillColorParamTex(ambient
, color
, param
, texture
);
1124 Color4f
colVal(color
->getValue()[0],
1125 color
->getValue()[1],
1126 color
->getValue()[2],
1127 color
->getValue()[3] );
1129 matChunk
->setAmbient(colVal
);
1131 else if(param
!= NULL
)
1134 SWARNING
<< "ColladaEffect::handleProfileCommonAmbient: "
1135 << "<ambient>/<param> not supported."
1138 else if(texture
!= NULL
)
1140 ColladaTexture
*pTex
= _textures
[AmbientTexture
].colTexture
;
1144 xsNCName tcSemantic
=
1145 _textures
[AmbientTexture
].texture
->getTexcoord();
1147 addTexture(tcSemantic
,
1154 // do we need a blend chunk?
1155 if(pTex
->hasAlpha())
1157 if(blendChunk
== NULL
)
1158 blendChunk
= BlendChunk::create();
1160 #if defined(OSG_COLLADA_TRANSPARENT_MODE) && OSG_COLLADA_TRANSPARENT_MODE == 1
1161 // Always use alpha test with low alpha value, standard
1162 // blending, but enable depth writes
1164 blendChunk
->setAlphaFunc (GL_GREATER
);
1165 blendChunk
->setAlphaValue(0.1f
);
1167 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
1168 blendChunk
->setDestFactor(GL_ONE_MINUS_SRC_ALPHA
);
1170 // force depth writing even for transparent object
1171 if(depthChunk
== NULL
)
1172 depthChunk
= DepthChunk::create();
1174 #elif defined(OSG_COLLADA_TRANSPARENT_MODE) && OSG_COLLADA_TRANSPARENT_MODE == 2
1175 // enable depth writes for textures with a "mask" alpha
1176 // channel (only values are 0 and 1)
1177 // standard blending otherwise
1179 if(pTex
->hasBinaryAlpha())
1182 ("ColladaEffect::handleProfileCommonAmbient: "
1183 "<ambient>/<texture> using alpha test.\n"));
1185 blendChunk
->setAlphaFunc (GL_GREATER
);
1186 blendChunk
->setAlphaValue(0.5f
);
1188 blendChunk
->setDestFactor(GL_ZERO
);
1189 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
1194 ("ColladaEffect::handleProfileCommonAmbient: "
1195 "<ambient>/<texture> using blending.\n"));
1197 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
1198 blendChunk
->setDestFactor(GL_ONE_MINUS_SRC_ALPHA
);
1200 #endif // OSG_COLLADA_TRANSPARENT_MODE
1205 SWARNING
<< "ColladaEffect::handleProfileCommonAmbient: "
1206 << "<ambient>/<texture> could not find sampler2D ["
1207 << texture
->getTexture() << "]."
1213 void ColladaEffect::handleProfileCommonDiffuse(
1214 domCommon_color_or_texture_type
*diffuse
,
1215 ColladaInstanceEffect
*colInstEffect
,
1217 MaterialChunk
*matChunk
,
1218 BlendChunkUnrecPtr
&blendChunk
,
1219 DepthChunkUnrecPtr
&depthChunk
,
1222 domCommon_color_or_texture_type::domColorRef color
;
1223 domCommon_color_or_texture_type::domParamRef param
;
1224 domCommon_color_or_texture_type::domTextureRef texture
;
1226 fillColorParamTex(diffuse
, color
, param
, texture
);
1230 Color4f
colVal(color
->getValue()[0],
1231 color
->getValue()[1],
1232 color
->getValue()[2],
1233 color
->getValue()[3] );
1235 matChunk
->setDiffuse(colVal
);
1237 else if(param
!= NULL
)
1239 SWARNING
<< "ColladaEffect::handleProfileCommonDiffuse: "
1240 << "<diffuse>/<param> not supported."
1243 else if(texture
!= NULL
)
1245 ColladaTexture
*pTex
= _textures
[DiffuseTexture
].colTexture
;
1249 xsNCName tcSemantic
=
1250 _textures
[DiffuseTexture
].texture
->getTexcoord();
1252 addTexture(tcSemantic
,
1259 // do we need a blend chunk?
1260 if(pTex
->hasAlpha())
1262 if(blendChunk
== NULL
)
1263 blendChunk
= BlendChunk::create();
1265 #if defined(OSG_COLLADA_TRANSPARENT_MODE) && OSG_COLLADA_TRANSPARENT_MODE == 1
1266 // Always use alpha test with low alpha value, standard
1267 // blending, but enable depth writes
1269 blendChunk
->setAlphaFunc (GL_GREATER
);
1270 blendChunk
->setAlphaValue(0.1f
);
1272 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
1273 blendChunk
->setDestFactor(GL_ONE_MINUS_SRC_ALPHA
);
1275 // force depth writing even for transparent object
1276 if(depthChunk
== NULL
)
1277 depthChunk
= DepthChunk::create();
1279 #elif defined(OSG_COLLADA_TRANSPARENT_MODE) && OSG_COLLADA_TRANSPARENT_MODE == 2
1280 // enable depth writes for textures with a "mask" alpha
1281 // channel (only values are 0 and 1)
1282 // standard blending otherwise
1284 if(pTex
->hasBinaryAlpha())
1287 ("ColladaEffect::handleProfileCommonDiffuse: "
1288 "<diffuse>/<texture> using alpha test.\n"));
1290 blendChunk
->setAlphaFunc (GL_GREATER
);
1291 blendChunk
->setAlphaValue(0.5f
);
1294 blendChunk
->setDestFactor(GL_ZERO
);
1295 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
1300 ("ColladaEffect::handleProfileCommonDiffuse: "
1301 "<diffuse>/<texture> using blending.\n"));
1303 blendChunk
->setSrcFactor (GL_SRC_ALPHA
);
1304 blendChunk
->setDestFactor(GL_ONE_MINUS_SRC_ALPHA
);
1306 #endif // OSG_COLLADA_TRANSPARENT_MODE
1311 SWARNING
<< "ColladaEffect::handleProfileCommonDiffuse: "
1312 << "<diffuse>/<texture> could not find sampler2D ["
1313 << texture
->getTexture() << "]."
1317 matChunk
->setDiffuse(Color4f(0.8f
, 0.8f
, 0.8f
, 1.f
));
1321 void ColladaEffect::handleProfileCommonSpecular(
1322 domCommon_color_or_texture_type
*specular
,
1323 MaterialChunk
*matChunk
)
1325 if(specular
== NULL
)
1327 // set specular color to black if there is no specular value defined!
1328 matChunk
->setSpecular(Color4f(0.0f
,0.0f
,0.0f
,0.0f
));
1333 domCommon_color_or_texture_type::domColorRef color
;
1334 domCommon_color_or_texture_type::domParamRef param
;
1335 domCommon_color_or_texture_type::domTextureRef texture
;
1337 fillColorParamTex(specular
, color
, param
, texture
);
1341 Color4f
colVal(color
->getValue()[0],
1342 color
->getValue()[1],
1343 color
->getValue()[2],
1344 color
->getValue()[3] );
1346 matChunk
->setSpecular(colVal
);
1348 else if(param
!= NULL
)
1350 SWARNING
<< "ColladaEffect::createInstanceProfileCommon: "
1351 << "<specular>/<param> not supported."
1354 else if(texture
!= NULL
)
1357 xsNCName texId
= texture
->getTexture ();
1358 xsNCName tcSemantic
= texture
->getTexcoord();
1360 SWARNING
<< "ColladaEffect::createInstanceProfileCommon: "
1361 << "<specular>/<texture> not supported."
1367 void ColladaEffect::fillColorParamTex(
1368 domCommon_color_or_texture_type
*colTex
,
1369 domCommon_color_or_texture_type::domColorRef
&colOut
,
1370 domCommon_color_or_texture_type::domParamRef
¶mOut
,
1371 domCommon_color_or_texture_type::domTextureRef
&texOut
)
1375 colOut
= colTex
->getColor ();
1376 paramOut
= colTex
->getParam ();
1377 texOut
= colTex
->getTexture();
1381 void ColladaEffect::fillColorParamTex(
1382 domCommon_transparent_type
*colTex
,
1383 domCommon_color_or_texture_type::domColorRef
&colOut
,
1384 domCommon_color_or_texture_type::domParamRef
¶mOut
,
1385 domCommon_color_or_texture_type::domTextureRef
&texOut
)
1389 colOut
= colTex
->getColor ();
1390 paramOut
= colTex
->getParam ();
1391 texOut
= colTex
->getTexture();
1395 void ColladaEffect::fillFloatParam(
1396 domCommon_float_or_param_type
*floatParam
,
1397 domCommon_float_or_param_type::domFloatRef
&floatOut
,
1398 domCommon_float_or_param_type::domParamRef
¶mOut
)
1400 if(floatParam
!= NULL
)
1402 floatOut
= floatParam
->getFloat();
1403 paramOut
= floatParam
->getParam();
1407 void ColladaEffect::addTexture(const std::string
&tcSemantic
,
1408 ColladaInstanceEffect
*colInstEffect
,
1409 ColladaTexture
*colTexture
,
1414 TextureEnvChunkUnrecPtr texEnv
= TextureEnvChunk::create();
1415 texEnv
->setEnvMode(envMode
);
1417 Image
*texImg
= colTexture
->getTexture()->getImage();
1421 mat
->addChunk(colTexture
->getTexture(), texCount
);
1422 mat
->addChunk(texEnv
, texCount
);
1423 mat
->addChunk(colTexture
->getTexTransform(), texCount
);
1425 getGlobal()->getStatCollector()->getElem(
1426 ColladaGlobal::statNTextureUsed
)->inc();
1428 OSG_COLLADA_LOG(("ColladaEffect::addTexture: "
1429 "texCoord symbol [%s] in slot [%d]\n",
1431 Geometry::TexCoordsIndex
+ texCount
));
1433 colInstEffect
->editTCMap()[tcSemantic
] =
1434 Geometry::TexCoordsIndex
+ texCount
;
1440 Real32
ColladaEffect::luminance(const Color4f
&col
)
1442 return (col
[0] * 0.212671f
+ col
[1] * 0.71516f
+ col
[2] * 0.072169f
);
1447 #endif // OSG_WITH_COLLADA