1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2010 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 "OSGColladaLight.h"
45 #ifdef OSG_WITH_COLLADA
47 #include "OSGColladaLog.h"
48 #include "OSGColladaInstanceLight.h"
50 #include "OSGDirectionalLight.h"
51 #include "OSGPointLight.h"
52 #include "OSGSpotLight.h"
53 #include "OSGChunkOverrideGroup.h"
54 #include "OSGNameAttachment.h"
58 // ===========================================================================
60 ColladaInstInfoTransitPtr
61 ColladaLight::ColladaLightInstInfo::create(
62 ColladaElement
*colInstParent
, ColladaInstanceLight
*colInst
,
65 return ColladaInstInfoTransitPtr(
66 new ColladaLightInstInfo(colInstParent
, colInst
, beaconN
));
70 ColladaLight::ColladaLightInstInfo::process(void)
72 Node
*lightInstN
= dynamic_cast<Node
*>(
73 getColInst()->getTargetElem()->createInstance(this));
75 if(lightInstN
== NULL
)
78 Node
*rootN
= getColInst()->getGlobal()->getRoot();
80 while(rootN
->getNChildren() > 0)
82 lightInstN
->addChild(rootN
->getChild(0));
85 rootN
->addChild(lightInstN
);
89 ColladaLight::ColladaLightInstInfo::getBeacon(void) const
94 ColladaLight::ColladaLightInstInfo::ColladaLightInstInfo(
95 ColladaElement
*colInstParent
, ColladaInstanceLight
*colInst
,
98 : Inherited(colInstParent
, colInst
)
103 ColladaLight::ColladaLightInstInfo::~ColladaLightInstInfo(void)
107 // ===========================================================================
109 // Ambient light sources are a bit tricky to handle. First all ambient sources
110 // in the scene have to be accumulated and then an appropriate LightModelChunk
111 // must be inserted at the top of the scene (using a ChunkOverrideGroup).
112 // The first part is done by ColladaLight::createInstance(), which will also
113 // place an instance of ColladaLightAmbientInstInfo into the instance queue.
114 // That instance will then cause the insertion of the LightModelChunk.
116 ColladaInstInfoTransitPtr
117 ColladaLight::ColladaLightAmbientInstInfo::create(
118 ColladaElement
*colInstParent
, ColladaInstanceLight
*colInst
)
120 return ColladaInstInfoTransitPtr(
121 new ColladaLightAmbientInstInfo(colInstParent
, colInst
));
125 ColladaLight::ColladaLightAmbientInstInfo::process(void)
127 dynamic_cast<ColladaLight
*>(
128 getColInst()->getTargetElem())->createAmbientLight(this);
131 ColladaLight::ColladaLightAmbientInstInfo::ColladaLightAmbientInstInfo(
132 ColladaElement
*colInstParent
, ColladaInstanceLight
*colInst
)
134 : Inherited(colInstParent
, colInst
)
138 ColladaLight::ColladaLightAmbientInstInfo::~ColladaLightAmbientInstInfo(void)
142 // ===========================================================================
144 ColladaLight::LightLoaderStateTransitPtr
145 ColladaLight::LightLoaderState::create(void)
147 return LightLoaderStateTransitPtr(new LightLoaderState());
151 ColladaLight::LightLoaderState::getLightModelChunk(void) const
157 ColladaLight::LightLoaderState::setLightModelChunk(LightModelChunk
*chunk
)
162 ColladaLight::LightLoaderState::LightLoaderState(void)
168 ColladaLight::LightLoaderState::~LightLoaderState(void)
172 // ===========================================================================
174 ColladaElementRegistrationHelper
ColladaLight::_regHelper(
175 &ColladaLight::create
, "light");
176 const std::string
ColladaLight::_loaderStateName("ColladaLight");
179 ColladaElementTransitPtr
180 ColladaLight::create(daeElement
*elem
, ColladaGlobal
*global
)
182 if(global
->getLoaderState(_loaderStateName
) == NULL
)
184 LightLoaderStateRefPtr state
= LightLoaderState::create();
186 global
->addLoaderState(_loaderStateName
, state
);
189 return ColladaElementTransitPtr(new ColladaLight(elem
, global
));
193 ColladaLight::read(ColladaElement
*colElemParent
)
195 domLightRef light
= getDOMElementAs
<domLight
>();
197 OSG_COLLADA_LOG(("ColladaLight::read id [%s]\n", light
->getId()));
201 ColladaLight::createInstance(ColladaInstInfo
*colInstInfo
)
203 domLightRef light
= getDOMElementAs
<domLight
>();
205 OSG_COLLADA_LOG(("ColladaLight::createInstance id [%s]\n",
208 NodeUnrecPtr retVal
= NULL
;
209 ColladaLightInstInfo
*lightInstInfo
=
210 dynamic_cast<ColladaLightInstInfo
*>(colInstInfo
);
211 domLight::domTechnique_commonRef techComm
=
212 light
->getTechnique_common();
214 const domTechnique_Array
&techs
= light
->getTechnique_array();
216 for(UInt32 i
= 0; i
< techs
.getCount(); ++i
)
218 retVal
= createInstanceTechnique(lightInstInfo
, techs
[i
]);
220 // stop as soon as something is created
225 // if we get here no technique was choosen so we evaluate
226 // <technique_common>
227 retVal
= createInstanceCommon(lightInstInfo
, techComm
);
233 ColladaLight::createAmbientLight(ColladaLightAmbientInstInfo
*colInstInfo
)
235 OSG_COLLADA_LOG(("ColladaLight::createAmbientLight\n"));
237 LightLoaderState
*state
=
238 getGlobal()->getLoaderStateAs
<LightLoaderState
>(_loaderStateName
);
239 OSG_ASSERT(state
!= NULL
);
241 ChunkOverrideGroupUnrecPtr coGroup
= ChunkOverrideGroup::create();
242 NodeUnrecPtr coGroupN
= makeNodeFor(coGroup
);
244 coGroup
->addChunk(state
->getLightModelChunk());
246 Node
*rootN
= getGlobal()->getRoot();
248 while(rootN
->getNChildren() > 0)
250 coGroupN
->addChild(rootN
->getChild(0));
253 if(getGlobal()->getOptions()->getCreateNameAttachments() == true)
255 setName(coGroupN
, "OpenSG_AmbientLight");
258 rootN
->addChild(coGroupN
);
261 ColladaLight::ColladaLight(daeElement
*elem
, ColladaGlobal
*global
)
262 : Inherited(elem
, global
)
266 ColladaLight::~ColladaLight(void)
271 ColladaLight::createInstanceTechnique(
272 ColladaLightInstInfo
*colInstInfo
, domTechnique
*tech
)
274 domLightRef light
= getDOMElementAs
<domLight
>();
276 OSG_COLLADA_LOG(("ColladaLight::createInstanceTechnique id [%s] "
277 "profile [%s]\n", light
->getId(), tech
->getProfile()));
283 ColladaLight::createInstanceCommon(
284 ColladaLightInstInfo
*colInstInfo
, domLight::domTechnique_common
*tech
)
286 domLightRef light
= getDOMElementAs
<domLight
>();
288 OSG_COLLADA_LOG(("ColladaLight::createInstanceCommon id [%s]\n",
291 NodeUnrecPtr lightN
= NULL
;
293 domLight::domTechnique_common::domAmbientRef ambient
=
295 domLight::domTechnique_common::domDirectionalRef directional
=
296 tech
->getDirectional();
297 domLight::domTechnique_common::domPointRef point
=
299 domLight::domTechnique_common::domSpotRef spot
=
304 Color4f
lightColor(ambient
->getColor()->getValue()[0],
305 ambient
->getColor()->getValue()[1],
306 ambient
->getColor()->getValue()[2], 1.f
);
308 LightLoaderState
*state
=
309 getGlobal()->getLoaderStateAs
<LightLoaderState
>(_loaderStateName
);
310 OSG_ASSERT(state
!= NULL
);
312 LightModelChunkUnrecPtr lmChunk
= state
->getLightModelChunk();
314 if(state
->getLightModelChunk() == NULL
)
316 lmChunk
= LightModelChunk::create();
317 lmChunk
->setAmbient(Color4f(0.f
, 0.f
, 0.f
, 1.f
));
319 state
->setLightModelChunk(lmChunk
);
321 // only place one instance into the inst queue, it will
322 // add the LightModelChunk with the accumulated ambient
324 ColladaInstInfoRefPtr ambientInstInfo
=
325 ColladaLightAmbientInstInfo::create(
326 colInstInfo
->getColInstParent(),
327 dynamic_cast<ColladaInstanceLight
*>(
328 colInstInfo
->getColInst()) );
330 getGlobal()->editInstQueue().push_back(ambientInstInfo
);
334 osgClamp(0.f
, lmChunk
->getAmbient()[0] + lightColor
[0], 1.f
);
336 osgClamp(0.f
, lmChunk
->getAmbient()[1] + lightColor
[1], 1.f
);
338 osgClamp(0.f
, lmChunk
->getAmbient()[2] + lightColor
[0], 1.f
);
340 lmChunk
->setAmbient(lightColor
);
343 if(directional
!= NULL
)
345 Color4f
lightColor(directional
->getColor()->getValue()[0],
346 directional
->getColor()->getValue()[1],
347 directional
->getColor()->getValue()[2], 1.f
);
349 DirectionalLightUnrecPtr dl
= DirectionalLight::create();
350 lightN
= makeNodeFor(dl
);
352 dl
->setBeacon (colInstInfo
->getBeacon());
353 dl
->setDiffuse (lightColor
);
354 dl
->setSpecular(lightColor
);
359 Color4f
lightColor(point
->getColor()->getValue()[0],
360 point
->getColor()->getValue()[1],
361 point
->getColor()->getValue()[2], 1.f
);
363 PointLightUnrecPtr pl
= PointLight::create();
364 lightN
= makeNodeFor(pl
);
366 Real32 constAtt
= 1.f
;
368 Real32 quadAtt
= 0.f
;
370 if(point
->getConstant_attenuation() != NULL
)
371 constAtt
= point
->getConstant_attenuation()->getValue();
373 if(point
->getLinear_attenuation() != NULL
)
374 linAtt
= point
->getLinear_attenuation()->getValue();
376 if(point
->getQuadratic_attenuation() != NULL
)
377 quadAtt
= point
->getQuadratic_attenuation()->getValue();
379 pl
->setBeacon (colInstInfo
->getBeacon());
380 pl
->setDiffuse (lightColor
);
381 pl
->setSpecular (lightColor
);
382 pl
->setConstantAttenuation (constAtt
);
383 pl
->setLinearAttenuation (linAtt
);
384 pl
->setQuadraticAttenuation(quadAtt
);
389 Color4f
lightColor(spot
->getColor()->getValue()[0],
390 spot
->getColor()->getValue()[1],
391 spot
->getColor()->getValue()[2], 1.f
);
393 SpotLightUnrecPtr sl
= SpotLight::create();
394 lightN
= makeNodeFor(sl
);
396 Real32 constAtt
= 1.f
;
398 Real32 quadAtt
= 0.f
;
399 Real32 cutOff
= 180.f
;
400 Real32 exponent
= 0.f
;
402 if(spot
->getConstant_attenuation() != NULL
)
403 constAtt
= spot
->getConstant_attenuation()->getValue();
405 if(spot
->getLinear_attenuation() != NULL
)
406 linAtt
= spot
->getLinear_attenuation()->getValue();
408 if(spot
->getQuadratic_attenuation() != NULL
)
409 quadAtt
= spot
->getQuadratic_attenuation()->getValue();
411 if(spot
->getFalloff_angle() != NULL
)
412 cutOff
= spot
->getFalloff_angle()->getValue();
414 if(spot
->getFalloff_exponent() != NULL
)
415 exponent
= spot
->getFalloff_exponent()->getValue();
417 sl
->setBeacon (colInstInfo
->getBeacon());
418 sl
->setDiffuse (lightColor
);
419 sl
->setSpecular (lightColor
);
420 sl
->setConstantAttenuation (constAtt
);
421 sl
->setLinearAttenuation (linAtt
);
422 sl
->setQuadraticAttenuation(quadAtt
);
423 sl
->setSpotCutOff (osgDegree2Rad(cutOff
) );
424 sl
->setSpotExponent (exponent
);
429 editInstStore().push_back(lightN
);
431 if(getGlobal()->getOptions()->getCreateNameAttachments() == true &&
432 light
->getName() != NULL
)
434 setName(lightN
, light
->getName());
437 getGlobal()->getStatCollector()->getElem(
438 ColladaGlobal::statNLightCreated
)->inc();
446 #endif // OSG_WITH_COLLADA