Visualization Library 2.1.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
DaeLoader.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
34 
35 using namespace vl;
36 
37 namespace
38 {
39  //-----------------------------------------------------------------------------
40  const char* VL_NO_MATERIAL_SPECIFIED = "<VL_NO_MATERIAL_SPECIFIED>";
41  const char* VL_DEFAULT_LIGHT = "<VL_DEFAULT_LIGHT>";
42  //-----------------------------------------------------------------------------
43  struct
44  {
45  Dae::EInputSemantic mSemantic;
46  const char* mSemanticString;
47  } SemanticTable[] =
48  {
49  { Dae::IS_UNKNOWN, "UNKNOWN" },
50  { Dae::IS_BINORMAL, "BINORMAL" },
51  { Dae::IS_COLOR, "COLOR" },
52  { Dae::IS_CONTINUITY, "CONTINUITY" },
53  { Dae::IS_IMAGE, "IMAGE" },
54  { Dae::IS_INPUT, "INPUT" },
55  { Dae::IS_IN_TANGENT, "IN_TANGENT" },
56  { Dae::IS_INTERPOLATION, "INTERPOLATION" },
57  { Dae::IS_INV_BIND_MATRIX, "INV_BIND_MATRIX" },
58  { Dae::IS_JOINT, "JOINT" },
59  { Dae::IS_LINEAR_STEPS, "LINEAR_STEPS" },
60  { Dae::IS_MORPHS_TARGET, "MORPHS_TARGET" },
61  { Dae::IS_MORPH_WEIGHT, "MORPH_WEIGHT" },
62  { Dae::IS_NORMAL, "NORMAL" },
63  { Dae::IS_OUTPUT, "OUTPUT" },
64  { Dae::IS_OUT_TANGENT, "OUT_TANGENT" },
65  { Dae::IS_POSITION, "POSITION" },
66  { Dae::IS_TANGENT, "TANGENT" },
67  { Dae::IS_TEXBINORMAL, "TEXBINORMAL" },
68  { Dae::IS_TEXCOORD, "TEXCOORD" },
69  { Dae::IS_TEXTANGENT, "TEXTANGENT" },
70  { Dae::IS_UV, "UV" },
71  { Dae::IS_VERTEX, "VERTEX" },
72  { Dae::IS_WEIGHT, "WEIGHT" },
74  };
75 }
76 //-----------------------------------------------------------------------------
78 {
79  reset();
80 
81  // default material
82 
83  mDefaultFX = new Effect;
84  mDefaultFX->setObjectName( VL_NO_MATERIAL_SPECIFIED );
85  mDefaultFX->shader()->enable(EN_LIGHTING);
86  mDefaultFX->shader()->setRenderState( new Light, 0 );
87  mDefaultFX->shader()->gocMaterial()->setFlatColor( vl::fuchsia );
88  mDefaultFX->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
89 }
90 //-----------------------------------------------------------------------------
92 {
93  mAssumeOpaque = false;
94  mInvertTransparency = false;
95  mScene = NULL;
97 }
98 //-----------------------------------------------------------------------------
99 void DaeLoader::parseInputs(Dae::Primitive* dae_primitive, const domInputLocalOffset_Array& input_arr, const std::vector< ref<Dae::Input> >& vertex_inputs)
100 {
101  dae_primitive->mIndexStride = 0;
102 
103  for(size_t iinp=0; iinp<input_arr.getCount(); ++iinp)
104  {
105  domInputLocalOffsetRef input = input_arr.get(iinp);
106 
107  // copy over VERTEX inputs with the current offset and set
108  if ( getSemantic(input->getSemantic()) == Dae::IS_VERTEX )
109  {
110  VL_CHECK(!vertex_inputs.empty())
111  for(size_t ivert=0; ivert<vertex_inputs.size(); ++ivert)
112  {
113  ref<Dae::Input> dae_input = new Dae::Input;
114  dae_input->mSemantic = vertex_inputs[ivert]->mSemantic;
115  dae_input->mSource = vertex_inputs[ivert]->mSource;
116  dae_input->mOffset = (size_t)input->getOffset();
117  dae_input->mSet = (size_t)input->getSet();
118  dae_primitive->mChannels.push_back(dae_input);
119 
120  VL_CHECK(dae_input->mSource);
121  VL_CHECK(dae_input->mSemantic != Dae::IS_UNKNOWN);
122 
123 
124  dae_primitive->mIndexStride = std::max(dae_primitive->mIndexStride, dae_input->mOffset);
125  }
126  }
127  else
128  {
129  ref<Dae::Input> dae_input = new Dae::Input;
130  dae_input->mSemantic = getSemantic(input->getSemantic());
131  dae_input->mSource = getSource( input->getSource().getElement() );
132  dae_input->mOffset = (size_t)input->getOffset();
133  dae_input->mSet = (size_t)input->getSet();
134 
135  // if the source is NULL getSource() has already issued an error.
136  if (dae_input->mSource)
137  dae_primitive->mChannels.push_back( dae_input );
138 
139  VL_CHECK(dae_input->mSource);
140  VL_CHECK(dae_input->mSemantic != Dae::IS_UNKNOWN);
141 
142  dae_primitive->mIndexStride = std::max(dae_primitive->mIndexStride, dae_input->mOffset);
143  }
144  }
145 
146  dae_primitive->mIndexStride += 1;
147 }
148 //-----------------------------------------------------------------------------
150 {
151  // try to reuse the geometry in the library
152  std::map< daeElementRef, ref<Dae::Mesh> >::iterator it = mMeshes.find( geometry );
153  if (it != mMeshes.end())
154  return it->second;
155 
156  if (!geometry->getChild("mesh"))
157  return NULL;
158 
159  domMesh* mesh = static_cast<domMesh*>(geometry->getChild("mesh"));
160 
161  // add to dictionary
162  ref<Dae::Mesh> dae_mesh = new Dae::Mesh;
163  mMeshes[geometry] = dae_mesh;
164 
165  // vertices
166  domVerticesRef vertices = mesh->getVertices();
167  domInputLocal_Array input_array = vertices->getInput_array();
168  for(size_t i=0; i<input_array.getCount(); ++i)
169  {
170  ref<Dae::Input> dae_input = new Dae::Input;
171 
172  dae_input->mSemantic = getSemantic(input_array[i]->getSemantic());
173  if (dae_input->mSemantic == Dae::IS_UNKNOWN)
174  {
175  Log::error( Say("LoadWriterDae: the following semantic is unknown: %s\n") << input_array[i]->getSemantic() );
176  continue;
177  }
178 
179  dae_input->mSource = getSource( input_array[i]->getSource().getElement() );
180  // if the source is NULL getSource() already issued an error.
181  if (!dae_input->mSource)
182  continue;
183 
184  dae_mesh->mVertexInputs.push_back(dae_input);
185  }
186 
187  // --- --- ---- primitives ---- --- ---
188 
189  // NOTE: for the moment we generate one Geometry for each primitive but we should try to generate
190  // one single set of vertex attribute array for each input semantic and recycle it if possible.
191  // Unfortunately COLLADA makes this trivial task impossible to achieve.
192 
193  // --- ---- triangles ---- ---
194  domTriangles_Array triangles_arr = mesh->getTriangles_array();
195  for(size_t itri=0; itri< triangles_arr.getCount(); ++itri)
196  {
197  domTrianglesRef triangles = triangles_arr.get(itri);
198 
199  ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
200  dae_mesh->mPrimitives.push_back(dae_primitive);
201  dae_primitive->mType = Dae::PT_TRIANGLES;
202  dae_primitive->mCount = (size_t)triangles->getCount();
203 
204  // --- input ---
205  domInputLocalOffset_Array input_arr = triangles->getInput_array();
206  parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
207 
208  // --- ---- p ---- ---
209  dae_primitive->mP.push_back( triangles->getP() );
210 
211  // --- ---- material ---- ---
212  dae_primitive->mMaterial = triangles->getMaterial() ? triangles->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
213 
214  // --- ---- generates the geometry ---- ---
215  generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
216  }
217 
218  // --- ---- triangles fan ---- ---
219  domTrifans_Array trifan_arr = mesh->getTrifans_array();
220  for(size_t itri=0; itri< trifan_arr.getCount(); ++itri)
221  {
222  domTrifansRef trifan = trifan_arr.get(itri);
223 
224  ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
225  dae_mesh->mPrimitives.push_back(dae_primitive);
226  dae_primitive->mType = Dae::PT_TRIFANS;
227  dae_primitive->mCount = (size_t)trifan->getCount();
228 
229  // --- input ---
230  domInputLocalOffset_Array input_arr = trifan->getInput_array();
231  parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
232 
233  // --- ---- p ---- ---
234  for(size_t ip=0; ip<trifan->getP_array().getCount(); ++ip)
235  dae_primitive->mP.push_back( trifan->getP_array().get(ip) );
236 
237  // --- ---- material ---- ---
238  dae_primitive->mMaterial = trifan->getMaterial() ? trifan->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
239 
240  // --- ---- generates the geometry ---- ---
241  generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
242  }
243 
244  // --- ---- triangle strip ---- ---
245  domTristrips_Array tristrip_arr = mesh->getTristrips_array();
246  for(size_t itri=0; itri< tristrip_arr.getCount(); ++itri)
247  {
248  domTristripsRef tristrip = tristrip_arr.get(itri);
249 
250  ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
251  dae_mesh->mPrimitives.push_back(dae_primitive);
252  dae_primitive->mType = Dae::PT_TRISTRIPS;
253  dae_primitive->mCount = (size_t)tristrip->getCount();
254 
255  // --- input ---
256  domInputLocalOffset_Array input_arr = tristrip->getInput_array();
257  parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
258 
259  // --- ---- p ---- ---
260  for(size_t ip=0; ip<tristrip->getP_array().getCount(); ++ip)
261  dae_primitive->mP.push_back( tristrip->getP_array().get(ip) );
262 
263  // --- ---- material ---- ---
264  dae_primitive->mMaterial = tristrip->getMaterial() ? tristrip->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
265 
266  // --- ---- generates the geometry ---- ---
267  generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
268  }
269 
270  // --- ---- polygons ---- ---
271  domPolygons_Array polygon_arr = mesh->getPolygons_array();
272  for(size_t itri=0; itri< polygon_arr.getCount(); ++itri)
273  {
274  domPolygonsRef polygon = polygon_arr.get(itri);
275 
276  ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
277  dae_mesh->mPrimitives.push_back(dae_primitive);
278  dae_primitive->mType = Dae::PT_POLYGONS;
279  dae_primitive->mCount = (size_t)polygon->getCount();
280 
281  // --- input ---
282  domInputLocalOffset_Array input_arr = polygon->getInput_array();
283  parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
284 
285  // --- ---- p ---- ---
286  for(size_t ip=0; ip<polygon->getP_array().getCount(); ++ip)
287  dae_primitive->mP.push_back( polygon->getP_array().get(ip) );
288 
289  // --- ---- material ---- ---
290  dae_primitive->mMaterial = polygon->getMaterial() ? polygon->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
291 
292  // --- ---- generates the geometry ---- ---
293  generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
294  }
295 
296  // --- ---- polylists ---- ---
297  domPolylist_Array polylist_arr = mesh->getPolylist_array();
298  for(size_t itri=0; itri< polylist_arr.getCount(); ++itri)
299  {
300  domPolylistRef polylist = polylist_arr.get(itri);
301 
302  ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
303  dae_mesh->mPrimitives.push_back(dae_primitive);
304  dae_primitive->mType = Dae::PT_POLYGONS;
305  dae_primitive->mCount = (size_t)polylist->getVcount()->getValue().getCount();
306 
307  // --- input ---
308  domInputLocalOffset_Array input_arr = polylist->getInput_array();
309  parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
310 
311  // --- ---- p ---- ---
312  size_t ip=0;
313  for(size_t ivc=0; ivc<polylist->getVcount()->getValue().getCount(); ++ivc)
314  {
315  domPRef p = static_cast<domP*>(domP::create(mDAE).cast());
316  VL_CHECK(p->typeID() == domP::ID());
317  dae_primitive->mP.push_back( p );
318  size_t vcount = (size_t)polylist->getVcount()->getValue()[ivc];
319  p->getValue().setCount(vcount * dae_primitive->mIndexStride);
320  for(size_t i=0; i<p->getValue().getCount(); ++i)
321  p->getValue().set(i, polylist->getP()->getValue()[ip++]);
322  }
323 
324  // --- ---- material ---- ---
325  dae_primitive->mMaterial = polylist->getMaterial() ? polylist->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
326 
327  // --- ---- generates the geometry ---- ---
328  generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
329  }
330 
331  // --- ---- linestrips ---- ---
332  domLinestrips_Array linestrip_arr = mesh->getLinestrips_array();
333  for(size_t itri=0; itri< linestrip_arr.getCount(); ++itri)
334  {
335  domLinestripsRef linestrip = linestrip_arr.get(itri);
336 
337  ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
338  dae_mesh->mPrimitives.push_back(dae_primitive);
339  dae_primitive->mType = Dae::PT_LINE_STRIP;
340  dae_primitive->mCount = (size_t)linestrip->getCount();
341 
342  // --- input ---
343  domInputLocalOffset_Array input_arr = linestrip->getInput_array();
344  parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
345 
346  // --- ---- p ---- ---
347  for(size_t ip=0; ip<linestrip->getP_array().getCount(); ++ip)
348  dae_primitive->mP.push_back( linestrip->getP_array().get(ip) );
349 
350  // --- ---- material ---- ---
351  dae_primitive->mMaterial = linestrip->getMaterial() ? linestrip->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
352 
353  // --- ---- generates the geometry ---- ---
354  generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
355  }
356 
357  // --- ---- lines ---- ---
358  domLines_Array line_arr = mesh->getLines_array();
359  for(size_t itri=0; itri< line_arr.getCount(); ++itri)
360  {
361  domLinesRef line = line_arr.get(itri);
362 
363  ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
364  dae_mesh->mPrimitives.push_back(dae_primitive);
365  dae_primitive->mType = Dae::PT_LINES;
366  dae_primitive->mCount = (size_t)line->getCount();
367 
368  // --- input ---
369  domInputLocalOffset_Array input_arr = line->getInput_array();
370  parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
371 
372  // --- ---- p ---- ---
373  dae_primitive->mP.push_back( line->getP() );
374 
375  // --- ---- material ---- ---
376  dae_primitive->mMaterial = line->getMaterial() ? line->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
377 
378  // --- ---- generates the geometry ---- ---
379  generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
380  }
381 
382  return dae_mesh;
383 }
384 //-----------------------------------------------------------------------------
385 Dae::Source* DaeLoader::getSource(daeElement* source_el)
386 {
387  std::map< daeElementRef, ref<Dae::Source> >::iterator it = mSources.find(source_el);
388  if (it != mSources.end())
389  return it->second.get();
390  else
391  {
392  VL_CHECK(source_el->typeID() == domSource::ID())
393  domSourceRef source = static_cast<domSource*>(source_el);
394 
395  domSource::domTechnique_commonRef tech_common = source->getTechnique_common(); VL_CHECK(tech_common)
396  domAccessorRef accessor = tech_common->getAccessor();
397 
398  size_t mask = 0;
399  // we support up to 32 parameters for a single accessor
400  domParam_Array param_array = accessor->getParam_array();
401  size_t attr_count = param_array.getCount() <= 32 ? param_array.getCount() : 32;
402  for(size_t ipar=0; ipar<attr_count; ++ipar)
403  {
404  if (param_array[ipar]->getName() && strlen(param_array[ipar]->getName()))
405  mask |= 1<<ipar;
406  }
407 
408  ref<Dae::Source> dae_source = new Dae::Source;
409 
410  if (source->getFloat_array())
411  dae_source->init(source->getFloat_array(), accessor->getCount(), accessor->getStride(), accessor->getOffset(), mask);
412  else
413  if (source->getInt_array())
414  dae_source->init(source->getInt_array(), accessor->getCount(), accessor->getStride(), accessor->getOffset(), mask);
415  else
416  if (source->getBool_array())
417  dae_source->init(source->getBool_array(), accessor->getCount(), accessor->getStride(), accessor->getOffset(), mask);
418  else
419  {
420  Log::error("LoadWriterDae: no supported source data found. Only Float_array, Int_array and Bool_array are supported as source data.\n");
421  return NULL;
422  }
423 
424  // add to source library for quick access later
425  mSources[source] = dae_source;
426 
427  return dae_source.get();
428  }
429 }
430 //-----------------------------------------------------------------------------
432 {
433  VL_CHECK(mat)
434  VL_CHECK(mat->mDaeEffect)
435  // VL_CHECK(mat->mDaeEffect->mDaeTechniqueCOMMON)
436 
437  ref<Effect> fx = new Effect;
438  fx->shader()->enable(EN_DEPTH_TEST);
439 
440  // very basic material setup
441  if (mat->mDaeEffect->mDaeTechniqueCOMMON)
442  {
443  Dae::TechniqueCOMMON* common_tech =mat->mDaeEffect->mDaeTechniqueCOMMON.get();
444 
445  // compute the actual tranparency
446  float transparency = 0;
447  if ( common_tech->mOpaqueMode == Dae::OM_A_ONE )
448  transparency = common_tech->mTransparent.mColor.a() * common_tech->mTransparency;
449  else
450  transparency = (1.0f - dot( common_tech->mTransparent.mColor.rgb(), fvec3(0.2126f, 0.7152f, 0.0722f))) * common_tech->mTransparency;
451 
452  bool use_lighting = strstr(mat->mDaeEffect->objectName().c_str(), "blinn:") ||
453  strstr(mat->mDaeEffect->objectName().c_str(), "phong:") ||
454  strstr(mat->mDaeEffect->objectName().c_str(), "lambert:");
455 
456  // enable lighting only if required
457  if ( use_lighting )
458  {
459  fx->shader()->enable(EN_LIGHTING);
460 
461  // mic fixme: most of .dae files I tested require this even if no double_sided flag is set.
462  // fx->shader()->gocLightModel()->setTwoSide(true);
463 
464  // material sanity checks: these are needed only when using fixed function pipeline
465  common_tech->mShininess = vl::clamp(common_tech->mShininess, 0.0f, 128.0f);
466 
467  // mic fixme: this vl::Effect can be put in mDaeTechniqueCOMMON and shared among all the materials that use it.
468  fx->shader()->gocMaterial()->setDiffuse ( common_tech->mDiffuse.mColor ); // this is fuchsia by default
469  fx->shader()->gocMaterial()->setAmbient ( common_tech->mAmbient.mColor );
470  fx->shader()->gocMaterial()->setEmission ( common_tech->mEmission.mColor );
471  fx->shader()->gocMaterial()->setSpecular ( common_tech->mSpecular.mColor );
472  fx->shader()->gocMaterial()->setShininess( common_tech->mShininess );
473 
474  // if a texture is bound to the diffuse channel use it
475  // mic fixme: for the moment we support only one texture, we also assume the texture coords #0 are the right ones...
476  if ( common_tech->mDiffuse.mSampler && common_tech->mDiffuse.mSampler->mTexture )
477  {
478  fx->shader()->gocTextureSampler(0)->setTexture( common_tech->mDiffuse.mSampler->mTexture.get() );
479  fx->shader()->gocMaterial()->setDiffuse( vl::white );
480  }
481 
482  // alpha blending management
483 
484  // sets the alpha value of all material colors, front and back
485  fx->shader()->gocMaterial()->multiplyTransparency( transparency );
486  }
487  else
488  if ( strstr(mat->mDaeEffect->objectName().c_str(), "constant:") )
489  {
490 
491  // constant can have only emission, check if there is a texture attached to it and use it
492  // mic fixme: for the moment we support only one texture, we also assume the texture coords #0 are the right ones...
493  if ( common_tech->mEmission.mSampler && common_tech->mEmission.mSampler->mTexture )
494  {
495  fx->shader()->gocTextureSampler(0)->setTexture( common_tech->mEmission.mSampler->mTexture.get() );
496  // this is already the default: fx->shader()->gocColor()->setColor( vl::white );
497  }
498  else
499  fx->shader()->gocColor()->setValue( common_tech->mEmission.mColor );
500  }
501 
502  // enable alpha blending if material is transparent or alpha is coming from the diffuse texture
503  // NOTE: to be pedantic with the specs we should enabled the alpha blending if common_tech->mBlendingOn == true however
504  // applications and exporters have historically misused the <transparency> and <transparent> tags...
505  if ( transparency < 1.0f || (common_tech->mTransparent.mSampler && common_tech->mTransparent.mSampler == common_tech->mDiffuse.mSampler) )
506  if (!mAssumeOpaque)
507  fx->shader()->enable(EN_BLEND);
508 
509  // to be correct we should do this but most models are not made to render correctly this way...
510 #if 0
511  if (!mat->mDaeEffect->mDoubleSided)
512  fx->shader()->enable(EN_CULL_FACE); // no two sidelighting, yes culling
513  else
514  if (use_lighting)
515  fx->shader()->gocLightModel()->setTwoSide(true); // yes two side lighting, no culling
516 #endif
517  }
518  else
519  {
520  Log::error("LoadWriterDae: technique or profile not supported.\n");
521  fx->shader()->gocMaterial()->setDiffuse( vl::fuchsia );
522  }
523 
524  return fx;
525 }
526 //-----------------------------------------------------------------------------
527 void DaeLoader::bindMaterials(Dae::Node* dae_node, Dae::Mesh* dae_mesh, domBind_materialRef bind_material)
528 {
529  // map symbols to actual materials
530  std::map< std::string, Dae::Material* > material_map;
531 
532  if ( bind_material )
533  {
534  if (bind_material->getTechnique_common())
535  {
536  domInstance_material_Array& material_instances = bind_material->getTechnique_common()->getInstance_material_array();
537  for(size_t i=0; i<material_instances.getCount(); ++i)
538  {
539  daeElement* material = material_instances[i]->getTarget().getElement();
540  VL_CHECK(material)
541  std::map< daeElementRef, ref<Dae::Material> >::iterator it = mMaterials.find( material );
542  if (it != mMaterials.end())
543  {
544  // mic fixme: issue warning
545  // VL_CHECK( material_map.find(material_instances[i]->getSymbol()) == material_map.end() )
546  // VL_CHECK( material_instances[i]->getSymbol() )
547  material_map[ material_instances[i]->getSymbol() ] = it->second.get();
548  }
549  else
550  {
551  VL_LOG_DEBUG << "- LoadWriterDae: material '" << material << "' not found!\n";
552  continue;
553  }
554  }
555  }
556  else
557  {
558  VL_LOG_DEBUG << "- LoadWriterDae: technique_COMMON not found!\n";
559  }
560  }
561 
562  // now we need to instance the material
563  for(size_t iprim=0; iprim<dae_mesh->mPrimitives.size(); ++iprim)
564  {
565  ref<Dae::Material> dae_material;
566 
567  if (!dae_mesh->mPrimitives[iprim]->mMaterial.empty())
568  {
569  std::map< std::string, Dae::Material* >::iterator it = material_map.find( dae_mesh->mPrimitives[iprim]->mMaterial );
570  if (it != material_map.end())
571  {
572  dae_material = it->second;
573  }
574  else
575  {
576  if ( dae_mesh->mPrimitives[iprim]->mMaterial != VL_NO_MATERIAL_SPECIFIED)
577  {
578  VL_LOG_DEBUG << "- LoadWriterDae: material symbol " << dae_mesh->mPrimitives[iprim]->mMaterial << " could not be resolved.\n";
579  }
580  }
581  }
582 
583  ref<Effect> fx = dae_material ? setup_vl_Effect(dae_material.get()) : mDefaultFX;
584 
585  ref<Actor> actor = new Actor( dae_mesh->mPrimitives[iprim]->mGeometry.get(), fx.get(), dae_node->mTransform.get() );
586  dae_node->mActors.push_back( actor );
587  }
588 }
589 //-----------------------------------------------------------------------------
590 void DaeLoader::parseNode(daeElement* el, Dae::Node* parent)
591 {
592  if (el->typeID() == domNode::ID())
593  {
594  // --- --- --- parse this node --- --- ---
595 
596  // create new node and add it to the library
597  ref<Dae::Node> this_node = new Dae::Node;
598  mNodes.push_back(this_node);
599  parent->mChildren.push_back( this_node );
600  parent->mTransform->addChild( this_node->mTransform.get() );
601 
602  domNode* node = static_cast<domNode*>(el);
603 
604  // parse geometries
605  domInstance_geometry_Array geometries = node->getInstance_geometry_array();
606  for(size_t i=0; i<geometries.getCount(); ++i)
607  {
608  VL_CHECK(geometries[i]->getUrl().getElement()->typeID() == domGeometry::ID())
609  daeElement* geometry = geometries[i]->getUrl().getElement();
610  ref<Dae::Mesh> dae_mesh = parseGeometry(geometry);
611  if (dae_mesh)
612  this_node->mMesh.push_back(dae_mesh.get());
613 
614  // generate the Actors belonging to this node with their own material
615  bindMaterials(this_node.get(), dae_mesh.get(), geometries[i]->getBind_material());
616  }
617 
618  // parse controllers
619  if (loadOptions()->extractSkins())
620  {
621  domInstance_controller_Array controllers = node->getInstance_controller_array();
622  for(size_t i=0; i<controllers.getCount(); ++i)
623  {
624  VL_CHECK(controllers[i]->getUrl().getElement()->typeID() == domController::ID())
625  daeElement* controller_el = controllers[i]->getUrl().getElement();
626  VL_CHECK(controller_el)
627  if (!controller_el)
628  continue;
629 
630  domController* controller = static_cast<domController*>(controller_el);
631  daeElement* geometry = controller->getSkin()->getSource().getElement();
632  VL_CHECK(geometry)
633  if (!geometry)
634  continue;
635 
636  ref<Dae::Mesh> dae_mesh = parseGeometry(geometry);
637  if (dae_mesh)
638  this_node->mMesh.push_back(dae_mesh.get());
639 
640  // generate the Actors belonging to this node with their own material
641  bindMaterials(this_node.get(), dae_mesh.get(), controllers[i]->getBind_material());
642  }
643  }
644 
645  // note: transforms are post-multiplied in the order in which they are specified (as if they were sub-nodes)
646  for(size_t ichild=0; ichild<node->getChildren().getCount(); ++ichild)
647  {
648  daeElement* child = node->getChildren()[ichild];
649 
650  if ( 0 == strcmp(child->getElementName(), "matrix") )
651  {
652  domMatrix* matrix = static_cast<domMatrix*>(child);
653  mat4 local_matrix;
654  for(int i=0; i<16; ++i)
655  local_matrix.ptr()[i] = (real)matrix->getValue().get(i);
656  local_matrix.transpose();
657  this_node->mTransform->postMultiply(local_matrix);
658  }
659  else
660  if ( 0 == strcmp(child->getElementName(), "translate") )
661  {
662  domTranslate* tr = static_cast<domTranslate*>(child);
663  mat4 m = mat4::getTranslation((real)tr->getValue()[0], (real)tr->getValue()[1], (real)tr->getValue()[2]);
664  this_node->mTransform->postMultiply( m );
665  }
666  else
667  if ( 0 == strcmp(child->getElementName(), "rotate") )
668  {
669  domRotate* rot = static_cast<domRotate*>(child);
670  mat4 m = mat4::getRotation((real)rot->getValue()[3], (real)rot->getValue()[0], (real)rot->getValue()[1], (real)rot->getValue()[2]);
671  this_node->mTransform->postMultiply( m );
672  }
673  else
674  if ( 0 == strcmp(child->getElementName(), "scale") )
675  {
676  domScale* sc = static_cast<domScale*>(child);
677  mat4 m = mat4::getScaling((real)sc->getValue()[0], (real)sc->getValue()[1], (real)sc->getValue()[2]);
678  this_node->mTransform->postMultiply( m );
679  }
680  else
681  if ( 0 == strcmp(child->getElementName(), "lookat") )
682  {
683  domLookat* lookat = static_cast<domLookat*>(child);
684  vec3 eye ((real)lookat->getValue()[0], (real)lookat->getValue()[1], (real)lookat->getValue()[2]);
685  vec3 look((real)lookat->getValue()[3], (real)lookat->getValue()[4], (real)lookat->getValue()[5]);
686  vec3 up ((real)lookat->getValue()[6], (real)lookat->getValue()[7], (real)lookat->getValue()[8]);
687  this_node->mTransform->preMultiply( mat4::getLookAt(eye, look, up) );
688  }
689  else
690  if ( 0 == strcmp(child->getElementName(), "skew") )
691  {
692  // mic fixme: support skew
693  // domSkew* skew = static_cast<domSkew*>(child);
694  Log::error("LoadWriterDae: <skew> transform not supported yet. Call me if you know how to compute it.\n");
695  }
696  }
697 
698  // parse lights
699  domInstance_light_Array lights = node->getInstance_light_array();
700  for(size_t i=0; i<lights.getCount(); ++i)
701  {
702  daeElementRef dae_light = lights[i]->getUrl().getElement();
703  domLight* dom_light = dynamic_cast<domLight*>(dae_light.cast());
704  ref<Light> light = parseLight(dom_light, this_node->mTransform.get());
705  mLights.push_back( light );
706  }
707 
708  // --- --- --- parse children --- --- ---
709 
710  // parse instance nodes
711  domInstance_node_Array nodes = node->getInstance_node_array();
712  for(size_t i=0; i<nodes.getCount(); ++i)
713  {
714  daeElement* node = nodes[i]->getUrl().getElement();
715  VL_CHECK(node->typeID() == domNode::ID())
716  parseNode(node, this_node.get());
717  }
718 
719  // parse proper children
720  daeTArray< daeSmartRef<daeElement> > children = node->getChildren();
721  for(size_t i=0; i<children.getCount(); ++i)
722  parseNode(children[i], this_node.get());
723  }
724 }
725 //-----------------------------------------------------------------------------
727 {
728  reset();
729 
730  mFilePath = file->path();
731 
732  // load COLLADA file as a string.
733  std::vector<char> buffer;
734  file->load(buffer);
735  if (buffer.empty())
736  return false;
737  buffer.push_back(0);
738 
739  daeElement* root = mDAE.openFromMemory(file->path().toStdString(), (char*)&buffer[0]);
740  if (!root)
741  {
742  Log::error( "LoadWriterDae: failed to open COLLADA document.\n" );
743  return false;
744  }
745 
746  parseAsset(root);
747 
748  parseImages(root->getDescendant("library_images"));
749 
750  parseEffects(root->getDescendant("library_effects"));
751 
752  parseMaterials(root->getDescendant("library_materials"));
753 
754  daeElement* visual_scene = root->getDescendant("visual_scene");
755  if (!visual_scene)
756  {
757  Log::error( "LoadWriterDae: <visual_scene> not found!\n" );
758  return false;
759  }
760 
761  // --- parse the visual scene ---
762 
763  mScene = new Dae::Node;
764  daeTArray< daeSmartRef<daeElement> > children = visual_scene->getChildren();
765  for(size_t i=0; i<children.getCount(); ++i)
766  parseNode(children[i], mScene.get());
767 
768  // --- fill the resource database and final setup ---
769 
770  // --- transform setup ---
771  // Up vector
772  // Note that we don't touch the local space vertices and the intermediate matrices,
773  // for proper reorientation of matrices and geometry the up-vector conditioner in
774  // Refinery should do the job.
775  mScene->mTransform->preMultiply( mUpMatrix );
776  // Setup world matrices
777  mScene->mTransform->computeWorldMatrixRecursive();
778 
779  // --- light setup ---
780  // Computes position and direction of lights, sorts them (direction -> spot -> point),
781  // adds them to the resource database.
782  setupLights();
783 
784  // return the Actors
785  for( size_t inode=0; inode<mNodes.size(); ++inode )
786  {
787  for(size_t i=0; i<mNodes[inode]->mActors.size(); ++i)
788  {
789  Actor* actor = mNodes[inode]->mActors[i].get();
790 
791  // add actor to the resources
792  mResources->resources().push_back( actor );
793 
794  // *** flatten transform hierarchy ***
795  if ( loadOptions()->flattenTransformHierarchy() )
796  actor->transform()->removeFromParent();
797 
798  // *** merge draw calls ***
799  if (loadOptions()->mergeDrawCalls())
800  {
801  Geometry* geom = actor->lod(0)->as<Geometry>();
802  if (geom)
803  {
804  // first merge all tristrips
805  ref<DrawCall> tristrips = geom->mergeTriangleStrips();
806  // keep it for later
807  geom->drawCalls().erase( tristrips.get() );
808 
809  // merge all non-tristrips
811 
812  // put back the tristrips
813  if (tristrips.get())
814  geom->drawCalls().push_back( tristrips.get() );
815  }
816  }
817 
818  // *** check for transforms that require normal rescaling ***
819  mat4 nmatrix = actor->transform()->worldMatrix().as3x3().invert().transpose();
820  real len_x = nmatrix.getX().length();
821  real len_y = nmatrix.getY().length();
822  real len_z = nmatrix.getZ().length();
823  if ( fabs(len_x - 1) > 0.05f || fabs(len_y - 1) > 0.05f || fabs(len_z - 1) > 0.05f )
824  {
825  // Log::warning("Detected mesh with scaled transform: enabled normal renormalization.\n");
826  if ( actor->effect()->shader()->isEnabled(vl::EN_LIGHTING) )
827  actor->effect()->shader()->enable(vl::EN_NORMALIZE); // or vl::EN_RESCALE_NORMAL
828  }
829 
830  // *** light association & normal computation (only if lighting is on!) ***
831  if ( actor->effect()->shader()->isEnabled(EN_LIGHTING) )
832  {
833  // *** light association ***
834  // crete new effect/shader with it's own light set
835  ref<Effect> fx = new Effect;
836  fx->setObjectName( actor->effect()->objectName().c_str() );
837  fx->shader()->setEnableSet( actor->effect()->shader()->getEnableSet() );
838  fx->shader()->setRenderStateSet( actor->effect()->shader()->getRenderStateSet() );
839  actor->setEffect( fx.get() );
840  for(size_t ilight=0; ilight<mLights.size() && ilight<8; ++ilight)
841  fx->shader()->setRenderState( mLights[ilight].get(), ilight );
842 
843  // *** compute missing normals ***
844  Geometry* geom = actor->lod(0)->as<Geometry>();
845  if ( loadOptions()->computeMissingNormals() && geom && !geom->normalArray() )
846  geom->computeNormals();
847  }
848  }
849  }
850 
851  if ( loadOptions()->flattenTransformHierarchy() )
852  mScene->mTransform->flattenHierarchy();
853  else
854  mResources->resources().push_back( mScene->mTransform );
855 
856  return true;
857 }
858 //-----------------------------------------------------------------------------
859 std::string DaeLoader::percentDecode(const char* uri)
860 {
861  std::string str;
862  for(int i=0; uri[i]; ++i)
863  {
864  // process encoded character
865  if ( uri[i] == '%' && uri[i+1] && uri[i+2] )
866  {
867  ++i;
868  char hex1 = uri[i];
869  if (hex1 >= '0' && hex1 <= '9')
870  hex1 -= '0';
871  else
872  if (hex1 >= 'A' && hex1 <= 'F')
873  hex1 -= 'A';
874  else
875  if (hex1 >= 'a' && hex1 <= 'f')
876  hex1 -= 'a';
877  else
878  hex1 = -1;
879 
880  ++i;
881  char hex2 = uri[i];
882  if (hex2 >= '0' && hex2 <= '9')
883  hex2 -= '0';
884  else
885  if (hex2 >= 'A' && hex2 <= 'F')
886  hex2 -= 'A';
887  else
888  if (hex2 >= 'a' && hex2 <= 'f')
889  hex2 -= 'a';
890  else
891  hex2 = -1;
892 
893  // encoding error
894  if (hex1 == -1 || hex2 == -1)
895  {
896  // insert percent code as it is
897  str.push_back('%');
898  i -= 2;
899  }
900 
901  char ch = (hex1 << 4) + (hex2);
902  str.push_back(ch);
903  }
904  else
905  str.push_back(uri[i]);
906  }
907  return str;
908 }
909 //-----------------------------------------------------------------------------
910 void DaeLoader::loadImages(const domImage_Array& images)
911 {
912  for(size_t i=0; i<images.getCount(); ++i)
913  {
914  if ( strstr( images[i]->getInit_from()->getValue().getProtocol(), "file") == 0 )
915  {
916  Log::error( Say("LoadWriterDae: protocol not supported: %s\n") << images[i]->getInit_from()->getValue().getURI() );
917  continue;
918  }
919 
920  std::string full_path = percentDecode( images[i]->getInit_from()->getValue().getURI() + 6 );
921  ref<Image> image = loadImage( full_path.c_str() );
922 
923  mImages[ images[i].cast() ] = image;
924  }
925 }
926 //-----------------------------------------------------------------------------
927 void DaeLoader::parseImages(daeElement* library)
928 {
929  if (!library)
930  return;
931  domLibrary_images* library_images = static_cast<domLibrary_images*>(library);
932  const domImage_Array& images = library_images->getImage_array();
933  loadImages(images);
934 }
935 //-----------------------------------------------------------------------------
936 void DaeLoader::parseEffects(daeElement* library)
937 {
938  if (!library)
939  return;
940  domLibrary_effects* library_effects = static_cast<domLibrary_effects*>(library);
941  const domEffect_Array& effects = library_effects->getEffect_array();
942  for(size_t i=0; i<effects.getCount(); ++i)
943  {
944  domEffect* effect = effects[i].cast();
945 
946  ref<Dae::Effect> dae_effect = new Dae::Effect;
947 
948  std::string effect_name;
949  if (effect->getName())
950  effect_name = effect->getName();
951 
952  mEffects[effect] = dae_effect;
953 
954  // load images
955  loadImages(effect->getImage_array());
956 
957  const domFx_profile_abstract_Array& profiles = effect->getFx_profile_abstract_array();
958  for(size_t i=0; i<profiles.getCount(); ++i)
959  {
960  // <profile_COMMON>
961  if ( profiles[i]->typeID() == domProfile_COMMON::ID() )
962  {
963  domProfile_COMMON* common = static_cast<domProfile_COMMON*>(profiles[i].cast());
964 
965  // --- parse <newparam> ---
966  for(size_t ipar=0; ipar<common->getNewparam_array().getCount(); ++ipar)
967  {
968  domCommon_newparam_typeRef newparam = common->getNewparam_array()[ipar];
969 
970  ref<Dae::NewParam> dae_newparam = new Dae::NewParam;
971  dae_effect->mNewParams.push_back( dae_newparam );
972 
973  // insert in the map se can resolve references to <sampler2D> and <surface>
974  mDaeNewParams[newparam.cast()] = dae_newparam;
975 
976  // --- <surface> ---
977  // mic fixme: for the moment we support only single image 2D surfaces
978  if (newparam->getSurface())
979  {
980  domFx_surface_commonRef surface = newparam->getSurface();
981 
982  if ( !surface->getFx_surface_init_common()->getInit_from_array().getCount() )
983  {
984  VL_LOG_DEBUG << "- 'surface->getFx_surface_init_common()->getInit_from_array().getCount()' is 0: " << __FILE__ << ":" << __LINE__ << "\n";
985  continue;
986  }
987 
988  dae_newparam->mDaeSurface = new Dae::Surface;
989  daeElement* ref_image = surface->getFx_surface_init_common()->getInit_from_array()[0]->getValue().getElement();
990  if (!ref_image)
991  {
992  VL_LOG_DEBUG << "- 'surface->getFx_surface_init_common()->getInit_from_array()[0]->getValue().getElement()' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
993  continue;
994  }
995 
996  std::map< daeElementRef, ref<Image> >::iterator it = mImages.find( ref_image );
997  if (it != mImages.end())
998  dae_newparam->mDaeSurface->mImage = it->second.get();
999  else
1000  {
1001  VL_LOG_DEBUG << "- 'mImages.find( ref_image )' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
1002  continue;
1003  }
1004  }
1005 
1006  // --- <sampler2D> ---
1007  if (newparam->getSampler2D())
1008  {
1009  domFx_sampler2D_commonRef sampler2D = newparam->getSampler2D();
1010 
1011  dae_newparam->mDaeSampler2D = new Dae::Sampler2D;
1012 
1013  // --- <source> ---
1014  daeSIDResolver sid_res( effect, sampler2D->getSource()->getValue() );
1015  domElement* surface_newparam = sid_res.getElement();
1016  if(!surface_newparam)
1017  {
1018  VL_LOG_DEBUG << (Say("- <surface> '%s' referenced by <sampler2D> '%s' not found!\n") << sampler2D->getSource()->getValue() << newparam->getSid() );
1019  continue;
1020  }
1021 
1022  std::map< daeElementRef, ref<Dae::NewParam> >::iterator it = mDaeNewParams.find(surface_newparam);
1023  if ( it != mDaeNewParams.end() )
1024  {
1025  dae_newparam->mDaeSampler2D->mDaeSurface = it->second->mDaeSurface;
1026  }
1027  else
1028  {
1029  VL_LOG_DEBUG << "- 'mDaeNewParams.find(surface_newparam)' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
1030  continue;
1031  }
1032 
1033  // --- <minfilter> ---
1034  if( sampler2D->getMinfilter() )
1035  {
1036  dae_newparam->mDaeSampler2D->mMinFilter = translateSampleFilter( sampler2D->getMinfilter()->getValue() );
1037  }
1038 
1039 
1040  // --- <magfilter> ---
1041  if( sampler2D->getMagfilter() )
1042  {
1043  dae_newparam->mDaeSampler2D->mMagFilter = translateSampleFilter( sampler2D->getMagfilter()->getValue() );
1044  }
1045 
1046  // --- <wrap_s> ---
1047  if (sampler2D->getWrap_s())
1048  {
1049  dae_newparam->mDaeSampler2D->mWrapS = translateWrapMode( sampler2D->getWrap_s()->getValue() );
1050  }
1051 
1052  // --- <wrap_t> ---
1053  if (sampler2D->getWrap_t())
1054  {
1055  dae_newparam->mDaeSampler2D->mWrapT = translateWrapMode( sampler2D->getWrap_t()->getValue() );
1056  }
1057 
1058  // prepare vl::Texture for creation with the given parameters
1059  prepareTexture2D(dae_newparam->mDaeSampler2D.get());
1060  }
1061 
1062  // --- <float>, <float2>, <float3>, <floa4> ---
1063  if ( newparam->getFloat() )
1064  {
1065  dae_newparam->mFloat4 = fvec4((float)newparam->getFloat()->getValue(), 0, 0, 0);
1066  }
1067  else
1068  if ( newparam->getFloat2() )
1069  {
1070  daeDouble* fptr = &newparam->getFloat2()->getValue()[0];
1071  dae_newparam->mFloat4 = fvec4((float)fptr[0], (float)fptr[1], 0, 0);
1072  }
1073  else
1074  if ( newparam->getFloat3() )
1075  {
1076  daeDouble* fptr = &newparam->getFloat3()->getValue()[0];
1077  dae_newparam->mFloat4 = fvec4((float)fptr[0], (float)fptr[1], (float)fptr[2], 0);
1078  }
1079  else
1080  if ( newparam->getFloat4() )
1081  {
1082  daeDouble* fptr = &newparam->getFloat4()->getValue()[0];
1083  dae_newparam->mFloat4 = fvec4((float)fptr[0], (float)fptr[1], (float)fptr[2], (float)fptr[3]);
1084  }
1085  }
1086 
1087  // <technique sid="COMMON">
1088 
1089  // --- parse technique ---
1090  if (common->getTechnique()->getBlinn())
1091  {
1092  // track effect name
1093  effect_name = "blinn:"+effect_name;
1094 
1095  domProfile_COMMON::domTechnique::domBlinnRef blinn = common->getTechnique()->getBlinn();
1096 
1097  dae_effect->mDaeTechniqueCOMMON = new Dae::TechniqueCOMMON;
1098  parseColor( common, blinn->getEmission(), &dae_effect->mDaeTechniqueCOMMON->mEmission );
1099  parseColor( common, blinn->getAmbient(), &dae_effect->mDaeTechniqueCOMMON->mAmbient );
1100  parseColor( common, blinn->getDiffuse(), &dae_effect->mDaeTechniqueCOMMON->mDiffuse );
1101  parseColor( common, blinn->getSpecular(), &dae_effect->mDaeTechniqueCOMMON->mSpecular );
1102  if (blinn->getShininess())
1103  dae_effect->mDaeTechniqueCOMMON->mShininess = (float)blinn->getShininess()->getFloat()->getValue();
1104 
1105  parseColor( common, blinn->getReflective(), &dae_effect->mDaeTechniqueCOMMON->mReflective );
1106  if (blinn->getReflectivity())
1107  dae_effect->mDaeTechniqueCOMMON->mReflectivity = (float)blinn->getReflectivity()->getFloat()->getValue();
1108 
1109  if (blinn->getTransparent())
1110  {
1111  dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
1112  parseColor( common, blinn->getTransparent(), &dae_effect->mDaeTechniqueCOMMON->mTransparent );
1113  dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = blinn->getTransparent()->getOpaque() == FX_OPAQUE_ENUM_A_ONE ? Dae::OM_A_ONE : Dae::OM_RGB_ZERO;
1114  }
1115  if (blinn->getTransparency())
1116  {
1117  dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
1118  dae_effect->mDaeTechniqueCOMMON->mTransparency = (float)blinn->getTransparency()->getFloat()->getValue();
1119  }
1120  }
1121  else
1122  if (common->getTechnique()->getPhong())
1123  {
1124  // track effect name
1125  effect_name = "phong:"+effect_name;
1126 
1127  domProfile_COMMON::domTechnique::domPhongRef phong = common->getTechnique()->getPhong();
1128 
1129  dae_effect->mDaeTechniqueCOMMON = new Dae::TechniqueCOMMON;
1130  parseColor( common, phong->getEmission(), &dae_effect->mDaeTechniqueCOMMON->mEmission );
1131  parseColor( common, phong->getAmbient(), &dae_effect->mDaeTechniqueCOMMON->mAmbient );
1132  parseColor( common, phong->getDiffuse(), &dae_effect->mDaeTechniqueCOMMON->mDiffuse );
1133  parseColor( common, phong->getSpecular(), &dae_effect->mDaeTechniqueCOMMON->mSpecular );
1134  if (phong->getShininess())
1135  {
1136  dae_effect->mDaeTechniqueCOMMON->mShininess = (float)phong->getShininess()->getFloat()->getValue();
1137  }
1138 
1139  parseColor( common, phong->getReflective(), &dae_effect->mDaeTechniqueCOMMON->mReflective );
1140  if (phong->getReflectivity())
1141  dae_effect->mDaeTechniqueCOMMON->mReflectivity = (float)phong->getReflectivity()->getFloat()->getValue();
1142 
1143  if (phong->getTransparent())
1144  {
1145  dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
1146  parseColor( common, phong->getTransparent(), &dae_effect->mDaeTechniqueCOMMON->mTransparent );
1147  dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = phong->getTransparent()->getOpaque() == FX_OPAQUE_ENUM_A_ONE ? Dae::OM_A_ONE : Dae::OM_RGB_ZERO;
1148  }
1149  if (phong->getTransparency())
1150  {
1151  dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
1152  dae_effect->mDaeTechniqueCOMMON->mTransparency = (float)phong->getTransparency()->getFloat()->getValue();
1153  }
1154  }
1155  else
1156  if (common->getTechnique()->getLambert())
1157  {
1158  // track effect name
1159  effect_name = "lambert:"+effect_name;
1160 
1161  domProfile_COMMON::domTechnique::domLambertRef lambert = common->getTechnique()->getLambert();
1162 
1163  dae_effect->mDaeTechniqueCOMMON = new Dae::TechniqueCOMMON;
1164  parseColor( common, lambert->getEmission(), &dae_effect->mDaeTechniqueCOMMON->mEmission );
1165  parseColor( common, lambert->getAmbient(), &dae_effect->mDaeTechniqueCOMMON->mAmbient );
1166  parseColor( common, lambert->getDiffuse(), &dae_effect->mDaeTechniqueCOMMON->mDiffuse );
1167  dae_effect->mDaeTechniqueCOMMON->mSpecular.mColor = fvec4(0,0,0,1);
1168  dae_effect->mDaeTechniqueCOMMON->mShininess = 0;
1169 
1170  parseColor( common, lambert->getReflective(), &dae_effect->mDaeTechniqueCOMMON->mReflective );
1171  if (lambert->getReflectivity())
1172  dae_effect->mDaeTechniqueCOMMON->mReflectivity = (float)lambert->getReflectivity()->getFloat()->getValue();
1173 
1174  if (lambert->getTransparent())
1175  {
1176  dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
1177  parseColor( common, lambert->getTransparent(), &dae_effect->mDaeTechniqueCOMMON->mTransparent );
1178  dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = lambert->getTransparent()->getOpaque() == FX_OPAQUE_ENUM_A_ONE ? Dae::OM_A_ONE : Dae::OM_RGB_ZERO;
1179  }
1180  if (lambert->getTransparency())
1181  {
1182  dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
1183  dae_effect->mDaeTechniqueCOMMON->mTransparency = (float)lambert->getTransparency()->getFloat()->getValue();
1184  }
1185  }
1186  else
1187  if (common->getTechnique()->getConstant())
1188  {
1189  // track effect name
1190  effect_name = "constant:"+effect_name;
1191 
1192  domProfile_COMMON::domTechnique::domConstantRef constant = common->getTechnique()->getConstant();
1193 
1194  dae_effect->mDaeTechniqueCOMMON = new Dae::TechniqueCOMMON;
1195  parseColor( common, constant->getEmission(), &dae_effect->mDaeTechniqueCOMMON->mEmission );
1196  dae_effect->mDaeTechniqueCOMMON->mAmbient.mColor = fvec4(0,0,0,1);
1197  dae_effect->mDaeTechniqueCOMMON->mDiffuse.mColor = fvec4(0,0,0,1);
1198  dae_effect->mDaeTechniqueCOMMON->mSpecular.mColor = fvec4(0,0,0,1);
1199  dae_effect->mDaeTechniqueCOMMON->mShininess = 0;
1200 
1201  parseColor( common, constant->getReflective(), &dae_effect->mDaeTechniqueCOMMON->mReflective );
1202  if (constant->getReflectivity())
1203  dae_effect->mDaeTechniqueCOMMON->mReflectivity = (float)constant->getReflectivity()->getFloat()->getValue();
1204 
1205  if (constant->getTransparent())
1206  {
1207  dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
1208  parseColor( common, constant->getTransparent(), &dae_effect->mDaeTechniqueCOMMON->mTransparent );
1209  dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = constant->getTransparent()->getOpaque() == FX_OPAQUE_ENUM_A_ONE ? Dae::OM_A_ONE : Dae::OM_RGB_ZERO;
1210  }
1211  if (constant->getTransparency())
1212  {
1213  dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
1214  dae_effect->mDaeTechniqueCOMMON->mTransparency = (float)constant->getTransparency()->getFloat()->getValue();
1215  }
1216  }
1217  else
1218  {
1219  Log::error("LoadWriterDae: technique not supported.\n");
1220  }
1221 
1222  dae_effect->setObjectName( effect_name.c_str() );
1223 
1224  // trasparency override options
1225  if (mAssumeOpaque)
1226  {
1227  dae_effect->mDaeTechniqueCOMMON->mTransparency = 1.0f;
1228  dae_effect->mDaeTechniqueCOMMON->mTransparent.mColor = fvec4(0, 0, 0, 1);
1229  dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = Dae::OM_A_ONE; // mic fixme: metti questo dentro Dae:: namespace
1230  }
1231  else
1233  {
1234  dae_effect->mDaeTechniqueCOMMON->mTransparency = 1.0f - dae_effect->mDaeTechniqueCOMMON->mTransparency;
1235  // and don't trust <transparent> values...
1236  dae_effect->mDaeTechniqueCOMMON->mTransparent.mColor = fvec4(0, 0, 0, 1);
1237  dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = Dae::OM_A_ONE;
1238  }
1239 
1240  // <extra>
1241 
1242  for(size_t iextra=0; iextra<common->getExtra_array().getCount(); ++iextra)
1243  {
1244  domExtraRef extra = common->getExtra_array()[iextra];
1245  for(size_t itech=0; itech<extra->getTechnique_array().getCount(); ++itech)
1246  {
1247  domTechniqueRef tech = extra->getTechnique_array()[itech];
1248  if ( strstr(tech->getProfile(), "GOOGLEEARTH") )
1249  {
1250  domAny* double_sided = (domAny*)tech->getChild("double_sided");
1251  if (double_sided)
1252  {
1253  const char* ptr = double_sided->getValue();
1254  if(strcmp(ptr, "1") == 0)
1255  dae_effect->mDoubleSided = true;
1256  }
1257  }
1258  }
1259  }
1260 
1261  }
1262 
1263  }
1264  }
1265 }
1266 //-----------------------------------------------------------------------------
1268 {
1269  if (sampler2D->mDaeSurface && sampler2D->mDaeSurface->mImage)
1270  {
1271  bool use_mipmaps = true;
1272  switch(sampler2D->mMinFilter)
1273  {
1274  case TPF_LINEAR:
1275  case TPF_NEAREST:
1276  if ( loadOptions()->useAlwaysMipmapping() )
1278  else
1279  use_mipmaps = false;
1280  default:
1281  break;
1282  }
1283 
1284  sampler2D->mTexture = new Texture;
1285  sampler2D->mTexture->prepareTexture2D(sampler2D->mDaeSurface->mImage.get(), TF_UNKNOWN, use_mipmaps, false);
1286  sampler2D->mTexture->getTexParameter()->setWrapS(sampler2D->mWrapS);
1287  sampler2D->mTexture->getTexParameter()->setWrapT(sampler2D->mWrapT);
1288  sampler2D->mTexture->getTexParameter()->setMinFilter(sampler2D->mMinFilter);
1289  sampler2D->mTexture->getTexParameter()->setMagFilter(sampler2D->mMagFilter);
1290  }
1291 }
1292 //-----------------------------------------------------------------------------
1293 void DaeLoader::parseMaterials(daeElement* library)
1294 {
1295  if (!library)
1296  return;
1297  domLibrary_materials* library_materials = static_cast<domLibrary_materials*>(library);
1298  const domMaterial_Array& materials = library_materials->getMaterial_array();
1299  for(size_t i=0; i<materials.getCount(); ++i)
1300  {
1301  domElement* effect = materials[i]->getInstance_effect()->getUrl().getElement();
1302  if (!effect)
1303  {
1304  VL_LOG_DEBUG << "- 'materials[i]->getInstance_effect()->getUrl().getElement()' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
1305  continue;
1306  }
1307 
1308  std::map< daeElementRef, ref<Dae::Effect> >::iterator it = mEffects.find(effect);
1309  if (it != mEffects.end())
1310  {
1311  domMaterial* material = materials[i].cast();
1312  ref<Dae::Material> dae_material = new Dae::Material;
1313  dae_material->mDaeEffect = it->second;
1314  mMaterials[ material ] = dae_material;
1315  }
1316  else
1317  {
1318  VL_LOG_DEBUG << "- 'mEffects.find(effect)' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
1319  continue;
1320  }
1321  }
1322 }
1323 //-----------------------------------------------------------------------------
1324 ref<Light> DaeLoader::parseLight(domLight* dom_light, Transform* transform)
1325 {
1326  domLight::domTechnique_commonRef light_common = dom_light->getTechnique_common();
1327 
1328  ref<Light> light = new Light;
1329  if (dom_light->getName())
1330  light->setObjectName( dom_light->getName() );
1331  else
1332  if (dom_light->getID())
1333  light->setObjectName( dom_light->getID() );
1334 
1335  light->bindTransform(transform);
1336 
1337  if (light_common->getPoint())
1338  {
1339  domLight::domTechnique_common::domPointRef point = light_common->getPoint();
1340 
1341  if (point->getColor())
1342  {
1343  domFloat3& c = point->getColor()->getValue();
1344  fvec4 color((float)c[0], (float)c[1], (float)c[2], 1);
1345  light->setAmbient( fvec4(0,0,0,1) );
1346  light->setDiffuse(color);
1347  light->setSpecular(color);
1348  }
1349 
1350  if (point->getConstant_attenuation())
1351  light->setConstantAttenuation( (float)point->getConstant_attenuation()->getValue() );
1352  if (point->getLinear_attenuation())
1353  light->setLinearAttenuation( (float)point->getLinear_attenuation()->getValue() );
1354  if (point->getQuadratic_attenuation())
1355  light->setQuadraticAttenuation( (float)point->getQuadratic_attenuation()->getValue() );
1356 
1357  light->setPosition( fvec4(0,0,0,1) );
1358  }
1359  else
1360  if (light_common->getDirectional())
1361  {
1362  domLight::domTechnique_common::domDirectionalRef directional = light_common->getDirectional();
1363 
1364  if (directional->getColor())
1365  {
1366  domFloat3& c = directional->getColor()->getValue();
1367  fvec4 color((float)c[0], (float)c[1], (float)c[2], 1);
1368  light->setAmbient( fvec4(0,0,0,1) );
1369  light->setDiffuse(color);
1370  light->setSpecular(color);
1371  }
1372 
1373  light->setPosition( fvec4( 0, 0, 1, 0) );
1374  }
1375  else
1376  if (light_common->getSpot())
1377  {
1378  domLight::domTechnique_common::domSpotRef spot= light_common->getSpot();
1379 
1380  if (spot->getColor())
1381  {
1382  domFloat3& c = spot->getColor()->getValue();
1383  fvec4 color((float)c[0], (float)c[1], (float)c[2], 1);
1384  light->setAmbient( fvec4(0,0,0,1) );
1385  light->setDiffuse(color);
1386  light->setSpecular(color);
1387  }
1388 
1389  if (spot->getConstant_attenuation())
1390  light->setConstantAttenuation( (float)spot->getConstant_attenuation()->getValue() );
1391  if (spot->getLinear_attenuation())
1392  light->setLinearAttenuation( (float)spot->getLinear_attenuation()->getValue() );
1393  if (spot->getQuadratic_attenuation())
1394  light->setQuadraticAttenuation( (float)spot->getQuadratic_attenuation()->getValue() );
1395 
1396  if (spot->getFalloff_angle())
1397  light->setSpotCutoff( (float)spot->getFalloff_angle()->getValue() );
1398  if (spot->getFalloff_exponent())
1399  light->setSpotExponent( (float)spot->getFalloff_exponent()->getValue() );
1400 
1401  light->setSpotDirection( fvec3(0,0,-1) );
1402  light->setPosition( fvec4( 0, 0, 0, 1) );
1403  }
1404  else
1405  if (light_common->getAmbient())
1406  {
1407  domLight::domTechnique_common::domAmbientRef ambient = light_common->getAmbient();
1408 
1409  if (ambient->getColor())
1410  {
1411  domFloat3& c = ambient->getColor()->getValue();
1412  fvec4 color((float)c[0], (float)c[1], (float)c[2], 1);
1413  light->setAmbient( color );
1414  light->setDiffuse( fvec4(0,0,0,1) );
1415  light->setSpecular( fvec4(0,0,0,1) );
1416  }
1417 
1418  // this is actually irrelevant since the diffuse and specular colors are zeroed.
1419  light->setPosition( fvec4( 0, 0, 0, 1) );
1420 
1421  // just for clarity, no attenuation
1422  light->setConstantAttenuation( 1 );
1423  light->setLinearAttenuation( 0 );
1424  light->setQuadraticAttenuation( 0 );
1425  }
1426 
1427  return light;
1428 }
1429 //-----------------------------------------------------------------------------
1431 {
1432  // generate light meshes
1433  if (loadOptions()->lightMeshSize())
1434  {
1435  for(size_t i=0; i<mLights.size(); ++i)
1436  {
1437  // spot light
1438  if (mLights[i]->spotCutoff() != 180)
1439  {
1440  ref<Geometry> light_mesh = vl::makeCone( vec3(0,0,0), loadOptions()->lightMeshSize(), loadOptions()->lightMeshSize(), 10 );
1441  light_mesh->transform( mat4::getTranslation(0,loadOptions()->lightMeshSize(),0) );
1442  light_mesh->transform( mat4::getRotation(90, +1,0,0) );
1443  light_mesh->setObjectName( ("LightMesh-" + mLights[i]->objectName()).c_str() );
1444  ref<Effect> fx = new Effect;
1445  fx->shader()->enable(EN_DEPTH_TEST);
1446  fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
1447  fx->shader()->gocColor()->setValue(vl::fuchsia);
1448  mResources->resources().push_back( new Actor( light_mesh.get(), fx.get(), mLights[i]->boundTransform() ) );
1449  }
1450  else
1451  // directional light
1452  if (mLights[i]->position().w() == 0)
1453  {
1454  ref<Geometry> light_mesh = vl::makePyramid( vec3(0,0,0), loadOptions()->lightMeshSize() / 2, loadOptions()->lightMeshSize() );
1455  light_mesh->transform( mat4::getRotation(90, -1,0,0) );
1456  light_mesh->setObjectName( ("LightMesh-" + mLights[i]->objectName()).c_str() );
1457  ref<Effect> fx = new Effect;
1458  fx->shader()->enable(EN_DEPTH_TEST);
1459  fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
1460  fx->shader()->gocColor()->setValue(vl::fuchsia);
1461  mResources->resources().push_back( new Actor( light_mesh.get(), fx.get(), mLights[i]->boundTransform() ) );
1462  }
1463  else
1464  // point light
1465  if( mLights[i]->ambient() == fvec4(0,0,0,1) )
1466  {
1467  ref<Geometry> light_mesh = vl::makeUVSphere( vec3(0,0,0), loadOptions()->lightMeshSize(), 10, 5);
1468  light_mesh->setObjectName( ("LightMesh-" + mLights[i]->objectName()).c_str() );
1469  ref<Effect> fx = new Effect;
1470  fx->shader()->enable(EN_DEPTH_TEST);
1471  fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
1472  fx->shader()->gocColor()->setValue(vl::fuchsia);
1473  mResources->resources().push_back( new Actor( light_mesh.get(), fx.get(), mLights[i]->boundTransform() ) );
1474  }
1475  else
1476  // ambient light
1477  {
1478  ref<Geometry> light_mesh = vl::makeTorus( vec3(0,0,0), loadOptions()->lightMeshSize(), loadOptions()->lightMeshSize()/4, 8, 14);
1479  light_mesh->setNormalArray(NULL); // remove normals
1480  light_mesh->setObjectName( ("LightMesh-" + mLights[i]->objectName()).c_str() );
1481  ref<Effect> fx = new Effect;
1482  fx->shader()->enable(EN_DEPTH_TEST);
1483  fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
1484  fx->shader()->gocColor()->setValue(vl::fuchsia);
1485  mResources->resources().push_back( new Actor( light_mesh.get(), fx.get(), mLights[i]->boundTransform() ) );
1486  }
1487  }
1488  }
1489 
1490  struct dummy
1491  {
1492  static bool light_sorter(const ref<Light>& a, const ref<Light>& b)
1493  {
1494  // ambient lights first
1495  if (a->ambient() != b->ambient())
1496  return b->ambient() < a->ambient();
1497  else
1498  // directional lights first
1499  if (a->position().w() != b->position().w())
1500  return a->position().w() < b->position().w();
1501  else
1502  // point lights first, spotlights last
1503  return a->spotCutoff() > b->spotCutoff();
1504  }
1505  };
1506 
1507  std::sort(mLights.begin(), mLights.end(), dummy::light_sorter);
1508 
1509  // set light indices and adds to the resource database
1510  for(size_t i=0; i<mLights.size(); ++i)
1511  {
1512  mResources->resources().push_back( mLights[i].get() );
1513  }
1514 
1515  if (loadOptions()->exportLights() == false)
1516  mLights.clear();
1517 
1518  // default light if no lights were present in the scene or exportLights() == false
1519  if (mLights.empty())
1520  {
1521  mLights.push_back( new Light );
1522  mLights[0]->setObjectName(VL_DEFAULT_LIGHT);
1523  }
1524 }
1525 //-----------------------------------------------------------------------------
1527 {
1528  for(int i=0; SemanticTable[i].mSemanticString; ++i)
1529  {
1530  if (strcmp(semantic, SemanticTable[i].mSemanticString) == 0)
1531  return SemanticTable[i].mSemantic;
1532  }
1533 
1534  return Dae::IS_UNKNOWN;
1535 }
1536 //-----------------------------------------------------------------------------
1538 {
1539  for(int i=0; SemanticTable[i].mSemanticString; ++i)
1540  {
1541  if ( semantic == SemanticTable[i].mSemantic )
1542  return SemanticTable[i].mSemanticString;
1543  }
1544 
1545  return NULL;
1546 }
1547 //-----------------------------------------------------------------------------
1548 ETexParamFilter DaeLoader::translateSampleFilter(domFx_sampler_filter_common filter)
1549 {
1550  switch(filter)
1551  {
1552  case FX_SAMPLER_FILTER_COMMON_NEAREST: return TPF_NEAREST;
1553  case FX_SAMPLER_FILTER_COMMON_LINEAR: return TPF_LINEAR;
1554  case FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_NEAREST: return TPF_NEAREST_MIPMAP_NEAREST;
1555  case FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_NEAREST: return TPF_LINEAR_MIPMAP_NEAREST;
1556  case FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_LINEAR: return TPF_NEAREST_MIPMAP_LINEAR;
1557  case FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_LINEAR: return TPF_LINEAR_MIPMAP_LINEAR;
1558  default: return (ETexParamFilter)0;
1559  }
1560 }
1561 //-----------------------------------------------------------------------------
1562 ETexParamWrap DaeLoader::translateWrapMode(domFx_sampler_wrap_common wrap)
1563 {
1564  switch(wrap)
1565  {
1566  case FX_SAMPLER_WRAP_COMMON_WRAP: return TPW_REPEAT;
1567  case FX_SAMPLER_WRAP_COMMON_MIRROR: return TPW_MIRRORED_REPEAT;
1568  case FX_SAMPLER_WRAP_COMMON_CLAMP: return TPW_CLAMP;
1569  case FX_SAMPLER_WRAP_COMMON_BORDER: return TPW_CLAMP_TO_BORDER;
1570  default: return (ETexParamWrap)0;
1571  }
1572 }
1573 //-----------------------------------------------------------------------------
1574 template<class T_color_or_texture>
1575 void DaeLoader::parseColor(const domProfile_COMMON* common, const T_color_or_texture& color_or_texture, Dae::ColorOrTexture* out_col)
1576 {
1577  if (!color_or_texture)
1578  return;
1579 
1580  if (color_or_texture->getColor())
1581  {
1582  domFx_color_common& col = color_or_texture->getColor()->getValue();
1583  out_col->mColor = fvec4( (float)col[0], (float)col[1], (float)col[2], (float)col[3] );
1584  }
1585 
1586  if (color_or_texture->getTexture())
1587  {
1588  // <texture texture="...">
1589  daeSIDResolver sid_res( const_cast<domProfile_COMMON*>(common), color_or_texture->getTexture()->getTexture() );
1590  domElement* sampler2D_newparam = sid_res.getElement();
1591 
1592  std::map< daeElementRef, ref<Dae::NewParam> >::iterator it = mDaeNewParams.find(sampler2D_newparam);
1593  if ( it != mDaeNewParams.end() )
1594  {
1595  VL_CHECK(it->second->mDaeSampler2D)
1596  out_col->mSampler = it->second->mDaeSampler2D;
1597  if ( it->second->mDaeSampler2D.get() == NULL)
1598  {
1599  VL_LOG_DEBUG << "- LoadWriterDae: malformed file: <texture texture=..> points to a <newparam> that does not contain <sampler2D>!\n";
1600  }
1601  }
1602  else
1603  {
1604  std::map< daeElementRef, ref<Image> >::iterator it = mImages.find(sampler2D_newparam);
1605  if ( it != mImages.end() )
1606  {
1607  // create dummy sampler
1608  out_col->mSampler = new Dae::Sampler2D;
1609  out_col->mSampler->mDaeSurface = new Dae::Surface;
1610  out_col->mSampler->mDaeSurface->mImage = it->second;
1611  prepareTexture2D( out_col->mSampler.get() );
1612  VL_LOG_DEBUG << "- LoadWriterDae: malformed file: <texture texture=..> parameter points to an <image> instead of a <sampler2D>!\n"
1613  "VL will create a dummy sampler with the specified image.\n";
1614  }
1615  else
1616  {
1617  VL_LOG_DEBUG << "- LoadWriterDae: malformed file: <texture texture=..> could not be resolved to anything!\n";
1618  }
1619  }
1620 
1621  // <texture texcoord="...">
1622  out_col->mTexCoord = color_or_texture->getTexture()->getTexcoord();
1623  }
1624 }
1625 //-----------------------------------------------------------------------------
1626 void DaeLoader::generateGeometry(Dae::Primitive* prim, const char* name)
1627 {
1628  VL_CHECK(prim->mIndexStride);
1629 
1630  prim->mGeometry = new Geometry;
1631  if (name)
1632  prim->mGeometry->setObjectName(name);
1633 
1634  // no primitives where specified so we treat it as a cloud of points simulating a single increasing <p>
1635  if(prim->mP.size() == 0 && prim->mType == Dae::PT_UNKNOWN && prim->mChannels.size())
1636  {
1637  // some sanity checks
1638  for(size_t i=0; i<prim->mChannels.size(); ++i)
1639  {
1640  if ( prim->mChannels[i]->mSource->count() != prim->mChannels[0]->mSource->count() )
1641  {
1642  VL_LOG_DEBUG << "- LoadWriterDae: cannot generate point cloud: channels have different sizes!\n";
1643  return;
1644  }
1645  if ( prim->mChannels[i]->mOffset != 0 )
1646  {
1647  VL_LOG_DEBUG << "- LoadWriterDae: cannot generate point cloud: channels must have offset == 0!\n";
1648  return;
1649  }
1650  }
1651 
1652  // generate dummy <p>
1653  prim->mP.resize(1);
1654  prim->mP[0] = static_cast<domP*>(domP::create(mDAE).cast());
1655  prim->mP[0]->getValue().setCount( prim->mChannels[0]->mSource->count() );
1656  for (size_t i=0; i<prim->mChannels[0]->mSource->count(); ++i)
1657  prim->mP[0]->getValue()[i] = i;
1658  }
1659 
1660  size_t total_index_count = 0;
1661  for(size_t ip=0; ip<prim->mP.size(); ++ip)
1662  total_index_count += prim->mP[ip]->getValue().getCount();
1663 
1664  ref<ArrayUInt1> index_buffer = new ArrayUInt1;
1665  index_buffer->resize( total_index_count / prim->mIndexStride );
1666 
1667  std::vector<GLint> vcount;
1668 
1669  // generate index buffer for DrawElements or MultiDrawElements.
1670  std::set<Dae::Vert> vert_set;
1671  for(size_t ip=0, iidx=0; ip<prim->mP.size(); ++ip)
1672  {
1673  const domListOfUInts& p = prim->mP[ip]->getValue();
1674 
1675  vcount.push_back( p.getCount() / prim->mIndexStride );
1676 
1677  for(size_t ivert=0; ivert<p.getCount(); ivert+=prim->mIndexStride, ++iidx)
1678  {
1679  Dae::Vert vert;
1680 
1681  // fill vertex info
1682  for(size_t ichannel=0; ichannel<prim->mChannels.size(); ++ichannel)
1683  vert.mAttribIndex[ichannel] = (size_t)p[ivert + prim->mChannels[ichannel]->mOffset];
1684 
1685  size_t final_index = 0xFFFFFFFF;
1686  // retrieve/insert the vertex
1687  std::set<Dae::Vert>::iterator it = vert_set.find(vert);
1688  if (it == vert_set.end())
1689  {
1690  vert.mIndex = final_index = vert_set.size();
1691  vert_set.insert(vert);
1692  }
1693  else
1694  final_index = it->mIndex;
1695 
1696  // this is the actual index
1697  (*index_buffer)[iidx] = final_index;
1698  }
1699  }
1700 
1701  if (vcount.size() == 1)
1702  {
1703  // use DrawElements
1705  switch(prim->mType)
1706  {
1707  case Dae::PT_UNKNOWN: de = new DrawElementsUInt( PT_POINTS ); break; // of course we can do better than this but we would need a lot of extra logic
1708  case Dae::PT_LINES: de = new DrawElementsUInt( PT_LINES ); break;
1709  case Dae::PT_LINE_STRIP: de = new DrawElementsUInt( PT_LINE_STRIP ); break;
1710  case Dae::PT_POLYGONS: de = new DrawElementsUInt( PT_POLYGON ); break;
1711  case Dae::PT_TRIFANS: de = new DrawElementsUInt( PT_TRIANGLE_FAN ); break;
1712  case Dae::PT_TRIANGLES: de = new DrawElementsUInt( PT_TRIANGLES ); break;
1713  case Dae::PT_TRISTRIPS: de = new DrawElementsUInt( PT_TRIANGLE_STRIP ); break;
1714  default:
1715  VL_TRAP()
1716  }
1717 
1718  de->setIndexBuffer( index_buffer.get() );
1719  prim->mGeometry->drawCalls().push_back( de.get() );
1720  }
1721  else
1722  {
1723  // use MultiDrawElements
1725  switch(prim->mType)
1726  {
1727  case Dae::PT_UNKNOWN: mde = new MultiDrawElementsUInt( PT_POINTS ); break; // of course we can do better than this but we would need a lot of extra logic
1728  case Dae::PT_LINES: mde = new MultiDrawElementsUInt( PT_LINES ); break;
1729  case Dae::PT_LINE_STRIP: mde = new MultiDrawElementsUInt( PT_LINE_STRIP ); break;
1730  case Dae::PT_POLYGONS: mde = new MultiDrawElementsUInt( PT_POLYGON ); break;
1731  case Dae::PT_TRIFANS: mde = new MultiDrawElementsUInt( PT_TRIANGLE_FAN ); break;
1732  case Dae::PT_TRIANGLES: mde = new MultiDrawElementsUInt( PT_TRIANGLES ); break;
1733  case Dae::PT_TRISTRIPS: mde = new MultiDrawElementsUInt( PT_TRIANGLE_STRIP ); break;
1734  default:
1735  VL_TRAP()
1736  }
1737 
1738  mde->setIndexBuffer( index_buffer.get() );
1739  mde->setCountVector( vcount );
1740  prim->mGeometry->drawCalls().push_back( mde.get() );
1741  }
1742 
1743  // generate new vertex attrib info and install data
1744  size_t tex_unit = 0;
1745  for( size_t ich=0; ich<prim->mChannels.size(); ++ich )
1746  {
1747  // init data storage for this channel
1748  ref<ArrayAbstract> vert_attrib;
1749  float* ptr = NULL;
1750  float* ptr_end = NULL;
1751  switch(prim->mChannels[ich]->mSource->dataSize())
1752  {
1753  case 1:
1754  {
1755  ref<ArrayFloat1> array_f1 = new ArrayFloat1;
1756  vert_attrib = array_f1;
1757  array_f1->resize( vert_set.size() );
1758  ptr = array_f1->begin();
1759  // debug
1760  ptr_end = ptr + vert_set.size() * 1;
1761  break;
1762  }
1763  case 2:
1764  {
1765  ref<ArrayFloat2> array_f2 = new ArrayFloat2;
1766  vert_attrib = array_f2;
1767  array_f2->resize( vert_set.size() );
1768  ptr = array_f2->at(0).ptr();
1769  // debug
1770  ptr_end = ptr + vert_set.size() * 2;
1771  break;
1772  }
1773  case 3:
1774  {
1775  ref<ArrayFloat3> array_f3 = new ArrayFloat3;
1776  vert_attrib = array_f3;
1777  array_f3->resize( vert_set.size() );
1778  ptr = array_f3->at(0).ptr();
1779  // debug
1780  ptr_end = ptr + vert_set.size() * 3;
1781  break;
1782  }
1783  case 4:
1784  {
1785  ref<ArrayFloat4> array_f4 = new ArrayFloat4;
1786  vert_attrib = array_f4;
1787  array_f4->resize( vert_set.size() );
1788  ptr = array_f4->at(0).ptr();
1789  // debug
1790  ptr_end = ptr + vert_set.size() * 4;
1791  break;
1792  }
1793  default:
1794  Log::warning( Say("LoadWriterDae: input '%s' skipped because parameter count is more than 4.\n") << getSemanticString(prim->mChannels[ich]->mSemantic) );
1795  continue;
1796  }
1797 
1798  // install vertex attribute
1799  switch(prim->mChannels[ich]->mSemantic)
1800  {
1801  case Dae::IS_POSITION: prim->mGeometry->setVertexArray( vert_attrib.get() ); break;
1802  case Dae::IS_NORMAL: prim->mGeometry->setNormalArray( vert_attrib.get() ); break;
1803  case Dae::IS_COLOR: prim->mGeometry->setColorArray( vert_attrib.get() ); break;
1804  case Dae::IS_TEXCOORD: prim->mGeometry->setTexCoordArray( tex_unit++, vert_attrib.get() ); break;
1805  default:
1806  VL_LOG_DEBUG << ( Say("- LoadWriterDae: input semantic '%s' not supported.\n") << getSemanticString(prim->mChannels[ich]->mSemantic) );
1807  continue;
1808  }
1809 
1810  // name it as TEXCOORD@SET0 etc. to be recognized when binding (not used yet)
1811  vert_attrib->setObjectName( String(Say("%s@SET%n") << getSemanticString(prim->mChannels[ich]->mSemantic) << prim->mChannels[ich]->mSet).toStdString().c_str() );
1812 
1813  // fill the vertex attribute array
1814  for(std::set<Dae::Vert>::iterator it = vert_set.begin(); it != vert_set.end(); ++it)
1815  {
1816  const Dae::Vert& vert = *it;
1817  size_t idx = vert.mAttribIndex[ich];
1818  VL_CHECK(ptr + prim->mChannels[ich]->mSource->dataSize()*vert.mIndex < ptr_end);
1819  prim->mChannels[ich]->mSource->readData(idx, ptr +prim-> mChannels[ich]->mSource->dataSize()*vert.mIndex);
1820  }
1821  }
1822 
1823  // --- fix bad normals ---
1824  if ( loadOptions()->fixBadNormals() && prim->mGeometry->normalArray() )
1825  {
1826  ref<ArrayFloat3> norm_old = vl::cast<ArrayFloat3>(prim->mGeometry->normalArray());
1827  VL_CHECK(norm_old);
1828 
1829  // recompute normals
1830  prim->mGeometry->computeNormals();
1831  ref<ArrayFloat3> norm_new = vl::cast<ArrayFloat3>(prim->mGeometry->normalArray());
1832  VL_CHECK(norm_new);
1833 
1834  size_t flipped = 0;
1835  size_t degenerate = 0;
1836  for(size_t i=0; i<norm_new->size(); ++i)
1837  {
1838  // compare VL normals with original ones
1839  float l = norm_old->at(i).length();
1840  if ( l < 0.5f )
1841  {
1842  norm_old->at(i) = norm_new->at(i);
1843  ++degenerate;
1844  }
1845 
1846  if ( l < 0.9f || l > 1.1f )
1847  {
1848  norm_old->at(i).normalize();
1849  ++degenerate;
1850  }
1851 
1852  if ( dot(norm_new->at(i), norm_old->at(i)) < -0.1f )
1853  {
1854  norm_old->at(i) = -norm_old->at(i);
1855  ++flipped;
1856  }
1857  }
1858 
1859  // mic fixme: issue these things as debug once things got stable
1860  if (degenerate || flipped)
1861  VL_LOG_DEBUG << ( Say("- LoadWriterDae: fixed bad normals in \"%s\": degenerate=%n, flipped=%n (out of %n).\n") << prim->mGeometry->objectName() << degenerate << flipped << norm_old->size() );
1862 
1863  // reinstall fixed normals
1864  prim->mGeometry->setNormalArray(norm_old.get());
1865  }
1866 
1867  // disabled: we transform the root matrix instead
1868  // --- orient geometry based on up vector ---
1869  // prim->mGeometry->transform((mat4)mUpMatrix);
1870 }
1871 //-----------------------------------------------------------------------------
1872 void DaeLoader::parseAsset(domElement* root)
1873 {
1874  domElement* asset_el = root->getChild("asset");
1875  if (asset_el)
1876  {
1877  domAsset* asset = static_cast<domAsset*>(asset_el);
1878 
1879  // up vector
1880  if (asset->getUp_axis())
1881  {
1882  if( asset->getUp_axis()->getValue() == UPAXISTYPE_X_UP )
1883  {
1884  // X_UP Negative y Positive x Positive z
1885  mUpMatrix.setX( vec3( 0, 1, 0) );
1886  mUpMatrix.setY( vec3(-1, 0, 0) );
1887  mUpMatrix.setZ( vec3( 0, 0, 1) );
1888  }
1889  else
1890  if( asset->getUp_axis()->getValue() == UPAXISTYPE_Z_UP )
1891  {
1892  // Z_UP Positive x Positive z Negative y
1893  mUpMatrix.setX( vec3(1, 0, 0) );
1894  mUpMatrix.setY( vec3(0, 0,-1) );
1895  mUpMatrix.setZ( vec3(0, 1, 0) );
1896  }
1897  }
1898 
1899  // try to fix the transparency written by crappy tools
1900  mInvertTransparency = false;
1901  mAssumeOpaque = false;
1902  if (loadOptions()->invertTransparency() == LoadWriterDae::LoadOptions::TransparencyInvert)
1903  mInvertTransparency = true;
1904  else
1905  if (loadOptions()->invertTransparency() == LoadWriterDae::LoadOptions::TransparencyAuto)
1906  {
1907  for(size_t i=0; i<asset->getContributor_array().getCount(); ++i)
1908  {
1909  const char* tool = asset->getContributor_array()[i]->getAuthoring_tool()->getValue();
1910 
1911  if (!tool)
1912  continue;
1913 
1914  VL_LOG_DEBUG << "- Authoring tool = " << tool << "\n";
1915 
1916  // Google SketchUp before 7.1 requires <transparency> inversion.
1917  // see http://www.collada.org/public_forum/viewtopic.php?f=12&t=1667
1918  const char* google_str = strstr(tool, "Google SketchUp");
1919  size_t google_str_len = strlen("Google SketchUp");
1920  if ( google_str )
1921  {
1922  if ( strlen(google_str) > google_str_len )
1923  {
1924  float version = 1000;
1925  if ( sscanf( google_str + google_str_len, "%f", &version) )
1926  {
1927  version = version * 100 + 0.5f;
1928  if (version < 710)
1929  mInvertTransparency = true;
1930  }
1931  else
1932  {
1933  // don't trust Google SketchUp if we cannot read the version
1934  mAssumeOpaque = true;
1935  }
1936  }
1937  else
1938  {
1939  // don't trust Google SketchUp if we cannot read the version
1940  mAssumeOpaque = true;
1941  }
1942  break;
1943  }
1944 
1945  // See https://collada.org/mediawiki/index.php/ColladaMaya#ColladaMaya_3.03
1946  // - "Data exported with previous versions of our COLLADA tools may import with inverted transparency in ColladaMax 3.03 and ColladaMaya 3.03."
1947  // - Actually ColladaMax/ColladaMaya before 3.03 use unpredictable combinations of <transparent> and <transparency>, so... we assume opaque.
1948 
1949  const char* colladamaya_str = strstr(tool, "ColladaMaya v");
1950  size_t colladamaya_str_len = strlen("ColladaMaya v");
1951  if ( colladamaya_str )
1952  {
1953  float version = 1000;
1954  if ( strlen(colladamaya_str) > colladamaya_str_len )
1955  {
1956  if ( sscanf( colladamaya_str + colladamaya_str_len, "%f", &version) )
1957  {
1958  version = version * 100 + 0.5f;
1959  if (version < 303)
1960  mAssumeOpaque = true;
1961  }
1962  else
1963  {
1964  // don't trust ColladaMaya if we cannot read the version
1965  mAssumeOpaque = true;
1966  }
1967  }
1968  else
1969  {
1970  // don't trust ColladaMaya if we cannot read the version
1971  mAssumeOpaque = true;
1972  }
1973  }
1974 
1975  const char* colladamax_str = strstr(tool, "ColladaMax v");
1976  size_t colladamax_str_len = strlen("ColladaMax v");
1977  if ( colladamax_str )
1978  {
1979  float version = 1000;
1980  if ( strlen(colladamax_str) > colladamax_str_len )
1981  {
1982  if ( sscanf( colladamax_str + colladamax_str_len, "%f", &version) )
1983  {
1984  version = version * 100 + 0.5f;
1985  if (version < 303)
1986  mAssumeOpaque = true;
1987  }
1988  else
1989  {
1990  // don't trust ColladaMax if we cannot read the version
1991  mAssumeOpaque = true;
1992  }
1993  }
1994  else
1995  {
1996  // don't trust ColladaMax if we cannot read the version
1997  mAssumeOpaque = true;
1998  }
1999  }
2000 
2001  // MeshLab seem to flip the transparency also now.
2002  if ( strstr(tool, "VCGLib | MeshLab") )
2003  {
2004  mInvertTransparency = true;
2005  }
2006 
2007  VL_LOG_DEBUG << "- Invert transparency = " << (mInvertTransparency ? "yes" : "no.") << "\n";
2008  VL_LOG_DEBUG << "- Assume opaque = " << (mAssumeOpaque? "yes" : "no.") << "\n";
2009 
2010  // stop at the first contributor
2011  break;
2012  }
2013  }
2014  }
2015 }
bool extractSkins() const
If set to true the skinned geometries will be also exported. Enabled by default.
Definition: ioDae.hpp:112
Associates a Renderable object to an Effect and Transform.
Definition: Actor.hpp:130
Material * gocMaterial()
Definition: Shader.cpp:119
COLLADA sampler2D.
Definition: DaeHelpers.hpp:304
const Renderable * lod(int lod_index) const
Returns the Renderable object representing the LOD level specifed by lod_index.
Definition: Actor.hpp:173
float clamp(float x, float minval, float maxval)
Definition: Vector2.hpp:316
void setEffect(Effect *effect)
Binds an Effect to an Actor.
Definition: Actor.hpp:196
COLLADA common technique.
Definition: DaeHelpers.hpp:341
static Dae::EInputSemantic getSemantic(const char *semantic)
Definition: DaeLoader.cpp:1526
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:228
An array of vl::fvec4.
Definition: Array.hpp:416
int isEnabled(EEnable capability) const
Definition: Shader.hpp:2164
#define VL_LOG_DEBUG
Definition: Log.hpp:222
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:253
size_t mAttribIndex[MAX_ATTRIBS]
Definition: DaeHelpers.hpp:118
Transform * transform()
Returns the Transform bound tho an Actor.
Definition: Actor.hpp:190
ref< Dae::Surface > mDaeSurface
Definition: DaeHelpers.hpp:315
Implements a 4x4 matrix transform used to define the position and orientation of an Actor...
Definition: Transform.hpp:72
Vector3< T_Scalar > getZ() const
Definition: Matrix4.hpp:131
ref< Dae::TechniqueCOMMON > mDaeTechniqueCOMMON
Definition: DaeHelpers.hpp:391
void setIndexBuffer(arr_type *index_buffer)
const T * get() const
Definition: Object.hpp:128
Color * gocColor()
Definition: Shader.cpp:103
An abstract class representing a file.
Definition: VirtualFile.hpp:60
< Transparency becomes 1.0 - <transparency>.
Definition: ioDae.hpp:60
void bindMaterials(Dae::Node *dae_node, Dae::Mesh *dae_mesh, domBind_materialRef bind_material)
Definition: DaeLoader.cpp:527
std::vector< ref< Dae::Primitive > > mPrimitives
Definition: DaeHelpers.hpp:279
If enabled, do depth comparisons and update the depth buffer; Note that even if the depth buffer exis...
float spotCutoff() const
Valid values are from 0.0f to 90.0f plus the special value 180.0f (default) which disables the spot l...
Definition: Light.hpp:90
Vector4< float > fvec4
A 4 components vector with float precision.
Definition: Vector4.hpp:280
Matrix4 & setX(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:141
void parseImages(daeElement *library)
Definition: DaeLoader.cpp:927
A simple String formatting class.
Definition: Say.hpp:124
void setObjectName(const char *name)
The name of the object, by default set to the object&#39;s class name in debug builds.
Definition: Object.hpp:220
static void warning(const String &message)
Use this function to provide information about situations that might lead to errors or loss of data...
Definition: Log.cpp:155
Matrix4 & transpose()
Definition: Matrix4.hpp:355
ETexParamFilter
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
std::vector< ref< Dae::Input > > mVertexInputs
Definition: DaeHelpers.hpp:278
EnableSet * getEnableSet()
Definition: Shader.hpp:2229
If enabled, use the current lighting parameters to compute the vertex color; Otherwise, simply associate the current color with each vertex, see also Material, LightModel, and Light.
void loadImages(const domImage_Array &images)
Definition: DaeLoader.cpp:910
Dae::ColorOrTexture mSpecular
Definition: DaeHelpers.hpp:372
VLGRAPHICS_EXPORT ref< Geometry > makeCone(const vec3 &origin, real diameter=1, real height=1, int phi=20, bool bottom=true)
Creates a cone.
COLLADA data source.
Definition: DaeHelpers.hpp:123
void setRenderStateSet(RenderStateSet *rss)
Definition: Shader.hpp:2277
ref< Light > parseLight(domLight *, Transform *)
Definition: DaeLoader.cpp:1324
Dae::Source * getSource(daeElement *source_el)
Definition: DaeLoader.cpp:385
If enabled, blend the incoming RGBA color values with the values in the color buffers, see also BlendFunc for more information.
std::map< daeElementRef, ref< Dae::NewParam > > mDaeNewParams
Definition: DaeLoader.hpp:119
vl::ETexParamWrap mWrapT
Definition: DaeHelpers.hpp:319
void setShininess(float shininess)
Definition: Shader.hpp:797
Vector3< T_Scalar > getY() const
Definition: Matrix4.hpp:126
An array of GLuint.
Definition: Array.hpp:437
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
ref< Dae::Node > mScene
Definition: DaeLoader.hpp:121
COLLADA node.
Definition: DaeHelpers.hpp:283
void setPosition(const fvec4 &position)
The position or direction of a light.
Definition: Light.hpp:77
void setSpecular(const fvec4 &color)
Definition: Shader.hpp:795
void parseEffects(daeElement *library)
Definition: DaeLoader.cpp:936
std::map< daeElementRef, ref< Dae::Mesh > > mMeshes
Definition: DaeLoader.hpp:115
std::vector< ref< Dae::Node > > mChildren
Definition: DaeHelpers.hpp:291
Wraps an OpenGL texture object representing and managing all the supported texture types...
Definition: Texture.hpp:178
void setSpecular(const fvec4 &specularcolor)
Definition: Light.hpp:68
void resize(size_t dim)
Definition: Array.hpp:233
void setNormalArray(ArrayAbstract *data)
Conventional normal array.
Definition: Geometry.cpp:164
See MultiDrawElements.
< Transparency is inverted if <authoring_tool> contains the string "Google" or reports ColladaMax or ...
Definition: ioDae.hpp:61
const LoadWriterDae::LoadOptions * loadOptions() const
Definition: DaeLoader.hpp:56
void setLinearAttenuation(float linearattenuation)
If the light is positional, rather than directional, its intensity is attenuated by the reciprocal of...
Definition: Light.hpp:95
COLLADA material.
Definition: DaeHelpers.hpp:396
void setDiffuse(const fvec4 &diffusecolor)
Definition: Light.hpp:65
std::vector< domPRef > mP
Definition: DaeHelpers.hpp:270
Matrix4 & invert(T_Scalar *determinant=NULL)
Definition: Matrix4.hpp:446
vl::ETexParamWrap mWrapS
Definition: DaeHelpers.hpp:318
Dae::ColorOrTexture mDiffuse
Definition: DaeHelpers.hpp:371
PolygonMode * gocPolygonMode()
Definition: Shader.cpp:111
VLCORE_EXPORT ref< Image > loadImage(VirtualFile *file)
Loads an image from the specified file.
Definition: Image.cpp:1214
COLLADA mesh.
Definition: DaeHelpers.hpp:276
ref< Geometry > mGeometry
Definition: DaeHelpers.hpp:272
const T_VectorType * begin() const
Definition: Array.hpp:245
void setSpotCutoff(float spotcutoff)
Valid values are from 0.0f to 90.0f plus the special value 180.0f (default) which disables the spot l...
Definition: Light.hpp:88
std::vector< ref< Dae::NewParam > > mNewParams
Definition: DaeHelpers.hpp:390
ref< Dae::Surface > mDaeSurface
Definition: DaeHelpers.hpp:328
ref< ResourceDatabase > mResources
Definition: DaeLoader.hpp:111
const String & path() const
Returns the path of the file.
Definition: VirtualFile.hpp:98
size_t size() const
Returns the number of elements of an array.
Definition: Array.hpp:235
The Geometry class is a Renderable that implements a polygonal mesh made of polygons, lines and points.
Definition: Geometry.hpp:66
Visualization Library main namespace.
static std::string percentDecode(const char *uri)
Definition: DaeLoader.cpp:859
Vector3< T_Scalar > getX() const
Definition: Matrix4.hpp:121
float dot(float a, float b)
Definition: glsl_math.hpp:1111
ref< Dae::Effect > mDaeEffect
Definition: DaeHelpers.hpp:398
T_Scalar * ptr()
Definition: Vector2.hpp:130
bool computeMissingNormals() const
Compute normals for those objects that don&#39;t have. Enabled by default.
Definition: ioDae.hpp:100
std::map< daeElementRef, ref< Dae::Source > > mSources
Definition: DaeLoader.hpp:117
void reset()
Definition: DaeLoader.cpp:91
void setDiffuse(const fvec4 &color)
Definition: Shader.hpp:794
COLLADA color or texture input.
Definition: DaeHelpers.hpp:333
void setRenderState(RenderStateNonIndexed *renderstate)
Definition: Shader.hpp:2172
COLLADA primitive.
Definition: DaeHelpers.hpp:257
void generateGeometry(Dae::Primitive *primitive, const char *name)
Definition: DaeLoader.cpp:1626
Dae::EPrimitiveType mType
Definition: DaeHelpers.hpp:266
Matrix4 & setZ(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:157
#define VL_TRAP()
Definition: checks.hpp:70
Dae::ColorOrTexture mEmission
Definition: DaeHelpers.hpp:369
bool mInvertTransparency
Definition: DaeLoader.hpp:125
void setEmission(const fvec4 &color)
Definition: Shader.hpp:796
void parseAsset(domElement *root)
Definition: DaeLoader.cpp:1872
std::map< daeElementRef, ref< Dae::Material > > mMaterials
Definition: DaeLoader.hpp:113
void setConstantAttenuation(float constantattenuation)
If the light is positional, rather than directional, its intensity is attenuated by the reciprocal of...
Definition: Light.hpp:107
ref< Dae::Sampler2D > mSampler
Definition: DaeHelpers.hpp:336
float max(float a, float b)
Definition: Vector2.hpp:312
See DrawElements.
VLGRAPHICS_EXPORT ref< Geometry > makeTorus(const vec3 &origin, real diameter=1, real thickness=0.2, int phi=10, int theta=10, float tex_coords=0.0f)
Creates torus. This function generates also appropriate normals.
COLLADA input stream.
Definition: DaeHelpers.hpp:241
void parseInputs(Dae::Primitive *dae_primitive, const domInputLocalOffset_Array &input_arr, const std::vector< ref< Dae::Input > > &vertex_inputs)
Definition: DaeLoader.cpp:99
ref< Dae::Mesh > parseGeometry(daeElement *geometry)
Definition: DaeLoader.cpp:149
T_Scalar length() const
Definition: Vector3.hpp:225
void prepareTexture2D(Dae::Sampler2D *sampler2D)
Definition: DaeLoader.cpp:1267
void setCountVector(const std::vector< GLsizei > &vcount)
Sets the vector defining the length of each primitive and automatically computes the pointer vectors ...
static const char * getSemanticString(Dae::EInputSemantic semantic)
Definition: DaeLoader.cpp:1537
void init(domFloat_arrayRef data_src, domUint count, domUint stride, domUint offset, size_t fields_mask)
Initializes an accessor. An accessor can read only up to 32 floats.
Definition: DaeHelpers.hpp:138
void computeNormals(bool verbose=false)
Computes the normals in a "smooth" way, i.e.
Definition: Geometry.cpp:269
LightModel * gocLightModel()
Definition: Shader.cpp:121
VLGRAPHICS_EXPORT ref< Geometry > makePyramid(const vec3 &origin, real side=1, real height=1)
Creates a pyramid.
void setQuadraticAttenuation(float quadraticattenuation)
If the light is positional, rather than directional, its intensity is attenuated by the reciprocal of...
Definition: Light.hpp:101
void transform(const mat4 &matr, bool normalize=true)
Transforms vertices and normals belonging to this geometry.
Definition: Geometry.cpp:399
Dae::EInputSemantic mSemantic
Definition: DaeHelpers.hpp:251
void parseMaterials(daeElement *library)
Definition: DaeLoader.cpp:1293
T * as()
Casts an Object to the specified class.
Definition: Object.hpp:282
std::vector< ref< Dae::Input > > mChannels
Definition: DaeHelpers.hpp:268
vl::ETexParamFilter mMinFilter
Definition: DaeHelpers.hpp:316
void setAmbient(const fvec4 &color)
Definition: Shader.hpp:793
DrawCall * mergeTriangleStrips()
Merges all the PT_TRIANGLE_STRIP DrawElementsUInt objects into one single PT_TRIANGLE_STRIP DrawEleme...
Definition: Geometry.cpp:430
#define NULL
Definition: OpenGLDefs.hpp:81
const mat4 & worldMatrix() const
Returns the world matrix used for rendering.
Definition: Transform.hpp:168
Matrix4 & setY(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:149
void setSpotExponent(float spotexponent)
Definition: Light.hpp:84
bool mAssumeOpaque
Definition: DaeLoader.hpp:126
void setupLights()
Definition: DaeLoader.cpp:1430
T_Scalar * ptr()
Definition: Vector3.hpp:87
void setSpotDirection(const fvec3 &spotdirection)
Definition: Light.hpp:81
An array of GLfloat.
Definition: Array.hpp:410
Shader * shader(int lodi=0, int pass=0)
Utility function, same as &#39;lod(lodi)->at(pass);&#39;.
Definition: Effect.hpp:178
Defines the sequence of Shader objects used to render an Actor.
Definition: Effect.hpp:91
std::vector< ref< Light > > mLights
Definition: DaeLoader.hpp:112
static Matrix4 & getRotation(Matrix4 &out, float degrees, float x, float y, float z)
Definition: Matrix4.hpp:909
std::vector< ref< Dae::Mesh > > mMesh
Definition: DaeHelpers.hpp:292
T_VectorType & at(size_t i)
Definition: Array.hpp:255
Effect * effect()
Returns the Effect bound to an Actor.
Definition: Actor.hpp:199
bool load(VirtualFile *file)
Definition: DaeLoader.cpp:726
void multiplyTransparency(float alpha)
Definition: Shader.cpp:365
const std::string & objectName() const
The name of the object, by default set to the object&#39;s class name.
Definition: Object.hpp:217
fvec3 vec3
Defined as: &#39;typedef fvec3 vec3&#39;. See also VL_PIPELINE_PRECISION.
Definition: Vector3.hpp:270
void mergeDrawCallsWithTriangles(EPrimitiveType primitive_type)
Merges all the draw calls that use the given primitive type or PT_TRIANGLES into one single PT_TRIANG...
Definition: Geometry.cpp:605
ref< Texture > mTexture
Definition: DaeHelpers.hpp:321
Dae::ColorOrTexture mTransparent
Definition: DaeHelpers.hpp:376
T_Scalar * ptr()
Definition: Vector4.hpp:99
ETexParamWrap
RenderStateSet * getRenderStateSet()
Definition: Shader.hpp:2235
static Matrix4 & getTranslation(Matrix4 &out, const Vector3< float > &v)
Definition: Matrix4.hpp:553
T_Scalar * ptr()
Definition: Matrix4.hpp:345
void bindTransform(Transform *transform)
If NULL follows the camera otherwise the given transformation node.
Definition: Light.cpp:115
const fvec4 & position() const
The position or direction of a light.
Definition: Light.hpp:79
void setValue(const fvec4 &color)
Definition: Shader.hpp:108
std::map< daeElementRef, ref< Image > > mImages
Definition: DaeLoader.hpp:118
bool fixBadNormals() const
Fix normals that are flipped compared to the polygon winding order. Enabled by default.
Definition: ioDae.hpp:106
static Matrix4 & getScaling(Matrix4 &out, const Vector3< float > &v)
Definition: Matrix4.hpp:589
ref< Transform > mTransform
Definition: DaeHelpers.hpp:290
Wraps the OpenGL function glLight().
Definition: Light.hpp:51
vl::ETexParamFilter mMagFilter
Definition: DaeHelpers.hpp:317
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
An array of vl::fvec3.
Definition: Array.hpp:414
COLLADA effect.
Definition: DaeHelpers.hpp:383
Dae::ColorOrTexture mAmbient
Definition: DaeHelpers.hpp:370
ref< Effect > setup_vl_Effect(Dae::Material *mat)
Definition: DaeLoader.cpp:431
void removeFromParent()
Erases a Transform from it&#39;s parent and sets the local matrix to be equal to the world matrix...
Definition: Transform.hpp:381
Vector3< T_Scalar > rgb() const
Definition: Vector4.hpp:133
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
void parseNode(daeElement *el, Dae::Node *parent)
Definition: DaeLoader.cpp:590
VLGRAPHICS_EXPORT ref< Geometry > makeUVSphere(const vec3 &origin, real diameter=1, int phi=20, int theta=20)
Creates a uv sphere.
COLLADA surface.
Definition: DaeHelpers.hpp:297
long long load(std::vector< char > &data)
Loads the entire file in the specified vector.
static ETexParamWrap translateWrapMode(domFx_sampler_wrap_common wrap)
Definition: DaeLoader.cpp:1562
Matrix4 as3x3() const
Definition: Matrix4.hpp:315
void setIndexBuffer(arr_type *index_buffer)
The BufferObject containing the indices used to render.
An array of vl::fvec2.
Definition: Array.hpp:412
void setTwoSide(bool twoside)
Definition: Shader.hpp:875
static Matrix4 getLookAt(const Vector3< float > &eye, const Vector3< float > &at, const Vector3< float > &up)
Definition: Matrix4.hpp:788
If enabled, normal vectors are scaled to unit length after transformation, see also vl::EN_RESCALE_NO...
std::vector< ref< Actor > > mActors
Definition: DaeHelpers.hpp:293
ref< Dae::Sampler2D > mDaeSampler2D
Definition: DaeHelpers.hpp:327
#define VL_CHECK(expr)
Definition: checks.hpp:73
void enable(EEnable capability)
Definition: Shader.hpp:2158
Dae::EOpaqueMode mOpaqueMode
Definition: DaeHelpers.hpp:367
void set(EPolygonMode frontface, EPolygonMode backface)
Definition: Shader.hpp:541
ref< Dae::Source > mSource
Definition: DaeHelpers.hpp:250
std::vector< ref< Dae::Node > > mNodes
Definition: DaeLoader.hpp:116
const ArrayAbstract * normalArray() const
Conventional normal array.
Definition: Geometry.hpp:254
std::map< daeElementRef, ref< Dae::Effect > > mEffects
Definition: DaeLoader.hpp:114
std::string mMaterial
Definition: DaeHelpers.hpp:267
ref< Effect > mDefaultFX
Definition: DaeLoader.hpp:120
const fvec4 & ambient() const
Definition: Light.hpp:63
The ResourceDatabase class contains and manipulates a set of resources.
COLLADA newparam.
Definition: DaeHelpers.hpp:325
void setAmbient(const fvec4 &ambientcolor)
Definition: Light.hpp:62
static ETexParamFilter translateSampleFilter(domFx_sampler_filter_common filter)
Definition: DaeLoader.cpp:1548
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102
COLLADA vertex.
Definition: DaeHelpers.hpp:98
const T_Scalar & w() const
Definition: Vector4.hpp:105
String mFilePath
Definition: DaeLoader.hpp:123
const T_Scalar & a() const
Definition: Vector4.hpp:115
void setEnableSet(EnableSet *es)
Definition: Shader.hpp:2275
If enabled, cull polygons based on their winding in window coordinates, see also CullFace.
void parseColor(const domProfile_COMMON *common, const T_color_or_texture &color_or_texture, Dae::ColorOrTexture *out_col)
Definition: DaeLoader.cpp:1575