fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / FileIO / Collada / OSGColladaEffect.cpp
blobfc93a048bb335fd206341856c07548d9d98d2792
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2009 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
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. *
18 * *
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. *
23 * *
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. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
40 #pragma GCC diagnostic ignored "-Wold-style-cast"
41 #endif
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
78 OSG_BEGIN_NAMESPACE
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,
98 colInst )
102 ColladaEffect::ColladaEffectInstInfo::~ColladaEffectInstInfo(void)
106 // ===========================================================================
108 ColladaElementRegistrationHelper ColladaEffect::_regHelper(
109 &ColladaEffect::create,
110 "effect");
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."
137 << std::endl;
138 continue;
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)
148 ParamSurface param;
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;
158 continue;
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;
177 continue;
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]);
195 if(pProfile != NULL)
197 readProfileCommon(pProfile);
199 pProfileExtras = &(pProfile->getExtra_array());
202 else if(domProfile_GLSL::ID() == profiles[i]->typeID())
204 pDomProfHandler =
205 ColladaHandlerFactory::the()->createDomProfileHandler(
206 domProfile_GLSL::ID());
208 domProfile_GLSL *pProfile =
209 daeSafeCast<domProfile_GLSL>(profiles[i]);
211 if(pProfile != NULL)
213 if(pDomProfHandler != NULL)
215 pDomProfHandler->readProfile(pProfile);
217 else
219 readProfileGLSL(pProfile);
222 pProfileExtras = &(pProfile->getExtra_array());
225 else if(domProfile_CG::ID() == profiles[i]->typeID())
227 pDomProfHandler =
228 ColladaHandlerFactory::the()->createDomProfileHandler(
229 domProfile_CG::ID());
231 domProfile_CG *pProfile = daeSafeCast<domProfile_CG>(profiles[i]);
233 if(pProfile != NULL)
235 if(pDomProfHandler != NULL)
237 pDomProfHandler->readProfile(pProfile);
239 else
241 readProfileCG(pProfile);
244 pProfileExtras = &(pProfile->getExtra_array());
248 if(_extraHandlers.size() == 0)
249 continue;
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]);
291 if(pProfile != NULL)
293 retVal = createInstanceProfileCommon(pProfile,
294 effect,
295 instEffect);
297 pProfileExtras = &(pProfile->getExtra_array());
300 else if(domProfile_GLSL::ID() == profiles[i]->typeID())
302 pDomProfHandler =
303 ColladaHandlerFactory::the()->createDomProfileHandler(
304 domProfile_GLSL::ID());
306 domProfile_GLSL *pProfile =
307 daeSafeCast<domProfile_GLSL>(profiles[i]);
309 if(pProfile != NULL)
311 if(pDomProfHandler != NULL)
313 pDomProfHandler->createInstProfile(pProfile,
314 effect,
315 instEffect );
317 else
319 retVal = createInstanceProfileGLSL(pProfile,
320 effect,
321 instEffect);
324 pProfileExtras = &(pProfile->getExtra_array());
327 else if(domProfile_CG::ID() == profiles[i]->typeID())
329 pDomProfHandler =
330 ColladaHandlerFactory::the()->createDomProfileHandler(
331 domProfile_CG::ID());
333 domProfile_CG *pProfile = daeSafeCast<domProfile_CG>(profiles[i]);
335 if(pProfile != NULL)
337 if(pDomProfHandler != NULL)
339 pDomProfHandler->createInstProfile(pProfile,
340 effect,
341 instEffect );
343 else
345 retVal = createInstanceProfileCG(pProfile,
346 effect,
347 instEffect);
350 pProfileExtras = &(pProfile->getExtra_array());
354 if(_extraHandlers.size() == 0 || pProfileExtras->getCount() == 0)
355 continue;
357 ExtraHandlerStoreIt ehIt = _extraHandlers.begin();
358 ExtraHandlerStoreConstIt ehEnd = _extraHandlers.end ();
360 for(; ehIt != ehEnd; ++ehIt)
362 (*ehIt)->instProfileExtraElements(this,
363 retVal);
367 editInstStore().push_back(retVal);
369 return retVal;
372 /*! Return parameter of the effect (\c &lt;newparam&gt; tags) with the given
373 * \a name.
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;
392 return NULL;
395 /*! Return the loader element for the parameter of the effect (\c
396 &lt;newparam&gt; 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;
415 return NULL;
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) :
434 Inherited (elem,
435 global),
436 _sampler2DParams( ),
437 _surfaceParams ( ),
438 _textures ( ),
439 _extraHandlers ( )
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]);
456 if(colImg == NULL)
458 colImg = dynamic_pointer_cast<ColladaImage>(
459 ColladaElementFactory::the()->create(
460 images[i],
461 getGlobal()));
463 colImg->read(this);
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)
480 ParamSurface param;
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;
490 continue;
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;
509 continue;
512 // param is unhandled if we get to here
513 SWARNING << "ColladaEffect::readProfileCommon: Unhandled <newparam> ["
514 << newParams[i]->getSid() << "]."
515 << std::endl;
520 /*! Fills internal data structures for \c &lt;profile_COMMON&gt;.
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)
527 if(prof == NULL)
529 SWARNING << "ColladaEffect::readProfileCommon: No DOM element or "
530 << "incorrect type." << std::endl;
531 return;
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 =
549 tech->getConstant();
552 readTextureParams((constant->getEmission() != NULL) ?
553 constant->getEmission()->getTexture() : NULL,
554 EmissionTexture);
556 readTextureParams((constant->getTransparent() != NULL) ?
557 constant->getTransparent()->getTexture() : NULL,
558 TransparentTexture);
560 else if(tech->getLambert() != NULL)
562 OSG_COLLADA_LOG(("ColladaEffect::readProfileCommon: "
563 "using <lambert> shader\n"));
565 domProfile_COMMON::domTechnique::domLambertRef lambert =
566 tech->getLambert();
568 readTextureParams((lambert->getEmission() != NULL) ?
569 lambert->getEmission()->getTexture() : NULL,
570 EmissionTexture);
572 readTextureParams((lambert->getAmbient() != NULL) ?
573 lambert->getAmbient() ->getTexture() : NULL,
574 AmbientTexture);
576 readTextureParams((lambert->getDiffuse() != NULL) ?
577 lambert->getDiffuse() ->getTexture() : NULL,
578 DiffuseTexture);
580 readTextureParams((lambert->getTransparent() != NULL) ?
581 lambert->getTransparent()->getTexture() : NULL,
582 TransparentTexture);
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,
593 EmissionTexture);
595 readTextureParams((phong->getAmbient() != NULL) ?
596 phong->getAmbient() ->getTexture() : NULL,
597 AmbientTexture);
599 readTextureParams((phong->getDiffuse() != NULL) ?
600 phong->getDiffuse() ->getTexture() : NULL,
601 DiffuseTexture);
603 readTextureParams((phong->getSpecular() != NULL) ?
604 phong->getSpecular() ->getTexture() : NULL,
605 SpecularTexture);
607 readTextureParams((phong->getTransparent() != NULL) ?
608 phong->getTransparent()->getTexture() : NULL,
609 TransparentTexture);
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,
620 EmissionTexture);
622 readTextureParams((blinn->getAmbient() != NULL) ?
623 blinn->getAmbient() ->getTexture() : NULL,
624 AmbientTexture);
626 readTextureParams((blinn->getDiffuse() != NULL) ?
627 blinn->getDiffuse() ->getTexture() : NULL,
628 DiffuseTexture);
630 readTextureParams((blinn->getSpecular() != NULL) ?
631 blinn->getSpecular() ->getTexture() : NULL,
632 SpecularTexture);
634 readTextureParams((blinn->getTransparent() != NULL) ?
635 blinn->getTransparent()->getTexture() : NULL,
636 TransparentTexture);
639 const domExtra_Array &techniqueExtras = tech->getExtra_array();
641 if(_extraHandlers.size() == 0)
642 return;
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 )
660 if(texture == NULL)
661 return;
663 ParamTexture oTexParam;
665 oTexParam.colTexture =
666 dynamic_pointer_cast<ColladaTexture>(
667 ColladaElementFactory::the()->create(texture,
668 getGlobal()));
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 &lt;profile_COMMON&gt;
689 material (to the extent possible).
692 MaterialTransitPtr ColladaEffect::createInstanceProfileCommon(
693 domProfile_COMMON *prof,
694 domEffect *effect,
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 =
718 tech->getConstant();
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 =
730 tech->getLambert();
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 =
744 tech->getPhong();
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 =
760 tech->getBlinn();
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();
771 UInt32 texCount = 0;
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,
783 matChunk);
785 handleProfileCommonAmbient (ambient,
786 colInstEffect,
787 mat,
788 matChunk,
789 blendChunk,
790 depthChunk,
791 texCount );
793 handleProfileCommonDiffuse (diffuse,
794 colInstEffect,
795 mat,
796 matChunk,
797 blendChunk,
798 depthChunk,
799 texCount );
801 handleProfileCommonSpecular(specular,
802 matChunk );
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);
811 if(value != NULL)
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."
822 << std::endl;
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);
836 if(value != NULL)
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."
847 << std::endl;
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);
863 if(color != NULL)
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 );
889 OSG_COLLADA_LOG(
890 ("ColladaEffect::createInstanceProfileCommon: "
891 "src: GL_CONSTANT_ALPHA "
892 "dst: GL_ONE_MINUS_CONSTANT_ALPHA "
893 "%f\n",
894 constCol[0]));
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 );
916 OSG_COLLADA_LOG(
917 ("ColladaEffect::createInstanceProfileCommon: "
918 "src: GL_ONE_MINUS_CONSTANT_COLOR "
919 "dst: GL_CONSTANT_COLOR "
920 "%f %f %f %f\n",
921 constCol[0],
922 constCol[1],
923 constCol[2],
924 constCol[3]));
928 else if(param != NULL)
930 SWARNING << "ColladaEffect::createInstanceProfileCommon: "
931 << "<transparent>/<param> not supported."
932 << std::endl;
934 else if(texture != NULL)
936 ColladaTexture *pTex = _textures[TransparentTexture].colTexture;
938 if(pTex != NULL)
940 xsNCName tcSemantic =
941 _textures[TransparentTexture].texture->getTexcoord();
943 addTexture(tcSemantic,
944 colInstEffect,
945 pTex,
946 mat,
947 GL_MODULATE,
948 texCount );
950 // do we need a blend chunk?
951 if(pTex->hasAlpha())
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())
977 OSG_COLLADA_LOG((
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);
987 else
989 OSG_COLLADA_LOG((
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
999 else
1001 SWARNING << "ColladaEffect::createInstanceProfileCommon: "
1002 << "<diffuse>/<texture> could not find sampler2D ["
1003 << texture->getTexture() << "]."
1004 << std::endl;
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,
1044 domEffect *effect,
1045 domInstance_effect *instEffect)
1047 SWARNING << "ColladaEffect::createInstanceProfileGLSL: NIY" << std::endl;
1049 return MaterialTransitPtr();
1052 MaterialTransitPtr ColladaEffect::createInstanceProfileCG(
1053 domProfile_CG *prof,
1054 domEffect *effect,
1055 domInstance_effect *instEffect)
1057 SWARNING << "ColladaEffect::createInstanceProfileCG: Fallback NIY"
1058 << std::endl;
1060 return MaterialTransitPtr();
1063 void ColladaEffect::handleProfileCommonEmission(
1064 domCommon_color_or_texture_type *emission,
1065 MaterialChunk *matChunk )
1067 if(emission == NULL)
1068 return;
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);
1076 if(color != NULL)
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."
1089 << std::endl;
1091 else if(texture != NULL)
1093 #if 0
1094 xsNCName texId = texture->getTexture ();
1095 xsNCName tcSemantic = texture->getTexcoord();
1096 #endif
1098 SWARNING << "ColladaEffect::handleProfileCommonEmission: "
1099 << "<emission>/<texture> not supported."
1100 << std::endl;
1104 void ColladaEffect::handleProfileCommonAmbient(
1105 domCommon_color_or_texture_type *ambient,
1106 ColladaInstanceEffect *colInstEffect,
1107 ChunkMaterial *mat,
1108 MaterialChunk *matChunk,
1109 BlendChunkUnrecPtr &blendChunk,
1110 DepthChunkUnrecPtr &depthChunk,
1111 UInt32 &texCount )
1113 if(ambient == NULL)
1114 return;
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);
1122 if(color != NULL)
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."
1136 << std::endl;
1138 else if(texture != NULL)
1140 ColladaTexture *pTex = _textures[AmbientTexture].colTexture;
1142 if(pTex != NULL)
1144 xsNCName tcSemantic =
1145 _textures[AmbientTexture].texture->getTexcoord();
1147 addTexture(tcSemantic,
1148 colInstEffect,
1149 pTex,
1150 mat,
1151 GL_REPLACE,
1152 texCount );
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())
1181 OSG_COLLADA_LOG(
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);
1191 else
1193 OSG_COLLADA_LOG(
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
1203 else
1205 SWARNING << "ColladaEffect::handleProfileCommonAmbient: "
1206 << "<ambient>/<texture> could not find sampler2D ["
1207 << texture->getTexture() << "]."
1208 << std::endl;
1213 void ColladaEffect::handleProfileCommonDiffuse(
1214 domCommon_color_or_texture_type *diffuse,
1215 ColladaInstanceEffect *colInstEffect,
1216 ChunkMaterial *mat,
1217 MaterialChunk *matChunk,
1218 BlendChunkUnrecPtr &blendChunk,
1219 DepthChunkUnrecPtr &depthChunk,
1220 UInt32 &texCount )
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);
1228 if(color != NULL)
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."
1241 << std::endl;
1243 else if(texture != NULL)
1245 ColladaTexture *pTex = _textures[DiffuseTexture].colTexture;
1247 if(pTex != NULL)
1249 xsNCName tcSemantic =
1250 _textures[DiffuseTexture].texture->getTexcoord();
1252 addTexture(tcSemantic,
1253 colInstEffect,
1254 pTex,
1255 mat,
1256 GL_MODULATE,
1257 texCount );
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())
1286 OSG_COLLADA_LOG(
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);
1297 else
1299 OSG_COLLADA_LOG(
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
1309 else
1311 SWARNING << "ColladaEffect::handleProfileCommonDiffuse: "
1312 << "<diffuse>/<texture> could not find sampler2D ["
1313 << texture->getTexture() << "]."
1314 << std::endl;
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));
1330 return;
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);
1339 if(color != NULL)
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."
1352 << std::endl;
1354 else if(texture != NULL)
1356 #if 0
1357 xsNCName texId = texture->getTexture ();
1358 xsNCName tcSemantic = texture->getTexcoord();
1359 #endif
1360 SWARNING << "ColladaEffect::createInstanceProfileCommon: "
1361 << "<specular>/<texture> not supported."
1362 << std::endl;
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 &paramOut,
1371 domCommon_color_or_texture_type::domTextureRef &texOut )
1373 if(colTex != NULL)
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 &paramOut,
1385 domCommon_color_or_texture_type::domTextureRef &texOut )
1387 if(colTex != NULL)
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 &paramOut )
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,
1410 ChunkMaterial *mat,
1411 GLenum envMode,
1412 UInt32 &texCount )
1414 TextureEnvChunkUnrecPtr texEnv = TextureEnvChunk::create();
1415 texEnv->setEnvMode(envMode);
1417 Image *texImg = colTexture->getTexture()->getImage();
1419 if(texImg != NULL)
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",
1430 tcSemantic.c_str(),
1431 Geometry::TexCoordsIndex + texCount));
1433 colInstEffect->editTCMap()[tcSemantic] =
1434 Geometry::TexCoordsIndex + texCount;
1436 ++texCount;
1440 Real32 ColladaEffect::luminance(const Color4f &col)
1442 return (col[0] * 0.212671f + col[1] * 0.71516f + col[2] * 0.072169f);
1445 OSG_END_NAMESPACE
1447 #endif // OSG_WITH_COLLADA