Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/plugins/COLLADA/DaeLoader.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #include <vlGraphics/plugins/COLLADA/DaeLoader.hpp>
00033 #include <vlGraphics/GeometryPrimitives.hpp>
00034 
00035 using namespace vl;
00036 
00037 namespace
00038 {
00039   //-----------------------------------------------------------------------------
00040   const char* VL_NO_MATERIAL_SPECIFIED = "<VL_NO_MATERIAL_SPECIFIED>";
00041   const char* VL_DEFAULT_LIGHT = "<VL_DEFAULT_LIGHT>";
00042   //-----------------------------------------------------------------------------
00043   struct 
00044   {
00045     Dae::EInputSemantic mSemantic;
00046     const char* mSemanticString;
00047   } SemanticTable[] = 
00048     {
00049       { Dae::IS_UNKNOWN,         "UNKNOWN"         },
00050       { Dae::IS_BINORMAL,        "BINORMAL"        },
00051       { Dae::IS_COLOR,           "COLOR"           },
00052       { Dae::IS_CONTINUITY,      "CONTINUITY"      },
00053       { Dae::IS_IMAGE,           "IMAGE"           },
00054       { Dae::IS_INPUT,           "INPUT"           },
00055       { Dae::IS_IN_TANGENT,      "IN_TANGENT"      },
00056       { Dae::IS_INTERPOLATION,   "INTERPOLATION"   },
00057       { Dae::IS_INV_BIND_MATRIX, "INV_BIND_MATRIX" },
00058       { Dae::IS_JOINT,           "JOINT"           },
00059       { Dae::IS_LINEAR_STEPS,    "LINEAR_STEPS"    },
00060       { Dae::IS_MORPHS_TARGET,   "MORPHS_TARGET"   },
00061       { Dae::IS_MORPH_WEIGHT,    "MORPH_WEIGHT"    },
00062       { Dae::IS_NORMAL,          "NORMAL"          },
00063       { Dae::IS_OUTPUT,          "OUTPUT"          },
00064       { Dae::IS_OUT_TANGENT,     "OUT_TANGENT"     },
00065       { Dae::IS_POSITION,        "POSITION"        },
00066       { Dae::IS_TANGENT,         "TANGENT"         },
00067       { Dae::IS_TEXBINORMAL,     "TEXBINORMAL"     },
00068       { Dae::IS_TEXCOORD,        "TEXCOORD"        },
00069       { Dae::IS_TEXTANGENT,      "TEXTANGENT"      },
00070       { Dae::IS_UV,              "UV"              },
00071       { Dae::IS_VERTEX,          "VERTEX"          },
00072       { Dae::IS_WEIGHT,          "WEIGHT"          },
00073       { Dae::IS_UNKNOWN,          NULL             }
00074     };
00075 }
00076 //-----------------------------------------------------------------------------
00077 DaeLoader::DaeLoader()
00078 {
00079   reset();
00080 
00081   // default material
00082 
00083   mDefaultFX = new Effect;
00084   mDefaultFX->setObjectName( VL_NO_MATERIAL_SPECIFIED );
00085   mDefaultFX->shader()->enable(EN_LIGHTING);
00086   mDefaultFX->shader()->setRenderState( new Light, 0 );
00087   mDefaultFX->shader()->gocMaterial()->setFlatColor( vl::fuchsia );
00088   mDefaultFX->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
00089 }
00090 //-----------------------------------------------------------------------------
00091 void DaeLoader::reset()
00092 {
00093   mAssumeOpaque = false;
00094   mInvertTransparency = false;
00095   mScene = NULL;
00096   mResources = new ResourceDatabase;
00097 }
00098 //-----------------------------------------------------------------------------
00099 void DaeLoader::parseInputs(Dae::Primitive* dae_primitive, const domInputLocalOffset_Array& input_arr, const std::vector< ref<Dae::Input> >& vertex_inputs)
00100 {
00101   dae_primitive->mIndexStride = 0;
00102 
00103   for(size_t iinp=0; iinp<input_arr.getCount(); ++iinp)
00104   {
00105     domInputLocalOffsetRef input = input_arr.get(iinp);
00106 
00107     // copy over VERTEX inputs with the current offset and set
00108     if ( getSemantic(input->getSemantic()) ==  Dae::IS_VERTEX )
00109     {
00110       VL_CHECK(!vertex_inputs.empty())
00111       for(size_t ivert=0; ivert<vertex_inputs.size(); ++ivert)
00112       {
00113         ref<Dae::Input> dae_input = new Dae::Input;
00114         dae_input->mSemantic = vertex_inputs[ivert]->mSemantic;
00115         dae_input->mSource   = vertex_inputs[ivert]->mSource;
00116         dae_input->mOffset   = (size_t)input->getOffset();
00117         dae_input->mSet      = (size_t)input->getSet();
00118         dae_primitive->mChannels.push_back(dae_input);
00119 
00120         VL_CHECK(dae_input->mSource);
00121         VL_CHECK(dae_input->mSemantic != Dae::IS_UNKNOWN);
00122 
00123           
00124         dae_primitive->mIndexStride = std::max(dae_primitive->mIndexStride, dae_input->mOffset);
00125       }
00126     }
00127     else
00128     {
00129         ref<Dae::Input> dae_input = new Dae::Input;
00130         dae_input->mSemantic = getSemantic(input->getSemantic());
00131         dae_input->mSource   = getSource( input->getSource().getElement() );
00132         dae_input->mOffset   = (size_t)input->getOffset();
00133         dae_input->mSet      = (size_t)input->getSet();
00134 
00135         // if the source is NULL getSource() has already issued an error.
00136         if (dae_input->mSource)
00137           dae_primitive->mChannels.push_back( dae_input );
00138 
00139         VL_CHECK(dae_input->mSource);
00140         VL_CHECK(dae_input->mSemantic != Dae::IS_UNKNOWN);
00141 
00142         dae_primitive->mIndexStride = std::max(dae_primitive->mIndexStride, dae_input->mOffset);
00143     }
00144   }
00145     
00146   dae_primitive->mIndexStride += 1;
00147 }
00148 //-----------------------------------------------------------------------------
00149 ref<Dae::Mesh> DaeLoader::parseGeometry(daeElement* geometry)
00150 {
00151   // try to reuse the geometry in the library
00152   std::map< daeElementRef, ref<Dae::Mesh> >::iterator it = mMeshes.find( geometry );
00153   if (it != mMeshes.end())
00154     return it->second;
00155 
00156   if (!geometry->getChild("mesh"))
00157     return NULL;
00158 
00159   domMesh* mesh = static_cast<domMesh*>(geometry->getChild("mesh"));
00160 
00161   // add to dictionary
00162   ref<Dae::Mesh> dae_mesh = new Dae::Mesh;
00163   mMeshes[geometry] = dae_mesh;
00164 
00165   // vertices
00166   domVerticesRef vertices = mesh->getVertices();
00167   domInputLocal_Array input_array = vertices->getInput_array();
00168   for(size_t i=0; i<input_array.getCount(); ++i)
00169   {
00170     ref<Dae::Input> dae_input = new Dae::Input;
00171 
00172     dae_input->mSemantic = getSemantic(input_array[i]->getSemantic());
00173     if (dae_input->mSemantic == Dae::IS_UNKNOWN)
00174     {
00175       Log::error( Say("LoadWriterDae: the following semantic is unknown: %s\n") << input_array[i]->getSemantic() );
00176       continue;
00177     }
00178 
00179     dae_input->mSource = getSource( input_array[i]->getSource().getElement() );
00180     // if the source is NULL getSource() already issued an error.
00181     if (!dae_input->mSource)
00182       continue;
00183 
00184     dae_mesh->mVertexInputs.push_back(dae_input);
00185   }
00186 
00187   // --- --- ---- primitives ---- --- ---
00188 
00189   // NOTE: for the moment we generate one Geometry for each primitive but we should try to generate
00190   // one single set of vertex attribute array for each input semantic and recycle it if possible.
00191   // Unfortunately COLLADA makes this trivial task impossible to achieve.
00192 
00193   // --- ---- triangles ---- ---
00194   domTriangles_Array triangles_arr = mesh->getTriangles_array();
00195   for(size_t itri=0; itri< triangles_arr.getCount(); ++itri)
00196   {
00197     domTrianglesRef triangles = triangles_arr.get(itri);
00198 
00199     ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
00200     dae_mesh->mPrimitives.push_back(dae_primitive);
00201     dae_primitive->mType = Dae::PT_TRIANGLES;
00202     dae_primitive->mCount = (size_t)triangles->getCount();
00203 
00204     // --- input ---
00205     domInputLocalOffset_Array input_arr = triangles->getInput_array();
00206     parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
00207 
00208     // --- ---- p ---- ---
00209     dae_primitive->mP.push_back( triangles->getP() );
00210 
00211     // --- ---- material ---- ---
00212     dae_primitive->mMaterial = triangles->getMaterial() ? triangles->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
00213       
00214     // --- ---- generates the geometry ---- ---
00215     generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
00216   }
00217 
00218   // --- ---- triangles fan ---- ---
00219   domTrifans_Array trifan_arr = mesh->getTrifans_array();
00220   for(size_t itri=0; itri< trifan_arr.getCount(); ++itri)
00221   {
00222     domTrifansRef trifan = trifan_arr.get(itri);
00223 
00224     ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
00225     dae_mesh->mPrimitives.push_back(dae_primitive);
00226     dae_primitive->mType = Dae::PT_TRIFANS;
00227     dae_primitive->mCount = (size_t)trifan->getCount();
00228 
00229     // --- input ---
00230     domInputLocalOffset_Array input_arr = trifan->getInput_array();
00231     parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
00232 
00233     // --- ---- p ---- ---
00234     for(size_t ip=0; ip<trifan->getP_array().getCount(); ++ip)
00235       dae_primitive->mP.push_back( trifan->getP_array().get(ip) );
00236 
00237     // --- ---- material ---- ---
00238     dae_primitive->mMaterial = trifan->getMaterial() ? trifan->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
00239 
00240     // --- ---- generates the geometry ---- ---
00241     generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
00242   }
00243 
00244   // --- ---- triangle strip ---- ---
00245   domTristrips_Array tristrip_arr = mesh->getTristrips_array();
00246   for(size_t itri=0; itri< tristrip_arr.getCount(); ++itri)
00247   {
00248     domTristripsRef tristrip = tristrip_arr.get(itri);
00249 
00250     ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
00251     dae_mesh->mPrimitives.push_back(dae_primitive);
00252     dae_primitive->mType = Dae::PT_TRISTRIPS;
00253     dae_primitive->mCount = (size_t)tristrip->getCount();
00254 
00255     // --- input ---
00256     domInputLocalOffset_Array input_arr = tristrip->getInput_array();
00257     parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
00258 
00259     // --- ---- p ---- ---
00260     for(size_t ip=0; ip<tristrip->getP_array().getCount(); ++ip)
00261       dae_primitive->mP.push_back( tristrip->getP_array().get(ip) );
00262 
00263     // --- ---- material ---- ---
00264     dae_primitive->mMaterial = tristrip->getMaterial() ? tristrip->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
00265       
00266     // --- ---- generates the geometry ---- ---
00267     generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
00268   }
00269 
00270   // --- ---- polygons ---- ---
00271   domPolygons_Array polygon_arr = mesh->getPolygons_array();
00272   for(size_t itri=0; itri< polygon_arr.getCount(); ++itri)
00273   {
00274     domPolygonsRef polygon = polygon_arr.get(itri);
00275 
00276     ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
00277     dae_mesh->mPrimitives.push_back(dae_primitive);
00278     dae_primitive->mType = Dae::PT_POLYGONS;
00279     dae_primitive->mCount = (size_t)polygon->getCount();
00280 
00281     // --- input ---
00282     domInputLocalOffset_Array input_arr = polygon->getInput_array();
00283     parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
00284 
00285     // --- ---- p ---- ---
00286     for(size_t ip=0; ip<polygon->getP_array().getCount(); ++ip)
00287       dae_primitive->mP.push_back( polygon->getP_array().get(ip) );
00288 
00289     // --- ---- material ---- ---
00290     dae_primitive->mMaterial = polygon->getMaterial() ? polygon->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
00291       
00292     // --- ---- generates the geometry ---- ---
00293     generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
00294   }
00295 
00296   // --- ---- polylists ---- ---
00297   domPolylist_Array polylist_arr = mesh->getPolylist_array();
00298   for(size_t itri=0; itri< polylist_arr.getCount(); ++itri)
00299   {
00300     domPolylistRef polylist = polylist_arr.get(itri);
00301 
00302     ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
00303     dae_mesh->mPrimitives.push_back(dae_primitive);
00304     dae_primitive->mType = Dae::PT_POLYGONS;
00305     dae_primitive->mCount = (size_t)polylist->getVcount()->getValue().getCount();
00306 
00307     // --- input ---
00308     domInputLocalOffset_Array input_arr = polylist->getInput_array();
00309     parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
00310 
00311     // --- ---- p ---- ---
00312     size_t ip=0;
00313     for(size_t ivc=0; ivc<polylist->getVcount()->getValue().getCount(); ++ivc)
00314     {
00315       domPRef p = static_cast<domP*>(domP::create(mDAE).cast());
00316       VL_CHECK(p->typeID() == domP::ID());
00317       dae_primitive->mP.push_back( p );
00318       size_t vcount = (size_t)polylist->getVcount()->getValue()[ivc];
00319       p->getValue().setCount(vcount * dae_primitive->mIndexStride);
00320       for(size_t i=0; i<p->getValue().getCount(); ++i)
00321         p->getValue().set(i, polylist->getP()->getValue()[ip++]);
00322     }
00323 
00324     // --- ---- material ---- ---
00325     dae_primitive->mMaterial = polylist->getMaterial() ? polylist->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
00326       
00327     // --- ---- generates the geometry ---- ---
00328     generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
00329   }
00330 
00331   // --- ---- linestrips ---- ---
00332   domLinestrips_Array linestrip_arr = mesh->getLinestrips_array();
00333   for(size_t itri=0; itri< linestrip_arr.getCount(); ++itri)
00334   {
00335     domLinestripsRef linestrip = linestrip_arr.get(itri);
00336 
00337     ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
00338     dae_mesh->mPrimitives.push_back(dae_primitive);
00339     dae_primitive->mType = Dae::PT_LINE_STRIP;
00340     dae_primitive->mCount = (size_t)linestrip->getCount();
00341 
00342     // --- input ---
00343     domInputLocalOffset_Array input_arr = linestrip->getInput_array();
00344     parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
00345 
00346     // --- ---- p ---- ---
00347     for(size_t ip=0; ip<linestrip->getP_array().getCount(); ++ip)
00348       dae_primitive->mP.push_back( linestrip->getP_array().get(ip) );
00349 
00350     // --- ---- material ---- ---
00351     dae_primitive->mMaterial = linestrip->getMaterial() ? linestrip->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
00352       
00353     // --- ---- generates the geometry ---- ---
00354     generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
00355   }
00356 
00357   // --- ---- lines ---- ---
00358   domLines_Array line_arr = mesh->getLines_array();
00359   for(size_t itri=0; itri< line_arr.getCount(); ++itri)
00360   {
00361     domLinesRef line = line_arr.get(itri);
00362 
00363     ref<Dae::Primitive> dae_primitive = new Dae::Primitive;
00364     dae_mesh->mPrimitives.push_back(dae_primitive);
00365     dae_primitive->mType = Dae::PT_LINES;
00366     dae_primitive->mCount = (size_t)line->getCount();
00367 
00368     // --- input ---
00369     domInputLocalOffset_Array input_arr = line->getInput_array();
00370     parseInputs(dae_primitive.get(), input_arr, dae_mesh->mVertexInputs);
00371 
00372     // --- ---- p ---- ---
00373     dae_primitive->mP.push_back( line->getP() );
00374 
00375     // --- ---- material ---- ---
00376     dae_primitive->mMaterial = line->getMaterial() ? line->getMaterial() : VL_NO_MATERIAL_SPECIFIED;
00377       
00378     // --- ---- generates the geometry ---- ---
00379     generateGeometry( dae_primitive.get(), geometry->getAttribute("id").c_str() );
00380   }
00381 
00382   return dae_mesh;
00383 }
00384 //-----------------------------------------------------------------------------
00385 Dae::Source* DaeLoader::getSource(daeElement* source_el)
00386 {
00387   std::map< daeElementRef, ref<Dae::Source> >::iterator it = mSources.find(source_el);
00388   if (it != mSources.end())
00389     return it->second.get();
00390   else
00391   {
00392     VL_CHECK(source_el->typeID() == domSource::ID())
00393     domSourceRef source = static_cast<domSource*>(source_el);
00394 
00395     domSource::domTechnique_commonRef tech_common = source->getTechnique_common(); VL_CHECK(tech_common)
00396     domAccessorRef accessor = tech_common->getAccessor();
00397       
00398     size_t mask = 0;
00399     // we support up to 32 parameters for a single accessor
00400     domParam_Array param_array = accessor->getParam_array();
00401     size_t attr_count = param_array.getCount() <= 32 ? param_array.getCount() : 32;
00402     for(size_t ipar=0; ipar<attr_count; ++ipar)
00403     {
00404       if (param_array[ipar]->getName() && strlen(param_array[ipar]->getName()))
00405         mask |= 1<<ipar;
00406     }
00407 
00408     ref<Dae::Source> dae_source = new Dae::Source;
00409 
00410     if (source->getFloat_array())
00411       dae_source->init(source->getFloat_array(), accessor->getCount(), accessor->getStride(), accessor->getOffset(), mask);
00412     else
00413     if (source->getInt_array())
00414       dae_source->init(source->getInt_array(), accessor->getCount(), accessor->getStride(), accessor->getOffset(), mask);
00415     else
00416     if (source->getBool_array())
00417       dae_source->init(source->getBool_array(), accessor->getCount(), accessor->getStride(), accessor->getOffset(), mask);
00418     else
00419     {
00420       Log::error("LoadWriterDae: no supported source data found. Only Float_array, Int_array and Bool_array are supported as source data.\n");
00421       return NULL;
00422     }
00423 
00424     // add to source library for quick access later
00425     mSources[source] = dae_source;
00426 
00427     return dae_source.get();
00428   }
00429 }
00430 //-----------------------------------------------------------------------------
00431 ref<Effect> DaeLoader::setup_vl_Effect( Dae::Material* mat )
00432 {
00433   VL_CHECK(mat)
00434   VL_CHECK(mat->mDaeEffect)
00435   // VL_CHECK(mat->mDaeEffect->mDaeTechniqueCOMMON)
00436 
00437   ref<Effect> fx = new Effect;
00438   fx->shader()->enable(EN_DEPTH_TEST);
00439 
00440   // very basic material setup
00441   if (mat->mDaeEffect->mDaeTechniqueCOMMON)
00442   {
00443     Dae::TechniqueCOMMON* common_tech =mat->mDaeEffect->mDaeTechniqueCOMMON.get();
00444 
00445     // compute the actual tranparency
00446     float transparency = 0;
00447     if ( common_tech->mOpaqueMode == Dae::OM_A_ONE )
00448       transparency = common_tech->mTransparent.mColor.a() * common_tech->mTransparency;
00449     else
00450       transparency = (1.0f - dot( common_tech->mTransparent.mColor.rgb(), fvec3(0.2126f, 0.7152f, 0.0722f))) * common_tech->mTransparency;
00451 
00452     bool use_lighting = strstr(mat->mDaeEffect->objectName().c_str(), "blinn:") ||
00453                         strstr(mat->mDaeEffect->objectName().c_str(), "phong:") ||
00454                         strstr(mat->mDaeEffect->objectName().c_str(), "lambert:");
00455 
00456     // enable lighting only if required
00457     if ( use_lighting )
00458     {
00459       fx->shader()->enable(EN_LIGHTING);
00460 
00461       // mic fixme: most of .dae files I tested require this even if no double_sided flag is set.
00462       // fx->shader()->gocLightModel()->setTwoSide(true);
00463 
00464       // material sanity checks: these are needed only when using fixed function pipeline
00465       common_tech->mShininess = vl::clamp(common_tech->mShininess, 0.0f, 128.0f);
00466 
00467       // mic fixme: this vl::Effect can be put in mDaeTechniqueCOMMON and shared among all the materials that use it.
00468       fx->shader()->gocMaterial()->setDiffuse  ( common_tech->mDiffuse.mColor  ); // this is fuchsia by default
00469       fx->shader()->gocMaterial()->setAmbient  ( common_tech->mAmbient.mColor  );
00470       fx->shader()->gocMaterial()->setEmission ( common_tech->mEmission.mColor );
00471       fx->shader()->gocMaterial()->setSpecular ( common_tech->mSpecular.mColor );
00472       fx->shader()->gocMaterial()->setShininess( common_tech->mShininess );
00473 
00474       // if a texture is bound to the diffuse channel use it
00475       // mic fixme: for the moment we support only one texture, we also assume the texture coords #0 are the right ones...
00476       if ( common_tech->mDiffuse.mSampler && common_tech->mDiffuse.mSampler->mTexture )
00477       {
00478         fx->shader()->gocTextureSampler(0)->setTexture( common_tech->mDiffuse.mSampler->mTexture.get() );
00479         fx->shader()->gocMaterial()->setDiffuse( vl::white );
00480       }
00481 
00482       // alpha blending management
00483 
00484       // sets the alpha value of all material colors, front and back
00485       fx->shader()->gocMaterial()->multiplyTransparency( transparency );
00486     }
00487     else
00488     if ( strstr(mat->mDaeEffect->objectName().c_str(), "constant:") )
00489     {
00490 
00491       // constant can have only emission, check if there is a texture attached to it and use it
00492       // mic fixme: for the moment we support only one texture, we also assume the texture coords #0 are the right ones...
00493       if ( common_tech->mEmission.mSampler && common_tech->mEmission.mSampler->mTexture )
00494       {
00495         fx->shader()->gocTextureSampler(0)->setTexture( common_tech->mEmission.mSampler->mTexture.get() );
00496         // this is already the default: fx->shader()->gocColor()->setColor( vl::white );
00497       }
00498       else
00499         fx->shader()->gocColor()->setValue( common_tech->mEmission.mColor );
00500     }
00501 
00502     // enable alpha blending if material is transparent or alpha is coming from the diffuse texture
00503     // NOTE: to be pedantic with the specs we should enabled the alpha blending if common_tech->mBlendingOn == true however
00504     // applications and exporters have historically misused the <transparency> and <transparent> tags...
00505     if ( transparency < 1.0f || (common_tech->mTransparent.mSampler && common_tech->mTransparent.mSampler == common_tech->mDiffuse.mSampler) )
00506       if (!mAssumeOpaque)
00507         fx->shader()->enable(EN_BLEND);
00508 
00509     // to be correct we should do this but most models are not made to render correctly this way...
00510 #if 0
00511     if (!mat->mDaeEffect->mDoubleSided)
00512       fx->shader()->enable(EN_CULL_FACE); // no two sidelighting, yes culling
00513     else
00514     if (use_lighting)
00515       fx->shader()->gocLightModel()->setTwoSide(true); // yes two side lighting, no culling
00516 #endif
00517   }
00518   else
00519   {
00520     Log::error("LoadWriterDae: technique or profile not supported.\n");
00521     fx->shader()->gocMaterial()->setDiffuse( vl::fuchsia );
00522   }
00523 
00524   return fx;
00525 }
00526 //-----------------------------------------------------------------------------
00527 void DaeLoader::bindMaterials(Dae::Node* dae_node, Dae::Mesh* dae_mesh, domBind_materialRef bind_material)
00528 {
00529   // map symbols to actual materials
00530   std::map< std::string, Dae::Material* > material_map;
00531 
00532   if ( bind_material )
00533   {
00534     if (bind_material->getTechnique_common())
00535     {
00536       domInstance_material_Array& material_instances = bind_material->getTechnique_common()->getInstance_material_array();
00537       for(size_t i=0; i<material_instances.getCount(); ++i)
00538       {
00539         daeElement* material = material_instances[i]->getTarget().getElement();
00540         VL_CHECK(material)
00541         std::map< daeElementRef, ref<Dae::Material> >::iterator it = mMaterials.find( material );
00542         if (it != mMaterials.end())
00543         {
00544           // mic fixme: issue warning
00545           // VL_CHECK( material_map.find(material_instances[i]->getSymbol()) == material_map.end() )
00546           // VL_CHECK( material_instances[i]->getSymbol() )
00547           material_map[ material_instances[i]->getSymbol() ] = it->second.get();
00548         }
00549         else
00550         {
00551           VL_LOG_DEBUG << "- LoadWriterDae: material '" << material << "' not found!\n";
00552           continue;
00553         }
00554       }
00555     }
00556     else
00557     {
00558       VL_LOG_DEBUG << "- LoadWriterDae: technique_COMMON not found!\n";
00559     }
00560   }
00561 
00562   // now we need to instance the material
00563   for(size_t iprim=0; iprim<dae_mesh->mPrimitives.size(); ++iprim)
00564   {
00565     ref<Dae::Material> dae_material;
00566 
00567     if (!dae_mesh->mPrimitives[iprim]->mMaterial.empty())
00568     {
00569       std::map< std::string, Dae::Material* >::iterator it = material_map.find( dae_mesh->mPrimitives[iprim]->mMaterial );
00570       if (it != material_map.end())
00571       {
00572         dae_material = it->second;
00573       }
00574       else
00575       {
00576         if ( dae_mesh->mPrimitives[iprim]->mMaterial != VL_NO_MATERIAL_SPECIFIED)
00577         {
00578           VL_LOG_DEBUG << "- LoadWriterDae: material symbol " << dae_mesh->mPrimitives[iprim]->mMaterial << " could not be resolved.\n";
00579         }
00580       }
00581     }
00582 
00583     ref<Effect> fx = dae_material ? setup_vl_Effect(dae_material.get()) : mDefaultFX;
00584 
00585     ref<Actor> actor = new Actor( dae_mesh->mPrimitives[iprim]->mGeometry.get(), fx.get(), dae_node->mTransform.get() );
00586     dae_node->mActors.push_back( actor );
00587   }
00588 }
00589 //-----------------------------------------------------------------------------
00590 void DaeLoader::parseNode(daeElement* el, Dae::Node* parent)
00591 {
00592   if (el->typeID() == domNode::ID())
00593   {
00594     // --- --- --- parse this node --- --- ---
00595 
00596     // create new node and add it to the library
00597     ref<Dae::Node> this_node = new Dae::Node;
00598     mNodes.push_back(this_node);
00599     parent->mChildren.push_back( this_node );
00600     parent->mTransform->addChild( this_node->mTransform.get() );
00601 
00602     domNode* node = static_cast<domNode*>(el);
00603 
00604     // parse geometries
00605     domInstance_geometry_Array geometries = node->getInstance_geometry_array();
00606     for(size_t i=0; i<geometries.getCount(); ++i)
00607     {
00608       VL_CHECK(geometries[i]->getUrl().getElement()->typeID() == domGeometry::ID())
00609       daeElement* geometry = geometries[i]->getUrl().getElement();
00610       ref<Dae::Mesh> dae_mesh = parseGeometry(geometry);
00611       if (dae_mesh)
00612         this_node->mMesh.push_back(dae_mesh.get());
00613         
00614       // generate the Actors belonging to this node with their own material
00615       bindMaterials(this_node.get(), dae_mesh.get(), geometries[i]->getBind_material());
00616     }
00617 
00618     // parse controllers
00619     if (loadOptions()->extractSkins())
00620     {
00621       domInstance_controller_Array controllers = node->getInstance_controller_array();
00622       for(size_t i=0; i<controllers.getCount(); ++i)
00623       {
00624         VL_CHECK(controllers[i]->getUrl().getElement()->typeID() == domController::ID())
00625         daeElement* controller_el = controllers[i]->getUrl().getElement();
00626         VL_CHECK(controller_el)
00627         if (!controller_el)
00628           continue;
00629 
00630         domController* controller = static_cast<domController*>(controller_el);
00631         daeElement* geometry = controller->getSkin()->getSource().getElement();
00632         VL_CHECK(geometry)
00633         if (!geometry)
00634           continue;
00635 
00636         ref<Dae::Mesh> dae_mesh = parseGeometry(geometry);
00637         if (dae_mesh)
00638           this_node->mMesh.push_back(dae_mesh.get());
00639         
00640         // generate the Actors belonging to this node with their own material
00641         bindMaterials(this_node.get(), dae_mesh.get(), controllers[i]->getBind_material());
00642       }
00643     }
00644 
00645     // note: transforms are post-multiplied in the order in which they are specified (as if they were sub-nodes)
00646     for(size_t ichild=0; ichild<node->getChildren().getCount(); ++ichild)
00647     {
00648       daeElement* child = node->getChildren()[ichild];
00649       
00650       if ( 0 == strcmp(child->getElementName(), "matrix") )
00651       {
00652         domMatrix* matrix = static_cast<domMatrix*>(child);
00653         mat4 local_matrix;
00654         for(int i=0; i<16; ++i)
00655           local_matrix.ptr()[i] = (real)matrix->getValue().get(i);
00656         local_matrix.transpose();
00657         this_node->mTransform->postMultiply(local_matrix);
00658       }
00659       else
00660       if ( 0 == strcmp(child->getElementName(), "translate") )
00661       {
00662         domTranslate* tr = static_cast<domTranslate*>(child);
00663         mat4 m = mat4::getTranslation((real)tr->getValue()[0], (real)tr->getValue()[1], (real)tr->getValue()[2]);
00664         this_node->mTransform->postMultiply( m );
00665       }
00666       else
00667       if ( 0 == strcmp(child->getElementName(), "rotate") )
00668       {
00669         domRotate* rot = static_cast<domRotate*>(child);
00670         mat4 m = mat4::getRotation((real)rot->getValue()[3], (real)rot->getValue()[0], (real)rot->getValue()[1], (real)rot->getValue()[2]);
00671         this_node->mTransform->postMultiply( m );
00672       }
00673       else
00674       if ( 0 == strcmp(child->getElementName(), "scale") )
00675       {
00676         domScale* sc = static_cast<domScale*>(child);
00677         mat4 m = mat4::getScaling((real)sc->getValue()[0], (real)sc->getValue()[1], (real)sc->getValue()[2]);
00678         this_node->mTransform->postMultiply( m );
00679       }
00680       else
00681       if ( 0 == strcmp(child->getElementName(), "lookat") )
00682       {
00683         domLookat* lookat = static_cast<domLookat*>(child);
00684         vec3 eye ((real)lookat->getValue()[0], (real)lookat->getValue()[1], (real)lookat->getValue()[2]);
00685         vec3 look((real)lookat->getValue()[3], (real)lookat->getValue()[4], (real)lookat->getValue()[5]);
00686         vec3 up  ((real)lookat->getValue()[6], (real)lookat->getValue()[7], (real)lookat->getValue()[8]);
00687         this_node->mTransform->preMultiply( mat4::getLookAt(eye, look, up) );
00688       }
00689       else
00690       if ( 0 == strcmp(child->getElementName(), "skew") )
00691       {
00692         // mic fixme: support skew
00693         // domSkew* skew = static_cast<domSkew*>(child);
00694         Log::error("LoadWriterDae: <skew> transform not supported yet. Call me if you know how to compute it.\n");
00695       }
00696     }
00697 
00698     // parse lights
00699     domInstance_light_Array lights = node->getInstance_light_array();
00700     for(size_t i=0; i<lights.getCount(); ++i)
00701     {
00702       daeElementRef dae_light = lights[i]->getUrl().getElement();
00703       domLight* dom_light = dynamic_cast<domLight*>(dae_light.cast());
00704       ref<Light> light = parseLight(dom_light, this_node->mTransform.get());
00705       mLights.push_back( light );
00706     }
00707 
00708     // --- --- --- parse children --- --- ---
00709 
00710     // parse instance nodes
00711     domInstance_node_Array nodes = node->getInstance_node_array();
00712     for(size_t i=0; i<nodes.getCount(); ++i)
00713     {
00714       daeElement* node = nodes[i]->getUrl().getElement();
00715       VL_CHECK(node->typeID() == domNode::ID())
00716       parseNode(node, this_node.get());
00717     }
00718 
00719     // parse proper children
00720     daeTArray< daeSmartRef<daeElement> > children = node->getChildren();
00721     for(size_t i=0; i<children.getCount(); ++i)
00722       parseNode(children[i], this_node.get());
00723   }
00724 }
00725 //-----------------------------------------------------------------------------
00726 bool DaeLoader::load(VirtualFile* file)
00727 {
00728   reset();
00729 
00730   mFilePath = file->path();
00731 
00732   // load COLLADA file as a string.
00733   std::vector<char> buffer;
00734   file->load(buffer);
00735   if (buffer.empty())
00736     return false;
00737   buffer.push_back(0);
00738 
00739   daeElement* root = mDAE.openFromMemory(file->path().toStdString(), (char*)&buffer[0]);
00740   if (!root)
00741   {
00742     Log::error( "LoadWriterDae: failed to open COLLADA document.\n" );
00743     return false;
00744   }
00745 
00746   parseAsset(root);
00747 
00748   parseImages(root->getDescendant("library_images"));
00749 
00750   parseEffects(root->getDescendant("library_effects"));
00751 
00752   parseMaterials(root->getDescendant("library_materials"));
00753 
00754   daeElement* visual_scene = root->getDescendant("visual_scene");
00755   if (!visual_scene)
00756   {
00757     Log::error( "LoadWriterDae: <visual_scene> not found!\n" );
00758     return false;
00759   }
00760 
00761   // --- parse the visual scene ---
00762 
00763   mScene = new Dae::Node;
00764   daeTArray< daeSmartRef<daeElement> > children = visual_scene->getChildren();
00765   for(size_t i=0; i<children.getCount(); ++i)
00766     parseNode(children[i], mScene.get());
00767 
00768   // --- fill the resource database and final setup ---
00769 
00770   // --- transform setup ---
00771   // Up vector
00772   // Note that we don't touch the local space vertices and the intermediate matrices,
00773   // for proper reorientation of matrices and geometry the up-vector conditioner in
00774   // Refinery should do the job.
00775   mScene->mTransform->preMultiply( mUpMatrix );
00776   // Setup world matrices
00777   mScene->mTransform->computeWorldMatrixRecursive();
00778 
00779   // --- light setup ---
00780   // Computes position and direction of lights, sorts them (direction -> spot -> point), 
00781   // adds them to the resource database.
00782   setupLights();
00783 
00784   // return the Actors
00785   for( size_t inode=0; inode<mNodes.size(); ++inode )
00786   {
00787     for(size_t i=0; i<mNodes[inode]->mActors.size(); ++i)
00788     {
00789       Actor* actor = mNodes[inode]->mActors[i].get();
00790 
00791       // add actor to the resources
00792       mResources->resources().push_back( actor );
00793 
00794       // *** flatten transform hierarchy ***
00795       if ( loadOptions()->flattenTransformHierarchy() )
00796         actor->transform()->removeFromParent();
00797 
00798       // *** merge draw calls ***
00799       if (loadOptions()->mergeDrawCalls())
00800       {
00801         Geometry* geom = actor->lod(0)->as<Geometry>();
00802         if (geom)
00803         {
00804           // first merge all tristrips
00805           ref<DrawCall> tristrips = geom->mergeTriangleStrips();
00806           // keep it for later
00807           geom->drawCalls()->erase( tristrips.get() );
00808 
00809           // merge all non-tristrips
00810           geom->mergeDrawCallsWithTriangles(PT_UNKNOWN);
00811 
00812           // put back the tristrips
00813           if (tristrips.get())
00814             geom->drawCalls()->push_back( tristrips.get() );
00815         }
00816       }
00817 
00818       // *** check for transforms that require normal rescaling ***
00819       mat4 nmatrix = actor->transform()->worldMatrix().as3x3().invert().transpose();
00820       real len_x = nmatrix.getX().length();
00821       real len_y = nmatrix.getY().length();
00822       real len_z = nmatrix.getZ().length();
00823       if ( fabs(len_x - 1) > 0.05f || fabs(len_y - 1) > 0.05f || fabs(len_z - 1) > 0.05f )
00824       {
00825         // Log::warning("Detected mesh with scaled transform: enabled normal renormalization.\n");
00826         if ( actor->effect()->shader()->isEnabled(vl::EN_LIGHTING) )
00827           actor->effect()->shader()->enable(vl::EN_NORMALIZE); // or vl::EN_RESCALE_NORMAL
00828       }
00829 
00830       // *** light association & normal computation (only if lighting is on!) ***
00831       if ( actor->effect()->shader()->isEnabled(EN_LIGHTING) )
00832       {
00833         // *** light association ***
00834         // crete new effect/shader with it's own light set
00835         ref<Effect> fx = new Effect;
00836         fx->setObjectName( actor->effect()->objectName().c_str() );
00837         fx->shader()->setEnableSet( actor->effect()->shader()->getEnableSet() );
00838         fx->shader()->setRenderStateSet( actor->effect()->shader()->getRenderStateSet() );
00839         actor->setEffect( fx.get() );
00840         for(size_t ilight=0; ilight<mLights.size() && ilight<8; ++ilight)
00841           fx->shader()->setRenderState( mLights[ilight].get(), ilight );
00842 
00843        // *** compute missing normals ***
00844         Geometry* geom = actor->lod(0)->as<Geometry>();
00845        if ( loadOptions()->computeMissingNormals() && geom && !geom->normalArray() )
00846          geom->computeNormals();
00847       }
00848     }
00849   }
00850 
00851   if ( loadOptions()->flattenTransformHierarchy() )
00852     mScene->mTransform->flattenHierarchy();
00853   else
00854     mResources->resources().push_back( mScene->mTransform );
00855 
00856   return true;
00857 }
00858 //-----------------------------------------------------------------------------
00859 std::string DaeLoader::percentDecode(const char* uri)
00860 {
00861   std::string str;
00862   for(int i=0; uri[i]; ++i)
00863   {
00864     // process encoded character
00865     if ( uri[i] == '%' && uri[i+1] && uri[i+2] )
00866     {
00867       ++i;
00868       char hex1 = uri[i];
00869       if (hex1 >= '0' && hex1 <= '9')
00870         hex1 -= '0';
00871       else
00872       if (hex1 >= 'A' && hex1 <= 'F')
00873         hex1 -= 'A';
00874       else
00875       if (hex1 >= 'a' && hex1 <= 'f')
00876         hex1 -= 'a';
00877       else
00878         hex1 = -1;
00879 
00880       ++i;
00881       char hex2 = uri[i];
00882       if (hex2 >= '0' && hex2 <= '9')
00883         hex2 -= '0';
00884       else
00885       if (hex2 >= 'A' && hex2 <= 'F')
00886         hex2 -= 'A';
00887       else
00888       if (hex2 >= 'a' && hex2 <= 'f')
00889         hex2 -= 'a';
00890       else
00891         hex2 = -1;
00892 
00893       // encoding error
00894       if (hex1 == -1 || hex2 == -1)
00895       {
00896         // insert percent code as it is
00897         str.push_back('%');
00898         i -= 2;
00899       }
00900 
00901       char ch = (hex1 << 4) + (hex2);
00902       str.push_back(ch);
00903     }
00904     else
00905       str.push_back(uri[i]);
00906   }
00907   return str;
00908 }
00909 //-----------------------------------------------------------------------------
00910 void DaeLoader::loadImages(const domImage_Array& images)
00911 {
00912   for(size_t i=0; i<images.getCount(); ++i)
00913   {
00914     if ( strstr( images[i]->getInit_from()->getValue().getProtocol(), "file") == 0 )
00915     {
00916       Log::error( Say("LoadWriterDae: protocol not supported: %s\n") << images[i]->getInit_from()->getValue().getURI() );
00917       continue;
00918     }
00919 
00920     std::string full_path = percentDecode( images[i]->getInit_from()->getValue().getURI() + 6 );
00921     ref<Image> image = loadImage( full_path.c_str() );
00922       
00923     mImages[ images[i].cast() ] = image;
00924   }
00925 }
00926 //-----------------------------------------------------------------------------
00927 void DaeLoader::parseImages(daeElement* library)
00928 {
00929   if (!library)
00930     return;
00931   domLibrary_images* library_images = static_cast<domLibrary_images*>(library);
00932   const domImage_Array& images = library_images->getImage_array();
00933   loadImages(images);
00934 }
00935 //-----------------------------------------------------------------------------
00936 void DaeLoader::parseEffects(daeElement* library)
00937 {
00938   if (!library)
00939     return;
00940   domLibrary_effects* library_effects = static_cast<domLibrary_effects*>(library);
00941   const domEffect_Array& effects = library_effects->getEffect_array();
00942   for(size_t i=0; i<effects.getCount(); ++i)
00943   {
00944     domEffect* effect = effects[i].cast();
00945 
00946     ref<Dae::Effect> dae_effect = new Dae::Effect;
00947 
00948     std::string effect_name;
00949     if (effect->getName())
00950       effect_name = effect->getName();
00951 
00952     mEffects[effect] = dae_effect;
00953 
00954     // load images
00955     loadImages(effect->getImage_array());
00956 
00957     const domFx_profile_abstract_Array& profiles = effect->getFx_profile_abstract_array();
00958     for(size_t i=0; i<profiles.getCount(); ++i)
00959     {
00960       // <profile_COMMON>
00961       if ( profiles[i]->typeID() == domProfile_COMMON::ID() )
00962       {
00963         domProfile_COMMON* common = static_cast<domProfile_COMMON*>(profiles[i].cast());
00964 
00965         // --- parse <newparam> ---
00966         for(size_t ipar=0; ipar<common->getNewparam_array().getCount(); ++ipar)
00967         {
00968           domCommon_newparam_typeRef newparam = common->getNewparam_array()[ipar];
00969 
00970           ref<Dae::NewParam> dae_newparam = new Dae::NewParam;
00971           dae_effect->mNewParams.push_back( dae_newparam );
00972 
00973           // insert in the map se can resolve references to <sampler2D> and <surface>
00974           mDaeNewParams[newparam.cast()] = dae_newparam;
00975 
00976           // --- <surface> ---
00977           // mic fixme: for the moment we support only single image 2D surfaces
00978           if (newparam->getSurface())
00979           {
00980             domFx_surface_commonRef surface = newparam->getSurface();
00981 
00982             if ( !surface->getFx_surface_init_common()->getInit_from_array().getCount() )
00983             {
00984               VL_LOG_DEBUG << "- 'surface->getFx_surface_init_common()->getInit_from_array().getCount()' is 0: " << __FILE__ << ":" << __LINE__ << "\n";
00985               continue;
00986             }
00987 
00988             dae_newparam->mDaeSurface = new Dae::Surface;
00989             daeElement* ref_image = surface->getFx_surface_init_common()->getInit_from_array()[0]->getValue().getElement();
00990             if (!ref_image)
00991             {
00992               VL_LOG_DEBUG << "- 'surface->getFx_surface_init_common()->getInit_from_array()[0]->getValue().getElement()' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
00993               continue;
00994             }
00995 
00996             std::map< daeElementRef, ref<Image> >::iterator it = mImages.find( ref_image );
00997             if (it != mImages.end())
00998               dae_newparam->mDaeSurface->mImage = it->second.get();
00999             else
01000             {
01001               VL_LOG_DEBUG << "- 'mImages.find( ref_image )' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
01002               continue;
01003             }
01004           }
01005 
01006           // --- <sampler2D> ---
01007           if (newparam->getSampler2D())
01008           {
01009             domFx_sampler2D_commonRef sampler2D = newparam->getSampler2D();
01010               
01011             dae_newparam->mDaeSampler2D = new Dae::Sampler2D;
01012 
01013             // --- <source> ---
01014             daeSIDResolver sid_res( effect, sampler2D->getSource()->getValue() );
01015             domElement* surface_newparam = sid_res.getElement();
01016             if(!surface_newparam)
01017             {
01018               VL_LOG_DEBUG << (Say("- <surface> '%s' referenced by <sampler2D> '%s' not found!\n") << sampler2D->getSource()->getValue() << newparam->getSid() );
01019               continue;
01020             }
01021 
01022             std::map< daeElementRef, ref<Dae::NewParam> >::iterator it = mDaeNewParams.find(surface_newparam);
01023             if ( it != mDaeNewParams.end() )
01024             {
01025               dae_newparam->mDaeSampler2D->mDaeSurface = it->second->mDaeSurface;
01026             }
01027             else
01028             {
01029               VL_LOG_DEBUG << "- 'mDaeNewParams.find(surface_newparam)' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
01030               continue;
01031             }
01032               
01033             // --- <minfilter> ---
01034             if( sampler2D->getMinfilter() )
01035             {
01036               dae_newparam->mDaeSampler2D->mMinFilter = translateSampleFilter( sampler2D->getMinfilter()->getValue() );
01037             }
01038                 
01039 
01040             // --- <magfilter> ---
01041             if( sampler2D->getMagfilter() )
01042             {
01043               dae_newparam->mDaeSampler2D->mMagFilter = translateSampleFilter( sampler2D->getMagfilter()->getValue() );
01044             }
01045 
01046             // --- <wrap_s> ---
01047             if (sampler2D->getWrap_s())
01048             {
01049               dae_newparam->mDaeSampler2D->mWrapS = translateWrapMode( sampler2D->getWrap_s()->getValue() );
01050             }
01051 
01052             // --- <wrap_t> ---
01053             if (sampler2D->getWrap_t())
01054             {
01055               dae_newparam->mDaeSampler2D->mWrapT = translateWrapMode( sampler2D->getWrap_t()->getValue() );
01056             }
01057 
01058             // prepare vl::Texture for creation with the given parameters
01059             prepareTexture2D(dae_newparam->mDaeSampler2D.get());
01060           }
01061 
01062           // --- <float>, <float2>, <float3>, <floa4> ---
01063           if ( newparam->getFloat() )
01064           {
01065             dae_newparam->mFloat4 = fvec4((float)newparam->getFloat()->getValue(), 0, 0, 0);
01066           }
01067           else
01068           if ( newparam->getFloat2() )
01069           {
01070             daeDouble* fptr = &newparam->getFloat2()->getValue()[0];
01071             dae_newparam->mFloat4 = fvec4((float)fptr[0], (float)fptr[1], 0, 0);
01072           }
01073           else
01074           if ( newparam->getFloat3() )
01075           {
01076             daeDouble* fptr = &newparam->getFloat3()->getValue()[0];
01077             dae_newparam->mFloat4 = fvec4((float)fptr[0], (float)fptr[1], (float)fptr[2], 0);
01078           }
01079           else
01080           if ( newparam->getFloat4() )
01081           {
01082             daeDouble* fptr = &newparam->getFloat4()->getValue()[0];
01083             dae_newparam->mFloat4 = fvec4((float)fptr[0], (float)fptr[1], (float)fptr[2], (float)fptr[3]);
01084           }
01085         }
01086 
01087         // <technique sid="COMMON">
01088 
01089         // --- parse technique ---
01090         if (common->getTechnique()->getBlinn())
01091         {
01092           // track effect name
01093           effect_name = "blinn:"+effect_name;
01094 
01095           domProfile_COMMON::domTechnique::domBlinnRef blinn = common->getTechnique()->getBlinn();
01096 
01097           dae_effect->mDaeTechniqueCOMMON = new Dae::TechniqueCOMMON;
01098           parseColor( common, blinn->getEmission(), &dae_effect->mDaeTechniqueCOMMON->mEmission );
01099           parseColor( common, blinn->getAmbient(),  &dae_effect->mDaeTechniqueCOMMON->mAmbient );
01100           parseColor( common, blinn->getDiffuse(),  &dae_effect->mDaeTechniqueCOMMON->mDiffuse );
01101           parseColor( common, blinn->getSpecular(), &dae_effect->mDaeTechniqueCOMMON->mSpecular );
01102           if (blinn->getShininess())
01103             dae_effect->mDaeTechniqueCOMMON->mShininess = (float)blinn->getShininess()->getFloat()->getValue();
01104 
01105           parseColor( common, blinn->getReflective(), &dae_effect->mDaeTechniqueCOMMON->mReflective );
01106           if (blinn->getReflectivity())
01107             dae_effect->mDaeTechniqueCOMMON->mReflectivity = (float)blinn->getReflectivity()->getFloat()->getValue();
01108 
01109           if (blinn->getTransparent())
01110           {
01111             dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
01112             parseColor( common, blinn->getTransparent(), &dae_effect->mDaeTechniqueCOMMON->mTransparent );
01113             dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = blinn->getTransparent()->getOpaque() == FX_OPAQUE_ENUM_A_ONE ? Dae::OM_A_ONE : Dae::OM_RGB_ZERO;
01114           }
01115           if (blinn->getTransparency())
01116           {
01117             dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
01118             dae_effect->mDaeTechniqueCOMMON->mTransparency = (float)blinn->getTransparency()->getFloat()->getValue();
01119           }
01120         }
01121         else
01122         if (common->getTechnique()->getPhong())
01123         {
01124           // track effect name
01125           effect_name = "phong:"+effect_name;
01126 
01127           domProfile_COMMON::domTechnique::domPhongRef phong = common->getTechnique()->getPhong();
01128 
01129           dae_effect->mDaeTechniqueCOMMON = new Dae::TechniqueCOMMON;
01130           parseColor( common, phong->getEmission(), &dae_effect->mDaeTechniqueCOMMON->mEmission );
01131           parseColor( common, phong->getAmbient(),  &dae_effect->mDaeTechniqueCOMMON->mAmbient );
01132           parseColor( common, phong->getDiffuse(),  &dae_effect->mDaeTechniqueCOMMON->mDiffuse );
01133           parseColor( common, phong->getSpecular(), &dae_effect->mDaeTechniqueCOMMON->mSpecular );
01134           if (phong->getShininess())
01135           {
01136             dae_effect->mDaeTechniqueCOMMON->mShininess = (float)phong->getShininess()->getFloat()->getValue();
01137           }
01138 
01139           parseColor( common, phong->getReflective(), &dae_effect->mDaeTechniqueCOMMON->mReflective );
01140           if (phong->getReflectivity())
01141             dae_effect->mDaeTechniqueCOMMON->mReflectivity = (float)phong->getReflectivity()->getFloat()->getValue();
01142 
01143           if (phong->getTransparent())
01144           {
01145             dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
01146             parseColor( common, phong->getTransparent(), &dae_effect->mDaeTechniqueCOMMON->mTransparent );
01147             dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = phong->getTransparent()->getOpaque() == FX_OPAQUE_ENUM_A_ONE ? Dae::OM_A_ONE : Dae::OM_RGB_ZERO;
01148           }
01149           if (phong->getTransparency())
01150           {
01151             dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
01152             dae_effect->mDaeTechniqueCOMMON->mTransparency = (float)phong->getTransparency()->getFloat()->getValue();
01153           }
01154         }
01155         else
01156         if (common->getTechnique()->getLambert())
01157         {
01158           // track effect name
01159           effect_name = "lambert:"+effect_name;
01160 
01161           domProfile_COMMON::domTechnique::domLambertRef lambert = common->getTechnique()->getLambert();
01162 
01163           dae_effect->mDaeTechniqueCOMMON = new Dae::TechniqueCOMMON;
01164           parseColor( common, lambert->getEmission(), &dae_effect->mDaeTechniqueCOMMON->mEmission );
01165           parseColor( common, lambert->getAmbient(),  &dae_effect->mDaeTechniqueCOMMON->mAmbient );
01166           parseColor( common, lambert->getDiffuse(),  &dae_effect->mDaeTechniqueCOMMON->mDiffuse );
01167           dae_effect->mDaeTechniqueCOMMON->mSpecular.mColor = fvec4(0,0,0,1);
01168           dae_effect->mDaeTechniqueCOMMON->mShininess = 0;
01169 
01170           parseColor( common, lambert->getReflective(), &dae_effect->mDaeTechniqueCOMMON->mReflective );
01171           if (lambert->getReflectivity())
01172             dae_effect->mDaeTechniqueCOMMON->mReflectivity = (float)lambert->getReflectivity()->getFloat()->getValue();
01173 
01174           if (lambert->getTransparent())
01175           {
01176             dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
01177             parseColor( common, lambert->getTransparent(), &dae_effect->mDaeTechniqueCOMMON->mTransparent );
01178             dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = lambert->getTransparent()->getOpaque() == FX_OPAQUE_ENUM_A_ONE ? Dae::OM_A_ONE : Dae::OM_RGB_ZERO;
01179           }
01180           if (lambert->getTransparency())
01181           {
01182             dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
01183             dae_effect->mDaeTechniqueCOMMON->mTransparency = (float)lambert->getTransparency()->getFloat()->getValue();
01184           }
01185         }
01186         else
01187         if (common->getTechnique()->getConstant())
01188         {
01189           // track effect name
01190           effect_name = "constant:"+effect_name;
01191 
01192           domProfile_COMMON::domTechnique::domConstantRef constant = common->getTechnique()->getConstant();
01193 
01194           dae_effect->mDaeTechniqueCOMMON = new Dae::TechniqueCOMMON;
01195           parseColor( common, constant->getEmission(), &dae_effect->mDaeTechniqueCOMMON->mEmission );
01196           dae_effect->mDaeTechniqueCOMMON->mAmbient.mColor  = fvec4(0,0,0,1);
01197           dae_effect->mDaeTechniqueCOMMON->mDiffuse.mColor  = fvec4(0,0,0,1);
01198           dae_effect->mDaeTechniqueCOMMON->mSpecular.mColor = fvec4(0,0,0,1);
01199           dae_effect->mDaeTechniqueCOMMON->mShininess = 0;
01200 
01201           parseColor( common, constant->getReflective(), &dae_effect->mDaeTechniqueCOMMON->mReflective );
01202           if (constant->getReflectivity())
01203             dae_effect->mDaeTechniqueCOMMON->mReflectivity = (float)constant->getReflectivity()->getFloat()->getValue();
01204 
01205           if (constant->getTransparent())
01206           {
01207             dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
01208             parseColor( common, constant->getTransparent(), &dae_effect->mDaeTechniqueCOMMON->mTransparent );
01209             dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = constant->getTransparent()->getOpaque() == FX_OPAQUE_ENUM_A_ONE ? Dae::OM_A_ONE : Dae::OM_RGB_ZERO;
01210           }
01211           if (constant->getTransparency())
01212           {
01213             dae_effect->mDaeTechniqueCOMMON->mBlendingOn = true;
01214             dae_effect->mDaeTechniqueCOMMON->mTransparency = (float)constant->getTransparency()->getFloat()->getValue();
01215           }
01216         }
01217         else
01218         {
01219           Log::error("LoadWriterDae: technique not supported.\n");
01220         }
01221 
01222         dae_effect->setObjectName( effect_name.c_str() );
01223 
01224         // trasparency override options
01225         if (mAssumeOpaque)
01226         {
01227           dae_effect->mDaeTechniqueCOMMON->mTransparency = 1.0f;
01228           dae_effect->mDaeTechniqueCOMMON->mTransparent.mColor = fvec4(0, 0, 0, 1);
01229           dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = Dae::OM_A_ONE; // mic fixme: metti questo dentro Dae:: namespace
01230         }
01231         else
01232         if(mInvertTransparency)
01233         {
01234           dae_effect->mDaeTechniqueCOMMON->mTransparency = 1.0f - dae_effect->mDaeTechniqueCOMMON->mTransparency;
01235           // and don't trust <transparent> values...
01236           dae_effect->mDaeTechniqueCOMMON->mTransparent.mColor = fvec4(0, 0, 0, 1);
01237           dae_effect->mDaeTechniqueCOMMON->mOpaqueMode = Dae::OM_A_ONE;
01238         }
01239 
01240         // <extra>
01241 
01242         for(size_t iextra=0; iextra<common->getExtra_array().getCount(); ++iextra)
01243         {
01244           domExtraRef extra = common->getExtra_array()[iextra];
01245           for(size_t itech=0; itech<extra->getTechnique_array().getCount(); ++itech)
01246           {
01247             domTechniqueRef tech = extra->getTechnique_array()[itech];
01248             if ( strstr(tech->getProfile(), "GOOGLEEARTH") )
01249             {
01250               domAny* double_sided = (domAny*)tech->getChild("double_sided");
01251               if (double_sided)
01252               {
01253                 const char* ptr = double_sided->getValue();
01254                 if(strcmp(ptr, "1") == 0)
01255                   dae_effect->mDoubleSided = true;
01256               }
01257             }
01258           }
01259         }
01260 
01261       }
01262 
01263     }
01264   }
01265 }
01266 //-----------------------------------------------------------------------------
01267 void DaeLoader::prepareTexture2D(Dae::Sampler2D* sampler2D)
01268 {
01269   if (sampler2D->mDaeSurface && sampler2D->mDaeSurface->mImage)
01270   {
01271     bool use_mipmaps = true;
01272     switch(sampler2D->mMinFilter)
01273     {
01274     case TPF_LINEAR:
01275     case TPF_NEAREST:
01276       if ( loadOptions()->useAlwaysMipmapping() )
01277         sampler2D->mMinFilter = TPF_LINEAR_MIPMAP_NEAREST;
01278       else
01279         use_mipmaps = false;
01280     default:
01281       break;
01282     }
01283 
01284     sampler2D->mTexture = new Texture;
01285     sampler2D->mTexture->prepareTexture2D(sampler2D->mDaeSurface->mImage.get(), TF_UNKNOWN, use_mipmaps, false);
01286     sampler2D->mTexture->getTexParameter()->setWrapS(sampler2D->mWrapS);
01287     sampler2D->mTexture->getTexParameter()->setWrapT(sampler2D->mWrapT);
01288     sampler2D->mTexture->getTexParameter()->setMinFilter(sampler2D->mMinFilter);
01289     sampler2D->mTexture->getTexParameter()->setMagFilter(sampler2D->mMagFilter);
01290   }
01291 }
01292 //-----------------------------------------------------------------------------
01293 void DaeLoader::parseMaterials(daeElement* library)
01294 {
01295   if (!library)
01296     return;
01297   domLibrary_materials* library_materials = static_cast<domLibrary_materials*>(library);
01298   const domMaterial_Array& materials = library_materials->getMaterial_array();
01299   for(size_t i=0; i<materials.getCount(); ++i)
01300   {
01301     domElement* effect = materials[i]->getInstance_effect()->getUrl().getElement();
01302     if (!effect)
01303     {
01304       VL_LOG_DEBUG << "- 'materials[i]->getInstance_effect()->getUrl().getElement()' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
01305       continue;
01306     }
01307 
01308     std::map< daeElementRef, ref<Dae::Effect> >::iterator it = mEffects.find(effect);
01309     if (it != mEffects.end())
01310     {
01311       domMaterial* material = materials[i].cast();
01312       ref<Dae::Material> dae_material = new Dae::Material;
01313       dae_material->mDaeEffect = it->second;
01314       mMaterials[ material ] = dae_material;
01315     }
01316     else
01317     {
01318       VL_LOG_DEBUG << "- 'mEffects.find(effect)' FAILED: " << __FILE__ << ":" << __LINE__ << "\n";
01319       continue;
01320     }
01321   }
01322 }
01323 //-----------------------------------------------------------------------------
01324 ref<Light> DaeLoader::parseLight(domLight* dom_light, Transform* transform)
01325 {
01326   domLight::domTechnique_commonRef light_common = dom_light->getTechnique_common();
01327 
01328   ref<Light> light = new Light;
01329   if (dom_light->getName())
01330     light->setObjectName( dom_light->getName() );
01331   else
01332   if (dom_light->getID())
01333     light->setObjectName( dom_light->getID() );
01334 
01335   light->bindTransform(transform);
01336 
01337   if (light_common->getPoint())
01338   {
01339     domLight::domTechnique_common::domPointRef point = light_common->getPoint();
01340 
01341     if (point->getColor())
01342     {
01343       domFloat3& c = point->getColor()->getValue();
01344       fvec4 color((float)c[0], (float)c[1], (float)c[2], 1);
01345       light->setAmbient( fvec4(0,0,0,1) );
01346       light->setDiffuse(color);
01347       light->setSpecular(color);
01348     }
01349 
01350     if (point->getConstant_attenuation())
01351       light->setConstantAttenuation( (float)point->getConstant_attenuation()->getValue() );
01352     if (point->getLinear_attenuation())
01353       light->setLinearAttenuation( (float)point->getLinear_attenuation()->getValue() );
01354     if (point->getQuadratic_attenuation())
01355       light->setQuadraticAttenuation( (float)point->getQuadratic_attenuation()->getValue() );
01356 
01357     light->setPosition( fvec4(0,0,0,1) );
01358   }
01359   else
01360   if (light_common->getDirectional())
01361   {
01362     domLight::domTechnique_common::domDirectionalRef directional = light_common->getDirectional();
01363 
01364     if (directional->getColor())
01365     {
01366       domFloat3& c = directional->getColor()->getValue();
01367       fvec4 color((float)c[0], (float)c[1], (float)c[2], 1);
01368       light->setAmbient( fvec4(0,0,0,1) );
01369       light->setDiffuse(color);
01370       light->setSpecular(color);
01371     }
01372 
01373     light->setPosition( fvec4( 0, 0, 1, 0) );
01374   }
01375   else
01376   if (light_common->getSpot())
01377   {
01378     domLight::domTechnique_common::domSpotRef spot= light_common->getSpot();
01379 
01380     if (spot->getColor())
01381     {
01382       domFloat3& c = spot->getColor()->getValue();
01383       fvec4 color((float)c[0], (float)c[1], (float)c[2], 1);
01384       light->setAmbient( fvec4(0,0,0,1) );
01385       light->setDiffuse(color);
01386       light->setSpecular(color);
01387     }
01388 
01389     if (spot->getConstant_attenuation())
01390       light->setConstantAttenuation( (float)spot->getConstant_attenuation()->getValue() );
01391     if (spot->getLinear_attenuation())
01392       light->setLinearAttenuation( (float)spot->getLinear_attenuation()->getValue() );
01393     if (spot->getQuadratic_attenuation())
01394       light->setQuadraticAttenuation( (float)spot->getQuadratic_attenuation()->getValue() );
01395 
01396     if (spot->getFalloff_angle())
01397       light->setSpotCutoff( (float)spot->getFalloff_angle()->getValue() );
01398     if (spot->getFalloff_exponent())
01399       light->setSpotExponent( (float)spot->getFalloff_exponent()->getValue() );
01400 
01401     light->setSpotDirection( fvec3(0,0,-1) );
01402     light->setPosition( fvec4( 0, 0, 0, 1) );
01403   }
01404   else
01405   if (light_common->getAmbient())
01406   {
01407     domLight::domTechnique_common::domAmbientRef ambient = light_common->getAmbient();
01408 
01409     if (ambient->getColor())
01410     {
01411       domFloat3& c = ambient->getColor()->getValue();
01412       fvec4 color((float)c[0], (float)c[1], (float)c[2], 1);
01413       light->setAmbient( color );
01414       light->setDiffuse( fvec4(0,0,0,1) );
01415       light->setSpecular( fvec4(0,0,0,1) );
01416     }
01417 
01418     // this is actually irrelevant since the diffuse and specular colors are zeroed.
01419     light->setPosition( fvec4( 0, 0, 0, 1) );
01420 
01421     // just for clarity, no attenuation
01422     light->setConstantAttenuation( 1 );
01423     light->setLinearAttenuation( 0 );
01424     light->setQuadraticAttenuation( 0 );
01425   }
01426 
01427   return light;
01428 }
01429 //-----------------------------------------------------------------------------
01430 void DaeLoader::setupLights()
01431 {
01432   // generate light meshes
01433   if (loadOptions()->lightMeshSize())
01434   {
01435     for(size_t i=0; i<mLights.size(); ++i)
01436     {
01437       // spot light
01438       if (mLights[i]->spotCutoff() != 180)
01439       {
01440         ref<Geometry> light_mesh = vl::makeCone( vec3(0,0,0), loadOptions()->lightMeshSize(), loadOptions()->lightMeshSize(), 10 );
01441         light_mesh->transform( mat4::getTranslation(0,loadOptions()->lightMeshSize(),0) );
01442         light_mesh->transform( mat4::getRotation(90, +1,0,0) );
01443         light_mesh->setObjectName( ("LightMesh-" + mLights[i]->objectName()).c_str() );
01444         ref<Effect> fx = new Effect;
01445         fx->shader()->enable(EN_DEPTH_TEST);
01446         fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
01447         fx->shader()->gocColor()->setValue(vl::fuchsia);
01448         mResources->resources().push_back( new Actor( light_mesh.get(), fx.get(), mLights[i]->boundTransform() ) );
01449       }
01450       else
01451       // directional light
01452       if (mLights[i]->position().w() == 0)
01453       {
01454         ref<Geometry> light_mesh = vl::makePyramid( vec3(0,0,0), loadOptions()->lightMeshSize() / 2, loadOptions()->lightMeshSize() );
01455         light_mesh->transform( mat4::getRotation(90, -1,0,0) );
01456         light_mesh->setObjectName( ("LightMesh-" + mLights[i]->objectName()).c_str() );
01457         ref<Effect> fx = new Effect;
01458         fx->shader()->enable(EN_DEPTH_TEST);
01459         fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
01460         fx->shader()->gocColor()->setValue(vl::fuchsia);
01461         mResources->resources().push_back( new Actor( light_mesh.get(), fx.get(), mLights[i]->boundTransform() ) );
01462       }
01463       else
01464       // point light
01465       if( mLights[i]->ambient() == fvec4(0,0,0,1) )
01466       {
01467         ref<Geometry> light_mesh = vl::makeUVSphere( vec3(0,0,0), loadOptions()->lightMeshSize(), 10, 5);
01468         light_mesh->setObjectName( ("LightMesh-" + mLights[i]->objectName()).c_str() );
01469         ref<Effect> fx = new Effect;
01470         fx->shader()->enable(EN_DEPTH_TEST);
01471         fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
01472         fx->shader()->gocColor()->setValue(vl::fuchsia);
01473         mResources->resources().push_back( new Actor( light_mesh.get(), fx.get(), mLights[i]->boundTransform() ) );
01474       }
01475       else
01476       // ambient light
01477       {
01478         ref<Geometry> light_mesh = vl::makeTorus( vec3(0,0,0), loadOptions()->lightMeshSize(), loadOptions()->lightMeshSize()/4, 8, 14);
01479         light_mesh->setNormalArray(NULL); // remove normals
01480         light_mesh->setObjectName( ("LightMesh-" + mLights[i]->objectName()).c_str() );
01481         ref<Effect> fx = new Effect;
01482         fx->shader()->enable(EN_DEPTH_TEST);
01483         fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
01484         fx->shader()->gocColor()->setValue(vl::fuchsia);
01485         mResources->resources().push_back( new Actor( light_mesh.get(), fx.get(), mLights[i]->boundTransform() ) );
01486       }
01487     }
01488   }
01489 
01490   struct dummy
01491   {
01492     static bool light_sorter(const ref<Light>& a, const ref<Light>& b)
01493     {
01494       // ambient lights first
01495       if (a->ambient() != b->ambient())
01496         return b->ambient() < a->ambient();
01497       else
01498       // directional lights first
01499       if (a->position().w() != b->position().w())
01500         return a->position().w() < b->position().w();
01501       else
01502       // point lights first, spotlights last
01503         return a->spotCutoff() > b->spotCutoff();
01504     }
01505   };
01506 
01507   std::sort(mLights.begin(), mLights.end(), dummy::light_sorter);
01508 
01509   // set light indices and adds to the resource database
01510   for(size_t i=0; i<mLights.size(); ++i)
01511   {
01512     mResources->resources().push_back( mLights[i].get() );
01513   }
01514 
01515   if (loadOptions()->exportLights() == false)
01516     mLights.clear();
01517 
01518   // default light if no lights were present in the scene or exportLights() == false
01519   if (mLights.empty())
01520   {
01521     mLights.push_back( new Light );
01522     mLights[0]->setObjectName(VL_DEFAULT_LIGHT);
01523   }
01524 }
01525 //-----------------------------------------------------------------------------
01526 Dae::EInputSemantic DaeLoader::getSemantic(const char* semantic)
01527 {
01528   for(int i=0; SemanticTable[i].mSemanticString; ++i)
01529   {
01530     if (strcmp(semantic, SemanticTable[i].mSemanticString) == 0)
01531       return SemanticTable[i].mSemantic;
01532   }
01533 
01534   return Dae::IS_UNKNOWN;
01535 }
01536 //-----------------------------------------------------------------------------
01537 const char* DaeLoader::getSemanticString(Dae::EInputSemantic semantic)
01538 {
01539   for(int i=0; SemanticTable[i].mSemanticString; ++i)
01540   {
01541     if ( semantic == SemanticTable[i].mSemantic )
01542       return SemanticTable[i].mSemanticString;
01543   }
01544 
01545   return NULL;
01546 }
01547 //-----------------------------------------------------------------------------
01548 ETexParamFilter DaeLoader::translateSampleFilter(domFx_sampler_filter_common filter)
01549 {
01550   switch(filter)
01551   {
01552       case FX_SAMPLER_FILTER_COMMON_NEAREST:                return TPF_NEAREST;
01553       case FX_SAMPLER_FILTER_COMMON_LINEAR:                 return TPF_LINEAR;
01554       case FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_NEAREST: return TPF_NEAREST_MIPMAP_NEAREST;
01555       case FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_NEAREST:  return TPF_LINEAR_MIPMAP_NEAREST;
01556       case FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_LINEAR:  return TPF_NEAREST_MIPMAP_LINEAR;
01557       case FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_LINEAR:   return TPF_LINEAR_MIPMAP_LINEAR;
01558       default:                                              return (ETexParamFilter)0;
01559   }
01560 }
01561 //-----------------------------------------------------------------------------
01562 ETexParamWrap DaeLoader::translateWrapMode(domFx_sampler_wrap_common wrap)
01563 {
01564   switch(wrap)
01565   {
01566       case FX_SAMPLER_WRAP_COMMON_WRAP:   return TPW_REPEAT;
01567       case FX_SAMPLER_WRAP_COMMON_MIRROR: return TPW_MIRRORED_REPEAT;
01568       case FX_SAMPLER_WRAP_COMMON_CLAMP:  return TPW_CLAMP;
01569       case FX_SAMPLER_WRAP_COMMON_BORDER: return TPW_CLAMP_TO_BORDER;
01570       default:                            return (ETexParamWrap)0;
01571   }
01572 }
01573 //-----------------------------------------------------------------------------
01574 template<class T_color_or_texture>
01575 void DaeLoader::parseColor(const domProfile_COMMON* common, const T_color_or_texture& color_or_texture, Dae::ColorOrTexture* out_col)
01576 {
01577   if (!color_or_texture)
01578     return;
01579 
01580   if (color_or_texture->getColor())
01581   {
01582     domFx_color_common& col = color_or_texture->getColor()->getValue();
01583     out_col->mColor = fvec4( (float)col[0], (float)col[1], (float)col[2], (float)col[3] );
01584   }
01585 
01586   if (color_or_texture->getTexture())
01587   {
01588     // <texture texture="...">
01589     daeSIDResolver sid_res( const_cast<domProfile_COMMON*>(common), color_or_texture->getTexture()->getTexture() );
01590     domElement* sampler2D_newparam = sid_res.getElement();
01591 
01592     std::map< daeElementRef, ref<Dae::NewParam> >::iterator it = mDaeNewParams.find(sampler2D_newparam);
01593     if ( it != mDaeNewParams.end() )
01594     {
01595       VL_CHECK(it->second->mDaeSampler2D)
01596       out_col->mSampler = it->second->mDaeSampler2D;
01597       if ( it->second->mDaeSampler2D.get() == NULL)
01598       {
01599         VL_LOG_DEBUG << "- LoadWriterDae: malformed file: <texture texture=..> points to a <newparam> that does not contain <sampler2D>!\n";
01600       }
01601     }
01602     else
01603     {
01604       std::map< daeElementRef, ref<Image> >::iterator it = mImages.find(sampler2D_newparam);
01605       if ( it != mImages.end() )
01606       {
01607         // create dummy sampler
01608         out_col->mSampler = new Dae::Sampler2D;
01609         out_col->mSampler->mDaeSurface = new Dae::Surface;
01610         out_col->mSampler->mDaeSurface->mImage = it->second;
01611         prepareTexture2D( out_col->mSampler.get() );
01612         VL_LOG_DEBUG << "- LoadWriterDae: malformed file: <texture texture=..> parameter points to an <image> instead of a <sampler2D>!\n"
01613                           "VL will create a dummy sampler with the specified image.\n";
01614       }
01615       else
01616       {
01617         VL_LOG_DEBUG << "- LoadWriterDae: malformed file: <texture texture=..> could not be resolved to anything!\n";
01618       }
01619     }
01620 
01621     // <texture texcoord="...">
01622     out_col->mTexCoord = color_or_texture->getTexture()->getTexcoord();
01623   }
01624 }
01625 //-----------------------------------------------------------------------------
01626 void DaeLoader::generateGeometry(Dae::Primitive* prim, const char* name)
01627 {
01628   VL_CHECK(prim->mIndexStride);
01629 
01630   prim->mGeometry = new Geometry;
01631   if (name)
01632     prim->mGeometry->setObjectName(name);
01633 
01634   // no primitives where specified so we treat it as a cloud of points simulating a single increasing <p>
01635   if(prim->mP.size() == 0 && prim->mType == Dae::PT_UNKNOWN && prim->mChannels.size())
01636   {
01637     // some sanity checks
01638     for(size_t i=0; i<prim->mChannels.size(); ++i)
01639     {
01640       if ( prim->mChannels[i]->mSource->count() != prim->mChannels[0]->mSource->count() )
01641       {
01642         VL_LOG_DEBUG << "- LoadWriterDae: cannot generate point cloud: channels have different sizes!\n";
01643         return;
01644       }
01645       if ( prim->mChannels[i]->mOffset != 0 )
01646       {
01647         VL_LOG_DEBUG << "- LoadWriterDae: cannot generate point cloud: channels must have offset == 0!\n";
01648         return;
01649       }
01650     }
01651 
01652     // generate dummy <p>
01653     prim->mP.resize(1);
01654     prim->mP[0] = static_cast<domP*>(domP::create(mDAE).cast());
01655     prim->mP[0]->getValue().setCount( prim->mChannels[0]->mSource->count() );
01656     for (size_t i=0; i<prim->mChannels[0]->mSource->count(); ++i)
01657       prim->mP[0]->getValue()[i] = i;
01658   }
01659 
01660   size_t total_index_count = 0;
01661   for(size_t ip=0; ip<prim->mP.size(); ++ip)
01662     total_index_count += prim->mP[ip]->getValue().getCount();
01663 
01664   ref<ArrayUInt1> index_buffer = new ArrayUInt1;
01665   index_buffer->resize( total_index_count / prim->mIndexStride );
01666 
01667   std::vector<GLint> vcount;
01668 
01669   // generate index buffer for DrawElements or MultiDrawElements.
01670   std::set<Dae::Vert> vert_set;
01671   for(size_t ip=0, iidx=0; ip<prim->mP.size(); ++ip)
01672   {
01673     const domListOfUInts& p = prim->mP[ip]->getValue();
01674 
01675     vcount.push_back( p.getCount() / prim->mIndexStride );
01676 
01677     for(size_t ivert=0; ivert<p.getCount(); ivert+=prim->mIndexStride, ++iidx)
01678     {
01679       Dae::Vert vert;
01680 
01681       // fill vertex info
01682       for(size_t ichannel=0; ichannel<prim->mChannels.size(); ++ichannel)
01683         vert.mAttribIndex[ichannel] = (size_t)p[ivert + prim->mChannels[ichannel]->mOffset];
01684 
01685       size_t final_index = 0xFFFFFFFF;
01686       // retrieve/insert the vertex
01687       std::set<Dae::Vert>::iterator it = vert_set.find(vert);
01688       if (it == vert_set.end())
01689       {
01690         vert.mIndex = final_index = vert_set.size();
01691         vert_set.insert(vert);
01692       }
01693       else
01694         final_index = it->mIndex;
01695         
01696       // this is the actual index
01697       (*index_buffer)[iidx] = final_index;
01698     }
01699   }
01700 
01701   if (vcount.size() == 1)
01702   {
01703     // use DrawElements
01704     ref<DrawElementsUInt> de;
01705     switch(prim->mType)
01706     {
01707       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
01708       case Dae::PT_LINES:      de = new DrawElementsUInt( PT_LINES ); break;
01709       case Dae::PT_LINE_STRIP: de = new DrawElementsUInt( PT_LINE_STRIP ); break;
01710       case Dae::PT_POLYGONS:   de = new DrawElementsUInt( PT_POLYGON ); break;
01711       case Dae::PT_TRIFANS:    de = new DrawElementsUInt( PT_TRIANGLE_FAN ); break;
01712       case Dae::PT_TRIANGLES:  de = new DrawElementsUInt( PT_TRIANGLES ); break;
01713       case Dae::PT_TRISTRIPS:  de = new DrawElementsUInt( PT_TRIANGLE_STRIP ); break;
01714       default:
01715         VL_TRAP()
01716     }
01717 
01718     de->setIndexBuffer( index_buffer.get() );
01719     prim->mGeometry->drawCalls()->push_back( de.get() );
01720   }
01721   else
01722   {
01723     // use MultiDrawElements
01724     ref<MultiDrawElementsUInt> mde;
01725     switch(prim->mType)
01726     {
01727       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
01728       case Dae::PT_LINES:      mde = new MultiDrawElementsUInt( PT_LINES ); break;
01729       case Dae::PT_LINE_STRIP: mde = new MultiDrawElementsUInt( PT_LINE_STRIP ); break;
01730       case Dae::PT_POLYGONS:   mde = new MultiDrawElementsUInt( PT_POLYGON ); break;
01731       case Dae::PT_TRIFANS:    mde = new MultiDrawElementsUInt( PT_TRIANGLE_FAN ); break;
01732       case Dae::PT_TRIANGLES:  mde = new MultiDrawElementsUInt( PT_TRIANGLES ); break;
01733       case Dae::PT_TRISTRIPS:  mde = new MultiDrawElementsUInt( PT_TRIANGLE_STRIP ); break;
01734       default:
01735         VL_TRAP()
01736     }
01737 
01738     mde->setIndexBuffer( index_buffer.get() );
01739     mde->setCountVector( vcount );
01740     prim->mGeometry->drawCalls()->push_back( mde.get() );
01741   }
01742 
01743   // generate new vertex attrib info and install data
01744   size_t tex_unit = 0;
01745   for( size_t ich=0; ich<prim->mChannels.size(); ++ich )
01746   {
01747     // init data storage for this channel
01748     ref<ArrayAbstract> vert_attrib;
01749     float* ptr = NULL;
01750     float* ptr_end = NULL;
01751     switch(prim->mChannels[ich]->mSource->dataSize())
01752     {
01753       case 1:
01754       {
01755         ref<ArrayFloat1> array_f1 = new ArrayFloat1;
01756         vert_attrib = array_f1;
01757         array_f1->resize( vert_set.size() );
01758         ptr = array_f1->begin();
01759         // debug
01760         ptr_end = ptr + vert_set.size() * 1;
01761         break;
01762       }
01763       case 2:
01764       {
01765         ref<ArrayFloat2> array_f2 = new ArrayFloat2;
01766         vert_attrib = array_f2;
01767         array_f2->resize( vert_set.size() );
01768         ptr = array_f2->at(0).ptr();
01769         // debug
01770         ptr_end = ptr + vert_set.size() * 2;
01771         break;
01772       }
01773       case 3:
01774       {
01775         ref<ArrayFloat3> array_f3 = new ArrayFloat3;
01776         vert_attrib = array_f3;
01777         array_f3->resize( vert_set.size() );
01778         ptr = array_f3->at(0).ptr();
01779         // debug
01780         ptr_end = ptr + vert_set.size() * 3;
01781         break;
01782       }
01783       case 4:
01784       {
01785         ref<ArrayFloat4> array_f4 = new ArrayFloat4;
01786         vert_attrib = array_f4;
01787         array_f4->resize( vert_set.size() );
01788         ptr = array_f4->at(0).ptr();
01789         // debug
01790         ptr_end = ptr + vert_set.size() * 4;
01791         break;
01792       }
01793       default:
01794         Log::warning( Say("LoadWriterDae: input '%s' skipped because parameter count is more than 4.\n") << getSemanticString(prim->mChannels[ich]->mSemantic) );
01795         continue;
01796     }
01797 
01798     // install vertex attribute
01799     switch(prim->mChannels[ich]->mSemantic)
01800     {
01801     case Dae::IS_POSITION: prim->mGeometry->setVertexArray( vert_attrib.get() ); break;
01802     case Dae::IS_NORMAL:   prim->mGeometry->setNormalArray( vert_attrib.get() ); break;
01803     case Dae::IS_COLOR:    prim->mGeometry->setColorArray( vert_attrib.get() ); break;
01804     case Dae::IS_TEXCOORD: prim->mGeometry->setTexCoordArray( tex_unit++, vert_attrib.get() ); break;
01805     default:
01806       VL_LOG_DEBUG << ( Say("- LoadWriterDae: input semantic '%s' not supported.\n") << getSemanticString(prim->mChannels[ich]->mSemantic) );
01807       continue;
01808     }
01809 
01810     // name it as TEXCOORD@SET0 etc. to be recognized when binding (not used yet)
01811     vert_attrib->setObjectName( String(Say("%s@SET%n") << getSemanticString(prim->mChannels[ich]->mSemantic) << prim->mChannels[ich]->mSet).toStdString().c_str() );
01812 
01813     // fill the vertex attribute array
01814     for(std::set<Dae::Vert>::iterator it = vert_set.begin(); it != vert_set.end(); ++it)
01815     {
01816       const Dae::Vert& vert = *it;
01817       size_t idx = vert.mAttribIndex[ich];
01818       VL_CHECK(ptr + prim->mChannels[ich]->mSource->dataSize()*vert.mIndex < ptr_end);
01819       prim->mChannels[ich]->mSource->readData(idx, ptr +prim-> mChannels[ich]->mSource->dataSize()*vert.mIndex);
01820     }
01821   }
01822 
01823   // --- fix bad normals ---
01824   if ( loadOptions()->fixBadNormals() && prim->mGeometry->normalArray() )
01825   {
01826     ref<ArrayFloat3> norm_old = vl::cast<ArrayFloat3>(prim->mGeometry->normalArray());
01827     VL_CHECK(norm_old);
01828 
01829     // recompute normals
01830     prim->mGeometry->computeNormals();
01831     ref<ArrayFloat3> norm_new = vl::cast<ArrayFloat3>(prim->mGeometry->normalArray());
01832     VL_CHECK(norm_new);
01833 
01834     size_t flipped = 0;
01835     size_t degenerate = 0;
01836     for(size_t i=0; i<norm_new->size(); ++i)
01837     {
01838       // compare VL normals with original ones
01839       float l = norm_old->at(i).length();
01840       if ( l < 0.5f ) 
01841       {
01842         norm_old->at(i) = norm_new->at(i);
01843         ++degenerate;
01844       }
01845 
01846       if ( l < 0.9f || l > 1.1f ) 
01847       {
01848         norm_old->at(i).normalize();
01849         ++degenerate;
01850       }
01851 
01852       if ( dot(norm_new->at(i), norm_old->at(i)) < -0.1f )
01853       {
01854         norm_old->at(i) = -norm_old->at(i);
01855         ++flipped;
01856       }
01857     }
01858 
01859     // mic fixme: issue these things as debug once things got stable
01860     if (degenerate || flipped) 
01861       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() );
01862 
01863     // reinstall fixed normals
01864     prim->mGeometry->setNormalArray(norm_old.get());
01865   }
01866 
01867    // disabled: we transform the root matrix instead
01868    // --- orient geometry based on up vector ---
01869    // prim->mGeometry->transform((mat4)mUpMatrix);
01870 }
01871 //-----------------------------------------------------------------------------
01872 void DaeLoader::parseAsset(domElement* root)
01873 {
01874   domElement* asset_el = root->getChild("asset");
01875   if (asset_el)
01876   {
01877     domAsset* asset = static_cast<domAsset*>(asset_el);
01878 
01879     // up vector
01880     if (asset->getUp_axis())
01881     {
01882       if( asset->getUp_axis()->getValue() == UPAXISTYPE_X_UP )
01883       {
01884         // X_UP Negative y Positive x Positive z
01885         mUpMatrix.setX( vec3( 0, 1, 0) );
01886         mUpMatrix.setY( vec3(-1, 0, 0) );
01887         mUpMatrix.setZ( vec3( 0, 0, 1) );
01888       }
01889       else
01890       if( asset->getUp_axis()->getValue() == UPAXISTYPE_Z_UP )
01891       {
01892         // Z_UP Positive x Positive z Negative y
01893         mUpMatrix.setX( vec3(1, 0, 0) );
01894         mUpMatrix.setY( vec3(0, 0,-1) );
01895         mUpMatrix.setZ( vec3(0, 1, 0) );
01896       }
01897     }
01898 
01899     // try to fix the transparency written by crappy tools
01900     mInvertTransparency = false;
01901     mAssumeOpaque = false;
01902     if (loadOptions()->invertTransparency() == LoadWriterDae::LoadOptions::TransparencyInvert)
01903       mInvertTransparency = true;
01904     else
01905     if (loadOptions()->invertTransparency() == LoadWriterDae::LoadOptions::TransparencyAuto)
01906     {
01907       for(size_t i=0; i<asset->getContributor_array().getCount(); ++i)
01908       {
01909         const char* tool = asset->getContributor_array()[i]->getAuthoring_tool()->getValue();
01910         
01911         if (!tool)
01912           continue;
01913 
01914         VL_LOG_DEBUG << "- Authoring tool = " << tool << "\n";
01915 
01916         // Google SketchUp before 7.1 requires <transparency> inversion.
01917         // see http://www.collada.org/public_forum/viewtopic.php?f=12&t=1667
01918         const char* google_str = strstr(tool, "Google SketchUp");
01919         size_t google_str_len = strlen("Google SketchUp");
01920         if ( google_str )
01921         {
01922           if ( strlen(google_str) > google_str_len )
01923           {
01924             float version = 1000;
01925             if ( sscanf( google_str + google_str_len, "%f", &version) )
01926             {
01927               version = version * 100 + 0.5f;
01928               if (version < 710)
01929                 mInvertTransparency = true;
01930             }
01931             else
01932             {
01933               // don't trust Google SketchUp if we cannot read the version
01934               mAssumeOpaque = true;
01935             }
01936           }
01937           else
01938           {
01939             // don't trust Google SketchUp if we cannot read the version
01940             mAssumeOpaque = true;
01941           }
01942           break;
01943         }
01944 
01945         // See https://collada.org/mediawiki/index.php/ColladaMaya#ColladaMaya_3.03
01946         // - "Data exported with previous versions of our COLLADA tools may import with inverted transparency in ColladaMax 3.03 and ColladaMaya 3.03."
01947         // - Actually ColladaMax/ColladaMaya before 3.03 use unpredictable combinations of <transparent> and <transparency>, so... we assume opaque.
01948 
01949         const char* colladamaya_str = strstr(tool, "ColladaMaya v");
01950         size_t colladamaya_str_len = strlen("ColladaMaya v");
01951         if ( colladamaya_str )
01952         {
01953           float version = 1000;
01954           if ( strlen(colladamaya_str) > colladamaya_str_len  )
01955           {
01956             if ( sscanf( colladamaya_str + colladamaya_str_len, "%f", &version) )
01957             {
01958               version = version * 100 + 0.5f;
01959               if (version < 303)
01960                 mAssumeOpaque = true;
01961             }
01962             else
01963             {
01964               // don't trust ColladaMaya if we cannot read the version
01965               mAssumeOpaque = true;
01966             }
01967           }
01968           else
01969           {
01970             // don't trust ColladaMaya if we cannot read the version
01971             mAssumeOpaque = true;
01972           }
01973         }
01974 
01975         const char* colladamax_str = strstr(tool, "ColladaMax v");
01976         size_t colladamax_str_len = strlen("ColladaMax v");
01977         if ( colladamax_str )
01978         {
01979           float version = 1000;
01980           if ( strlen(colladamax_str) > colladamax_str_len )
01981           {
01982             if ( sscanf( colladamax_str + colladamax_str_len, "%f", &version) )
01983             {
01984               version = version * 100 + 0.5f;
01985               if (version < 303)
01986                 mAssumeOpaque = true;
01987             }
01988             else
01989             {
01990               // don't trust ColladaMax if we cannot read the version
01991               mAssumeOpaque = true;
01992             }
01993           }
01994           else
01995           {
01996             // don't trust ColladaMax if we cannot read the version
01997             mAssumeOpaque = true;
01998           }
01999         }
02000 
02001         // MeshLab seem to flip the transparency also now.
02002         if ( strstr(tool, "VCGLib | MeshLab") )
02003         {
02004           mInvertTransparency = true;
02005         }
02006 
02007         VL_LOG_DEBUG << "- Invert transparency = " << (mInvertTransparency ? "yes" : "no.") << "\n";
02008         VL_LOG_DEBUG << "- Assume opaque = " << (mAssumeOpaque? "yes" : "no.") << "\n";
02009 
02010         // stop at the first contributor
02011         break;
02012       }
02013     }
02014   }
02015 }

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:38.
Permission is granted to use this page to write and publish articles regarding Visualization Library.