Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://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 }