1 /*
2 * Copyright 2006 Sony Computer Entertainment Inc.
3 *
4 * Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
5 * file except in compliance with the License. You may obtain a copy of the License at:
6 * http://research.scea.com/scea_shared_source_license.html
7 *
8 * Unless required by applicable law or agreed to in writing, software distributed under the License
9 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10 * implied. See the License for the specific language governing permissions and limitations under the
11 * License.
12 */
13
14 #include "daeReader.h"
15 #include <dae.h>
16 #include <dae/domAny.h>
17 #include <dom/domCOLLADA.h>
18
19 #include <osg/Switch>
20 #include <osg/LightSource>
21 #include <osg/Geode>
22 #include <osg/ShapeDrawable>
23 #include <osg/LOD>
24 #include <osg/Billboard>
25 #include <osgSim/MultiSwitch>
26 #include <osg/Sequence>
27 #include <osg/CameraView>
28 #include <osg/LightModel>
29
30 using namespace osgDAE;
31
32 #ifdef COLLADA_DOM_2_4_OR_LATER
33 #include <dom/domAny.h>
34 using namespace ColladaDOM141;
35 #endif
36
processOsgMultiSwitch(domTechnique * teq)37 osg::Group* daeReader::processOsgMultiSwitch(domTechnique* teq)
38 {
39 osgSim::MultiSwitch* msw = new osgSim::MultiSwitch;
40
41 domAny* any = daeSafeCast<domAny>(teq->getChild("ActiveSwitchSet"));
42 if (any)
43 {
44 msw->setActiveSwitchSet(parseString<unsigned int>(any->getValue()));
45 }
46 else
47 {
48 OSG_WARN << "Expected element 'ActiveSwitchSet' not found" << std::endl;
49 }
50
51 any = daeSafeCast<domAny>(teq->getChild("ValueLists"));
52 if (any)
53 {
54 unsigned int numChildren = any->getChildren().getCount();
55 for (unsigned int currChild = 0; currChild < numChildren; currChild++)
56 {
57 domAny* child = daeSafeCast<domAny>(any->getChildren()[currChild]);
58 if (child)
59 {
60 if (strcmp(child->getElementName(), "ValueList" ) == 0 )
61 {
62 std::list<std::string> stringValues;
63 osgSim::MultiSwitch::ValueList values;
64
65 cdom::tokenize(child->getValue(), " ", stringValues);
66 cdom::tokenIter iter = stringValues.begin();
67
68 while (iter != stringValues.end())
69 {
70 values.push_back(parseString<bool>(*iter));
71 ++iter;
72 }
73
74 msw->setValueList(currChild, values);
75 }
76 else
77 {
78 OSG_WARN << "Child of element 'ValueLists' is not of type 'ValueList'" << std::endl;
79 }
80 }
81 else
82 {
83 OSG_WARN << "Element 'ValueLists' does not contain expected elements." << std::endl;
84 }
85 }
86 }
87 else
88 {
89 OSG_WARN << "Expected element 'ValueLists' not found" << std::endl;
90 }
91 return msw;
92 }
93
processOsgSwitch(domTechnique * teq)94 osg::Group* daeReader::processOsgSwitch(domTechnique* teq)
95 {
96 osg::Switch* sw = new osg::Switch;
97
98 domAny* any = daeSafeCast< domAny >(teq->getChild("ValueList"));
99 if (any)
100 {
101 std::list<std::string> stringValues;
102
103 cdom::tokenize(any->getValue(), " ", stringValues);
104 cdom::tokenIter iter = stringValues.begin();
105
106 int pos = 0;
107 while (iter != stringValues.end())
108 {
109 sw->setValue(pos++, parseString<bool>(*iter));
110 ++iter;
111 }
112 }
113 else
114 {
115 OSG_WARN << "Expected element 'ValueList' not found" << std::endl;
116 }
117 return sw;
118 }
119
processOsgSequence(domTechnique * teq)120 osg::Group* daeReader::processOsgSequence(domTechnique* teq)
121 {
122 osg::Sequence* sq = new osg::Sequence;
123
124 domAny* any = daeSafeCast< domAny >(teq->getChild("FrameTime"));
125 if (any)
126 {
127 std::list<std::string> stringValues;
128
129 cdom::tokenize(any->getValue(), " ", stringValues);
130 cdom::tokenIter iter = stringValues.begin();
131
132 int frame = 0;
133 while (iter != stringValues.end())
134 {
135 sq->setTime(frame++, parseString<double>(*iter));
136 ++iter;
137 }
138 }
139 else
140 {
141 OSG_WARN << "Expected element 'FrameTime' not found" << std::endl;
142 }
143
144 any = daeSafeCast< domAny >(teq->getChild("LastFrameTime"));
145 if (any)
146 {
147 sq->setLastFrameTime(parseString<double>(any->getValue()));
148 }
149 else
150 {
151 OSG_WARN << "Expected element 'LastFrameTime' not found" << std::endl;
152 }
153
154 osg::Sequence::LoopMode loopmode = osg::Sequence::LOOP;
155 any = daeSafeCast< domAny >(teq->getChild("LoopMode"));
156 if (any)
157 {
158 loopmode = (osg::Sequence::LoopMode)parseString<int>(any->getValue());
159 }
160 else
161 {
162 OSG_WARN << "Expected element 'LoopMode' not found" << std::endl;
163 }
164
165 int begin=0;
166 any = daeSafeCast< domAny >(teq->getChild("IntervalBegin"));
167 if (any)
168 {
169 begin = parseString<int>(any->getValue());
170 }
171 else
172 {
173 OSG_WARN << "Expected element 'IntervalBegin' not found" << std::endl;
174 }
175
176 int end=-1;
177 any = daeSafeCast< domAny >(teq->getChild("IntervalEnd"));
178 if (any)
179 {
180 end = parseString<int>(any->getValue());
181 }
182 else
183 {
184 OSG_WARN << "Expected element 'IntervalEnd' not found" << std::endl;
185 }
186
187 sq->setInterval(loopmode, begin, end);
188
189 float speed = 0;
190 any = daeSafeCast< domAny >(teq->getChild("DurationSpeed"));
191 if (any)
192 {
193 speed = parseString<float>(any->getValue());
194 }
195 else
196 {
197 OSG_WARN << "Expected element 'DurationSpeed' not found" << std::endl;
198 }
199
200 int nreps = -1;
201 any = daeSafeCast< domAny >(teq->getChild("DurationNReps"));
202 if (any)
203 {
204 nreps = parseString<int>(any->getValue());
205 }
206 else
207 {
208 OSG_WARN << "Expected element 'DurationNReps' not found" << std::endl;
209 }
210
211 sq->setDuration(speed, nreps);
212
213 any = daeSafeCast< domAny >(teq->getChild("SequenceMode"));
214 if (any)
215 {
216 sq->setMode((osg::Sequence::SequenceMode)parseString<int>(any->getValue()));
217 }
218 else
219 {
220 OSG_WARN << "Expected element 'SequenceMode' not found" << std::endl;
221 }
222
223 return sq;
224 }
225
226
processOsgLOD(domTechnique * teq)227 osg::Group* daeReader::processOsgLOD(domTechnique* teq)
228 {
229 osg::LOD* lod = new osg::LOD;
230
231 domAny* any = daeSafeCast< domAny >(teq->getChild("Center"));
232 if (any)
233 {
234 // If a center is specified
235 lod->setCenterMode(osg::LOD::USER_DEFINED_CENTER);
236 lod->setCenter(parseVec3String(any->getValue()));
237
238 any = daeSafeCast< domAny >(teq->getChild("Radius"));
239 if (any)
240 {
241 lod->setRadius(parseString<osg::LOD::value_type>(any->getValue()));
242 }
243 else
244 {
245 OSG_WARN << "Expected element 'Radius' not found" << std::endl;
246 }
247 }
248
249 any = daeSafeCast< domAny >(teq->getChild("RangeMode"));
250 if (any)
251 {
252 lod->setRangeMode((osg::LOD::RangeMode)parseString<int>(any->getValue()));
253 }
254 else
255 {
256 OSG_WARN << "Expected element 'RangeMode' not found" << std::endl;
257 }
258
259 any = daeSafeCast< domAny >(teq->getChild("RangeList"));
260 if (any)
261 {
262 osg::LOD::RangeList rangelist;
263
264 unsigned int numChildren = any->getChildren().getCount();
265 for (unsigned int currChild = 0; currChild < numChildren; currChild++)
266 {
267 domAny* child = daeSafeCast<domAny>(any->getChildren()[currChild]);
268 if (child)
269 {
270 if (strcmp(child->getElementName(), "MinMax" ) == 0 )
271 {
272 std::list<std::string> stringValues;
273 osg::LOD::MinMaxPair minMaxPair;
274
275 cdom::tokenize(child->getValue(), " ", stringValues);
276 cdom::tokenIter iter = stringValues.begin();
277
278 if (iter != stringValues.end())
279 {
280 minMaxPair.first = parseString<float>(*iter);
281 ++iter;
282 }
283 else
284 {
285 OSG_WARN << "'MinMax' does not contain a valid minimum value" << std::endl;
286 }
287
288 if (iter != stringValues.end())
289 {
290 minMaxPair.second = parseString<float>(*iter);
291 }
292 else
293 {
294 OSG_WARN << "'MinMax' does not contain a valid maximum value" << std::endl;
295 }
296
297 rangelist.push_back(minMaxPair);
298 }
299 else
300 {
301 OSG_WARN << "Child of element 'RangeList' is not of type 'MinMax'" << std::endl;
302 }
303 }
304 else
305 {
306 OSG_WARN << "Element 'RangeList' does not contain expected elements." << std::endl;
307 }
308 }
309
310 lod->setRangeList(rangelist);
311 }
312 else
313 {
314 OSG_WARN << "Expected element 'RangeList' not found" << std::endl;
315 }
316
317 return lod;
318 }
319
320 // <light>
321 // attributes:
322 // id, name
323 // elements:
324 // 0..1 <asset>
325 // 1 <technique_common>
326 // 1 <ambient>, <directional>, <point>, <spot>
327 // 0..* <technique>
328 // 0..* <extra>
processLight(domLight * dlight)329 osg::Node* daeReader::processLight( domLight *dlight )
330 {
331 if (_numlights >= 7)
332 {
333 OSG_WARN << "More than 8 lights may not be supported by OpenGL driver." << std::endl;
334 }
335
336 //do light processing here.
337 domLight::domTechnique_common::domAmbient *ambient;
338 domLight::domTechnique_common::domDirectional *directional;
339 domLight::domTechnique_common::domPoint *point;
340 domLight::domTechnique_common::domSpot *spot;
341
342 if ( dlight->getTechnique_common() == NULL ||
343 dlight->getTechnique_common()->getContents().getCount() == 0 )
344 {
345 OSG_WARN << "Invalid content for light" << std::endl;
346 return NULL;
347 }
348
349 osg::Light* light = new osg::Light();
350 light->setPosition(osg::Vec4(0,0,0,1));
351 light->setLightNum(_numlights);
352
353 // Enable OpenGL lighting
354 _rootStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
355 // Enable this OpenGL light
356 _rootStateSet->setMode(GL_LIGHT0 + _numlights++, osg::StateAttribute::ON);
357
358 // Set ambient of lightmodel to zero
359 // Ambient lights are added as separate lights with only an ambient term
360 osg::LightModel* lightmodel = new osg::LightModel;
361 lightmodel->setAmbientIntensity(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
362 _rootStateSet->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
363
364 osg::LightSource* lightsource = new osg::LightSource();
365 lightsource->setLight(light);
366 std::string name = dlight->getId() ? dlight->getId() : "";
367 if (dlight->getName())
368 name = dlight->getName();
369 lightsource->setName(name);
370
371 daeElement *el = dlight->getTechnique_common()->getContents()[0];
372 ambient = daeSafeCast< domLight::domTechnique_common::domAmbient >( el );
373 directional = daeSafeCast< domLight::domTechnique_common::domDirectional >( el );
374 point = daeSafeCast< domLight::domTechnique_common::domPoint >( el );
375 spot = daeSafeCast< domLight::domTechnique_common::domSpot >( el );
376 if ( ambient != NULL )
377 {
378 if ( ambient->getColor() == NULL )
379 {
380 OSG_WARN << "Invalid content for ambient light" << std::endl;
381 return NULL;
382 }
383
384 light->setAmbient( osg::Vec4( ambient->getColor()->getValue()[0],
385 ambient->getColor()->getValue()[1],
386 ambient->getColor()->getValue()[2], 1.0f ) );
387 light->setDiffuse( osg::Vec4( 0, 0, 0, 0));
388 light->setSpecular( osg::Vec4( 0, 0, 0, 0));
389
390 // Tell OpenGL to make it a directional light (w=0)
391 light->setPosition( osg::Vec4(0,0,0,0));
392 }
393 else if ( directional != NULL )
394 {
395 if ( directional->getColor() == NULL )
396 {
397 OSG_WARN << "Invalid content for directional light" << std::endl;
398 return NULL;
399 }
400 light->setAmbient( osg::Vec4( 0, 0, 0, 0));
401 light->setDiffuse( osg::Vec4( directional->getColor()->getValue()[0],
402 directional->getColor()->getValue()[1],
403 directional->getColor()->getValue()[2], 1.0f ) );
404 light->setSpecular( osg::Vec4( directional->getColor()->getValue()[0],
405 directional->getColor()->getValue()[1],
406 directional->getColor()->getValue()[2], 1.0f ) );
407
408 light->setDirection(osg::Vec3(0,0,-1));
409
410 // Tell OpenGL it is a directional light (w=0)
411 light->setPosition( osg::Vec4(0,0,1,0));
412 }
413 else if ( point != NULL )
414 {
415 if ( point->getColor() == NULL )
416 {
417 OSG_WARN << "Invalid content for point light" << std::endl;
418 return NULL;
419 }
420 light->setAmbient( osg::Vec4( 0, 0, 0, 0));
421 light->setDiffuse( osg::Vec4( point->getColor()->getValue()[0],
422 point->getColor()->getValue()[1],
423 point->getColor()->getValue()[2], 1.0f ) );
424 light->setSpecular( osg::Vec4( point->getColor()->getValue()[0],
425 point->getColor()->getValue()[1],
426 point->getColor()->getValue()[2], 1.0f ) );
427
428 if ( point->getConstant_attenuation() != NULL )
429 {
430 light->setConstantAttenuation( point->getConstant_attenuation()->getValue() );
431 }
432 else
433 {
434 light->setConstantAttenuation( 1.0 );
435 }
436 if ( point->getLinear_attenuation() != NULL )
437 {
438 light->setLinearAttenuation( point->getLinear_attenuation()->getValue() );
439 }
440 else
441 {
442 light->setLinearAttenuation( 0.0 );
443 }
444 if ( point->getQuadratic_attenuation() != NULL )
445 {
446 light->setQuadraticAttenuation( point->getQuadratic_attenuation()->getValue() );
447 }
448 else
449 {
450 light->setQuadraticAttenuation( 0.0 );
451 }
452
453 // Tell OpenGL this is an omni directional light
454 light->setDirection(osg::Vec3(0, 0, 0));
455 }
456 else if ( spot != NULL )
457 {
458 if ( spot->getColor() == NULL )
459 {
460 OSG_WARN << "Invalid content for spot light" << std::endl;
461 return NULL;
462 }
463 light->setAmbient( osg::Vec4( 0, 0, 0, 0));
464 light->setDiffuse( osg::Vec4( spot->getColor()->getValue()[0],
465 spot->getColor()->getValue()[1],
466 spot->getColor()->getValue()[2], 1.0f ) );
467 light->setSpecular( osg::Vec4( spot->getColor()->getValue()[0],
468 spot->getColor()->getValue()[1],
469 spot->getColor()->getValue()[2], 1.0f ) );
470
471 if ( spot->getConstant_attenuation() != NULL )
472 {
473 light->setConstantAttenuation( spot->getConstant_attenuation()->getValue() );
474 }
475 else
476 {
477 light->setConstantAttenuation( 1.0f );
478 }
479 if ( spot->getLinear_attenuation() != NULL )
480 {
481 light->setLinearAttenuation( spot->getLinear_attenuation()->getValue() );
482 }
483 else
484 {
485 light->setLinearAttenuation( 0.0f );
486 }
487 if ( spot->getQuadratic_attenuation() != NULL )
488 {
489 light->setQuadraticAttenuation( spot->getQuadratic_attenuation()->getValue() );
490 }
491 else
492 {
493 light->setQuadraticAttenuation( 0.0f );
494 }
495 // OpenGL range [0, 90] (degrees) or 180 (omni)
496 if ( spot->getFalloff_angle() != NULL )
497 {
498 float falloffAngle = spot->getFalloff_angle()->getValue();
499 if (falloffAngle != 180)
500 {
501 falloffAngle = osg::clampTo<float>(falloffAngle, 0, 90);
502 }
503 light->setSpotCutoff(falloffAngle);
504 }
505 else
506 {
507 light->setSpotCutoff( 180.0f );
508 }
509 // OpenGL range [0, 128], where 0 means hard edge, and 128 means soft edge
510 if ( spot->getFalloff_exponent() != NULL )
511 {
512 float falloffExponent = spot->getFalloff_exponent()->getValue();
513 falloffExponent = osg::clampTo<float>(falloffExponent, 0, 128);
514 light->setSpotExponent(falloffExponent);
515 }
516 else
517 {
518 light->setSpotExponent( 0.0f );
519 }
520 light->setDirection(osg::Vec3(0, 0, -1));
521 }
522
523 return lightsource;
524 }
525
526 // <camera>
527 // attributes:
528 // id, name
529 // elements:
530 // 0..1 <asset>
531 // 1 <optics>
532 // 1 <technique_common>
533 // 1 <orthographic>, <perspective>
534 // 0..* <technique>
535 // 0..* <extra>
536 // 0..* <imager>
537 // 1 <technique>
538 // 0..* <extra>
539 // 0..* <extra>
processCamera(domCamera * dcamera)540 osg::Node* daeReader::processCamera( domCamera * dcamera )
541 {
542 osg::CameraView* pOsgCameraView = new osg::CameraView;
543 pOsgCameraView->setName(dcamera->getId());
544
545 domCamera::domOptics::domTechnique_common *pDomTechniqueCommon = dcamera->getOptics()->getTechnique_common();
546 domCamera::domOptics::domTechnique_common::domPerspective *pDomPerspective = pDomTechniqueCommon->getPerspective();
547 domCamera::domOptics::domTechnique_common::domOrthographic *pDomOrthographic = pDomTechniqueCommon->getOrthographic();
548 if (pDomPerspective)
549 {
550 // <perspective>
551 // 1 <xfov>, <yfov>, <xfov> and <yfov>, <xfov> and <aspect_ratio>, <yfov> and <aspect_ratio>
552 // 1 <znear>
553 // 1 <zfar>
554 domTargetableFloat *pXfov = daeSafeCast< domTargetableFloat >(pDomPerspective->getXfov());
555 domTargetableFloat *pYfov = daeSafeCast< domTargetableFloat >(pDomPerspective->getYfov());
556 domTargetableFloat *pAspectRatio = daeSafeCast< domTargetableFloat >(pDomPerspective->getAspect_ratio());
557
558 if (pXfov)
559 {
560 if (pYfov)
561 {
562 // <xfov> and <yfov>
563 pOsgCameraView->setFieldOfView(pXfov->getValue());
564 pOsgCameraView->setFieldOfViewMode(osg::CameraView::HORIZONTAL);
565
566 if (pAspectRatio)
567 {
568 OSG_WARN << "Unexpected <aspectratio> in <camera> '" << dcamera->getId() << "'" << std::endl;
569 }
570 }
571 else if (pAspectRatio)
572 {
573 // <xfov> and <aspect_ratio>
574 pOsgCameraView->setFieldOfView(pXfov->getValue() * pAspectRatio->getValue());
575 pOsgCameraView->setFieldOfViewMode(osg::CameraView::HORIZONTAL);
576 }
577 else
578 {
579 // <xfov>
580 pOsgCameraView->setFieldOfView(pXfov->getValue());
581 pOsgCameraView->setFieldOfViewMode(osg::CameraView::HORIZONTAL);
582 }
583 }
584 else if (pYfov)
585 {
586 if (pAspectRatio)
587 {
588 // <yfov> and <aspect_ratio>
589 pOsgCameraView->setFieldOfView(pYfov->getValue() / pAspectRatio->getValue());
590 pOsgCameraView->setFieldOfViewMode(osg::CameraView::VERTICAL);
591 }
592 else
593 {
594 // <yfov>
595 pOsgCameraView->setFieldOfView(pYfov->getValue());
596 pOsgCameraView->setFieldOfViewMode(osg::CameraView::VERTICAL);
597 }
598 }
599 else
600 {
601 // xfov or yfov expected
602 OSG_WARN << "Expected <xfov> or <yfov> in <camera> '" << dcamera->getId() << "'" << std::endl;
603 }
604
605 //domTargetableFloat *pZnear = daeSafeCast< domTargetableFloat >(pDomPerspective->getZnear());
606 //domTargetableFloat *pZfar = daeSafeCast< domTargetableFloat >(pDomPerspective->getZfar());
607
608 // TODO The current osg::CameraView does not support storage of near far
609 }
610 else if (pDomOrthographic)
611 {
612 // <orthographic>
613 // 1 <xmag>, <ymag>, <xmag> and <ymag>, <xmag> and <aspect_ratio>, <ymag> and <aspect_ratio>
614 // 1 <znear>
615 // 1 <zfar>
616
617 //domTargetableFloat *pXmag = daeSafeCast< domTargetableFloat >(pDomOrthographic->getXmag());
618 //domTargetableFloat *pYmag = daeSafeCast< domTargetableFloat >(pDomOrthographic->getYmag());
619 //domTargetableFloat *pAspectRatio = daeSafeCast< domTargetableFloat >(pDomOrthographic->getAspect_ratio());
620
621 // TODO The current osg::CameraView does not support an orthographic view
622 OSG_WARN << "Orthographic in <camera> '" << dcamera->getId() << "' not supported" << std::endl;
623
624 //domTargetableFloat *pZnear = daeSafeCast< domTargetableFloat >(pDomOrthographic->getZnear());
625 //domTargetableFloat *pZfar = daeSafeCast< domTargetableFloat >(pDomOrthographic->getZfar());
626
627 // TODO The current osg::CameraView does not support storage of near far
628 }
629
630 return pOsgCameraView;
631 }
632