vrshoot
diff libs/assimp/BlenderDNA.inl @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/BlenderDNA.inl Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,706 @@ 1.4 +/* 1.5 +Open Asset Import Library (assimp) 1.6 +---------------------------------------------------------------------- 1.7 + 1.8 +Copyright (c) 2006-2012, assimp team 1.9 +All rights reserved. 1.10 + 1.11 +Redistribution and use of this software in source and binary forms, 1.12 +with or without modification, are permitted provided that the 1.13 +following conditions are met: 1.14 + 1.15 +* Redistributions of source code must retain the above 1.16 + copyright notice, this list of conditions and the 1.17 + following disclaimer. 1.18 + 1.19 +* Redistributions in binary form must reproduce the above 1.20 + copyright notice, this list of conditions and the 1.21 + following disclaimer in the documentation and/or other 1.22 + materials provided with the distribution. 1.23 + 1.24 +* Neither the name of the assimp team, nor the names of its 1.25 + contributors may be used to endorse or promote products 1.26 + derived from this software without specific prior 1.27 + written permission of the assimp team. 1.28 + 1.29 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.30 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.31 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.32 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.33 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.34 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.35 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.36 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.37 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.38 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.39 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.40 + 1.41 +---------------------------------------------------------------------- 1.42 +*/ 1.43 + 1.44 +/** @file BlenderDNA.inl 1.45 + * @brief Blender `DNA` (file format specification embedded in 1.46 + * blend file itself) loader. 1.47 + */ 1.48 +#ifndef INCLUDED_AI_BLEND_DNA_INL 1.49 +#define INCLUDED_AI_BLEND_DNA_INL 1.50 + 1.51 +namespace Assimp { 1.52 + namespace Blender { 1.53 + 1.54 +//-------------------------------------------------------------------------------- 1.55 +const Field& Structure :: operator [] (const std::string& ss) const 1.56 +{ 1.57 + std::map<std::string, size_t>::const_iterator it = indices.find(ss); 1.58 + if (it == indices.end()) { 1.59 + throw Error((Formatter::format(), 1.60 + "BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`" 1.61 + )); 1.62 + } 1.63 + 1.64 + return fields[(*it).second]; 1.65 +} 1.66 + 1.67 +//-------------------------------------------------------------------------------- 1.68 +const Field* Structure :: Get (const std::string& ss) const 1.69 +{ 1.70 + std::map<std::string, size_t>::const_iterator it = indices.find(ss); 1.71 + return it == indices.end() ? NULL : &fields[(*it).second]; 1.72 +} 1.73 + 1.74 +//-------------------------------------------------------------------------------- 1.75 +const Field& Structure :: operator [] (const size_t i) const 1.76 +{ 1.77 + if (i >= fields.size()) { 1.78 + throw Error((Formatter::format(), 1.79 + "BlendDNA: There is no field with index `",i,"` in structure `",name,"`" 1.80 + )); 1.81 + } 1.82 + 1.83 + return fields[i]; 1.84 +} 1.85 + 1.86 +//-------------------------------------------------------------------------------- 1.87 +template <typename T> boost::shared_ptr<ElemBase> Structure :: Allocate() const 1.88 +{ 1.89 + return boost::shared_ptr<T>(new T()); 1.90 +} 1.91 + 1.92 +//-------------------------------------------------------------------------------- 1.93 +template <typename T> void Structure :: Convert( 1.94 + boost::shared_ptr<ElemBase> in, 1.95 + const FileDatabase& db) const 1.96 +{ 1.97 + Convert<T> (*static_cast<T*> ( in.get() ),db); 1.98 +} 1.99 + 1.100 +//-------------------------------------------------------------------------------- 1.101 +template <int error_policy, typename T, size_t M> 1.102 +void Structure :: ReadFieldArray(T (& out)[M], const char* name, const FileDatabase& db) const 1.103 +{ 1.104 + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); 1.105 + try { 1.106 + const Field& f = (*this)[name]; 1.107 + const Structure& s = db.dna[f.type]; 1.108 + 1.109 + // is the input actually an array? 1.110 + if (!(f.flags & FieldFlag_Array)) { 1.111 + throw Error((Formatter::format(),"Field `",name,"` of structure `", 1.112 + this->name,"` ought to be an array of size ",M 1.113 + )); 1.114 + } 1.115 + 1.116 + db.reader->IncPtr(f.offset); 1.117 + 1.118 + // size conversions are always allowed, regardless of error_policy 1.119 + unsigned int i = 0; 1.120 + for(; i < std::min(f.array_sizes[0],M); ++i) { 1.121 + s.Convert(out[i],db); 1.122 + } 1.123 + for(; i < M; ++i) { 1.124 + _defaultInitializer<ErrorPolicy_Igno>()(out[i]); 1.125 + } 1.126 + } 1.127 + catch (const Error& e) { 1.128 + _defaultInitializer<error_policy>()(out,e.what()); 1.129 + } 1.130 + 1.131 + // and recover the previous stream position 1.132 + db.reader->SetCurrentPos(old); 1.133 + 1.134 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.135 + ++db.stats().fields_read; 1.136 +#endif 1.137 +} 1.138 + 1.139 +//-------------------------------------------------------------------------------- 1.140 +template <int error_policy, typename T, size_t M, size_t N> 1.141 +void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileDatabase& db) const 1.142 +{ 1.143 + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); 1.144 + try { 1.145 + const Field& f = (*this)[name]; 1.146 + const Structure& s = db.dna[f.type]; 1.147 + 1.148 + // is the input actually an array? 1.149 + if (!(f.flags & FieldFlag_Array)) { 1.150 + throw Error((Formatter::format(),"Field `",name,"` of structure `", 1.151 + this->name,"` ought to be an array of size ",M,"*",N 1.152 + )); 1.153 + } 1.154 + 1.155 + db.reader->IncPtr(f.offset); 1.156 + 1.157 + // size conversions are always allowed, regardless of error_policy 1.158 + unsigned int i = 0; 1.159 + for(; i < std::min(f.array_sizes[0],M); ++i) { 1.160 + unsigned int j = 0; 1.161 + for(; j < std::min(f.array_sizes[1],N); ++j) { 1.162 + s.Convert(out[i][j],db); 1.163 + } 1.164 + for(; j < N; ++j) { 1.165 + _defaultInitializer<ErrorPolicy_Igno>()(out[i][j]); 1.166 + } 1.167 + } 1.168 + for(; i < M; ++i) { 1.169 + _defaultInitializer<ErrorPolicy_Igno>()(out[i]); 1.170 + } 1.171 + } 1.172 + catch (const Error& e) { 1.173 + _defaultInitializer<error_policy>()(out,e.what()); 1.174 + } 1.175 + 1.176 + // and recover the previous stream position 1.177 + db.reader->SetCurrentPos(old); 1.178 + 1.179 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.180 + ++db.stats().fields_read; 1.181 +#endif 1.182 +} 1.183 + 1.184 +//-------------------------------------------------------------------------------- 1.185 +template <int error_policy, template <typename> class TOUT, typename T> 1.186 +void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db) const 1.187 +{ 1.188 + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); 1.189 + Pointer ptrval; 1.190 + const Field* f; 1.191 + try { 1.192 + f = &(*this)[name]; 1.193 + 1.194 + // sanity check, should never happen if the genblenddna script is right 1.195 + if (!(f->flags & FieldFlag_Pointer)) { 1.196 + throw Error((Formatter::format(),"Field `",name,"` of structure `", 1.197 + this->name,"` ought to be a pointer")); 1.198 + } 1.199 + 1.200 + db.reader->IncPtr(f->offset); 1.201 + Convert(ptrval,db); 1.202 + // actually it is meaningless on which Structure the Convert is called 1.203 + // because the `Pointer` argument triggers a special implementation. 1.204 + } 1.205 + catch (const Error& e) { 1.206 + _defaultInitializer<error_policy>()(out,e.what()); 1.207 + 1.208 + out.reset(); 1.209 + return; 1.210 + } 1.211 + 1.212 + // resolve the pointer and load the corresponding structure 1.213 + ResolvePointer(out,ptrval,db,*f); 1.214 + 1.215 + // and recover the previous stream position 1.216 + db.reader->SetCurrentPos(old); 1.217 + 1.218 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.219 + ++db.stats().fields_read; 1.220 +#endif 1.221 +} 1.222 + 1.223 +//-------------------------------------------------------------------------------- 1.224 +template <int error_policy, template <typename> class TOUT, typename T, size_t N> 1.225 +void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 1.226 + const FileDatabase& db) const 1.227 +{ 1.228 + // XXX see if we can reduce this to call to the 'normal' ReadFieldPtr 1.229 + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); 1.230 + Pointer ptrval[N]; 1.231 + const Field* f; 1.232 + try { 1.233 + f = &(*this)[name]; 1.234 + 1.235 + // sanity check, should never happen if the genblenddna script is right 1.236 + if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) { 1.237 + throw Error((Formatter::format(),"Field `",name,"` of structure `", 1.238 + this->name,"` ought to be a pointer AND an array")); 1.239 + } 1.240 + 1.241 + db.reader->IncPtr(f->offset); 1.242 + 1.243 + size_t i = 0; 1.244 + for(; i < std::min(f->array_sizes[0],N); ++i) { 1.245 + Convert(ptrval[i],db); 1.246 + } 1.247 + for(; i < N; ++i) { 1.248 + _defaultInitializer<ErrorPolicy_Igno>()(ptrval[i]); 1.249 + } 1.250 + 1.251 + // actually it is meaningless on which Structure the Convert is called 1.252 + // because the `Pointer` argument triggers a special implementation. 1.253 + } 1.254 + catch (const Error& e) { 1.255 + _defaultInitializer<error_policy>()(out,e.what()); 1.256 + for(size_t i = 0; i < N; ++i) { 1.257 + out[i].reset(); 1.258 + } 1.259 + return; 1.260 + } 1.261 + for(size_t i = 0; i < N; ++i) { 1.262 + // resolve the pointer and load the corresponding structure 1.263 + ResolvePointer(out[i],ptrval[i],db,*f); 1.264 + } 1.265 + 1.266 + // and recover the previous stream position 1.267 + db.reader->SetCurrentPos(old); 1.268 + 1.269 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.270 + ++db.stats().fields_read; 1.271 +#endif 1.272 +} 1.273 + 1.274 +//-------------------------------------------------------------------------------- 1.275 +template <int error_policy, typename T> 1.276 +void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) const 1.277 +{ 1.278 + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); 1.279 + try { 1.280 + const Field& f = (*this)[name]; 1.281 + // find the structure definition pertaining to this field 1.282 + const Structure& s = db.dna[f.type]; 1.283 + 1.284 + db.reader->IncPtr(f.offset); 1.285 + s.Convert(out,db); 1.286 + } 1.287 + catch (const Error& e) { 1.288 + _defaultInitializer<error_policy>()(out,e.what()); 1.289 + } 1.290 + 1.291 + // and recover the previous stream position 1.292 + db.reader->SetCurrentPos(old); 1.293 + 1.294 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.295 + ++db.stats().fields_read; 1.296 +#endif 1.297 +} 1.298 + 1.299 + 1.300 +//-------------------------------------------------------------------------------- 1.301 +template <template <typename> class TOUT, typename T> 1.302 +void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const 1.303 +{ 1.304 + out.reset(); 1.305 + if (!ptrval.val) { 1.306 + return; 1.307 + } 1.308 + const Structure& s = db.dna[f.type]; 1.309 + // find the file block the pointer is pointing to 1.310 + const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); 1.311 + 1.312 + // also determine the target type from the block header 1.313 + // and check if it matches the type which we expect. 1.314 + const Structure& ss = db.dna[block->dna_index]; 1.315 + if (ss != s) { 1.316 + throw Error((Formatter::format(),"Expected target to be of type `",s.name, 1.317 + "` but seemingly it is a `",ss.name,"` instead" 1.318 + )); 1.319 + } 1.320 + 1.321 + // try to retrieve the object from the cache 1.322 + db.cache(out).get(s,out,ptrval); 1.323 + if (out) { 1.324 + return; 1.325 + } 1.326 + 1.327 + // seek to this location, but save the previous stream pointer. 1.328 + const StreamReaderAny::pos pold = db.reader->GetCurrentPos(); 1.329 + db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) )); 1.330 + // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems. 1.331 + // I really ought to improve StreamReader to work with 64 bit indices exclusively. 1.332 + 1.333 + // continue conversion after allocating the required storage 1.334 + size_t num = block->size / ss.size; 1.335 + T* o = _allocate(out,num); 1.336 + 1.337 + // cache the object before we convert it to avoid cyclic recursion. 1.338 + db.cache(out).set(s,out,ptrval); 1.339 + 1.340 + for (size_t i = 0; i < num; ++i,++o) { 1.341 + s.Convert(*o,db); 1.342 + } 1.343 + 1.344 + db.reader->SetCurrentPos(pold); 1.345 + 1.346 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.347 + if(out) { 1.348 + ++db.stats().pointers_resolved; 1.349 + } 1.350 +#endif 1.351 +} 1.352 + 1.353 +//-------------------------------------------------------------------------------- 1.354 +inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, const FileDatabase& db, const Field& /*f*/) const 1.355 +{ 1.356 + // Currently used exclusively by PackedFile::data to represent 1.357 + // a simple offset into the mapped BLEND file. 1.358 + out.reset(); 1.359 + if (!ptrval.val) { 1.360 + return; 1.361 + } 1.362 + 1.363 + // find the file block the pointer is pointing to 1.364 + const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); 1.365 + 1.366 + out = boost::shared_ptr< FileOffset > (new FileOffset()); 1.367 + out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) ); 1.368 +} 1.369 + 1.370 +//-------------------------------------------------------------------------------- 1.371 +template <template <typename> class TOUT, typename T> 1.372 +void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const 1.373 +{ 1.374 + // This is a function overload, not a template specialization. According to 1.375 + // the partial ordering rules, it should be selected by the compiler 1.376 + // for array-of-pointer inputs, i.e. Object::mats. 1.377 + 1.378 + out.reset(); 1.379 + if (!ptrval.val) { 1.380 + return; 1.381 + } 1.382 + 1.383 + // find the file block the pointer is pointing to 1.384 + const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); 1.385 + const size_t num = block->size / (db.i64bit?8:4); 1.386 + 1.387 + // keep the old stream position 1.388 + const StreamReaderAny::pos pold = db.reader->GetCurrentPos(); 1.389 + db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) )); 1.390 + 1.391 + // allocate raw storage for the array 1.392 + out.resize(num); 1.393 + for (size_t i = 0; i< num; ++i) { 1.394 + Pointer val; 1.395 + Convert(val,db); 1.396 + 1.397 + // and resolve the pointees 1.398 + ResolvePointer(out[i],val,db,f); 1.399 + } 1.400 + 1.401 + db.reader->SetCurrentPos(pold); 1.402 +} 1.403 + 1.404 +//-------------------------------------------------------------------------------- 1.405 +template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 1.406 + const Pointer & ptrval, 1.407 + const FileDatabase& db, 1.408 + const Field& /*f*/ 1.409 +) const 1.410 +{ 1.411 + // Special case when the data type needs to be determined at runtime. 1.412 + // Less secure than in the `strongly-typed` case. 1.413 + 1.414 + out.reset(); 1.415 + if (!ptrval.val) { 1.416 + return; 1.417 + } 1.418 + 1.419 + // find the file block the pointer is pointing to 1.420 + const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); 1.421 + 1.422 + // determine the target type from the block header 1.423 + const Structure& s = db.dna[block->dna_index]; 1.424 + 1.425 + // try to retrieve the object from the cache 1.426 + db.cache(out).get(s,out,ptrval); 1.427 + if (out) { 1.428 + return; 1.429 + } 1.430 + 1.431 + // seek to this location, but save the previous stream pointer. 1.432 + const StreamReaderAny::pos pold = db.reader->GetCurrentPos(); 1.433 + db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) )); 1.434 + // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems. 1.435 + // I really ought to improve StreamReader to work with 64 bit indices exclusively. 1.436 + 1.437 + // continue conversion after allocating the required storage 1.438 + DNA::FactoryPair builders = db.dna.GetBlobToStructureConverter(s,db); 1.439 + if (!builders.first) { 1.440 + // this might happen if DNA::RegisterConverters hasn't been called so far 1.441 + // or if the target type is not contained in `our` DNA. 1.442 + out.reset(); 1.443 + DefaultLogger::get()->warn((Formatter::format(), 1.444 + "Failed to find a converter for the `",s.name,"` structure" 1.445 + )); 1.446 + return; 1.447 + } 1.448 + 1.449 + // allocate the object hull 1.450 + out = (s.*builders.first)(); 1.451 + 1.452 + // cache the object immediately to prevent infinite recursion in a 1.453 + // circular list with a single element (i.e. a self-referencing element). 1.454 + db.cache(out).set(s,out,ptrval); 1.455 + 1.456 + // and do the actual conversion 1.457 + (s.*builders.second)(out,db); 1.458 + db.reader->SetCurrentPos(pold); 1.459 + 1.460 + // store a pointer to the name string of the actual type 1.461 + // in the object itself. This allows the conversion code 1.462 + // to perform additional type checking. 1.463 + out->dna_type = s.name.c_str(); 1.464 + 1.465 + 1.466 + 1.467 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.468 + ++db.stats().pointers_resolved; 1.469 +#endif 1.470 +} 1.471 + 1.472 +//-------------------------------------------------------------------------------- 1.473 +const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrval, const FileDatabase& db) const 1.474 +{ 1.475 + // the file blocks appear in list sorted by 1.476 + // with ascending base addresses so we can run a 1.477 + // binary search to locate the pointee quickly. 1.478 + 1.479 + // NOTE: Blender seems to distinguish between side-by-side 1.480 + // data (stored in the same data block) and far pointers, 1.481 + // which are only used for structures starting with an ID. 1.482 + // We don't need to make this distinction, our algorithm 1.483 + // works regardless where the data is stored. 1.484 + vector<FileBlockHead>::const_iterator it = std::lower_bound(db.entries.begin(),db.entries.end(),ptrval); 1.485 + if (it == db.entries.end()) { 1.486 + // this is crucial, pointers may not be invalid. 1.487 + // this is either a corrupted file or an attempted attack. 1.488 + throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x", 1.489 + std::hex,ptrval.val,", no file block falls into this address range" 1.490 + )); 1.491 + } 1.492 + if (ptrval.val >= (*it).address.val + (*it).size) { 1.493 + throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x", 1.494 + std::hex,ptrval.val,", nearest file block starting at 0x", 1.495 + (*it).address.val," ends at 0x", 1.496 + (*it).address.val + (*it).size 1.497 + )); 1.498 + } 1.499 + return &*it; 1.500 +} 1.501 + 1.502 +// ------------------------------------------------------------------------------------------------ 1.503 +// NOTE: The MSVC debugger keeps showing up this annoying `a cast to a smaller data type has 1.504 +// caused a loss of data`-warning. Avoid this warning by a masking with an appropriate bitmask. 1.505 + 1.506 +template <typename T> struct signless; 1.507 +template <> struct signless<char> {typedef unsigned char type;}; 1.508 +template <> struct signless<short> {typedef unsigned short type;}; 1.509 +template <> struct signless<int> {typedef unsigned int type;}; 1.510 + 1.511 +template <typename T> 1.512 +struct static_cast_silent { 1.513 + template <typename V> 1.514 + T operator()(V in) { 1.515 + return static_cast<T>(in & static_cast<typename signless<T>::type>(-1)); 1.516 + } 1.517 +}; 1.518 + 1.519 +template <> struct static_cast_silent<float> { 1.520 + template <typename V> float operator()(V in) { 1.521 + return static_cast<float> (in); 1.522 + } 1.523 +}; 1.524 + 1.525 +template <> struct static_cast_silent<double> { 1.526 + template <typename V> double operator()(V in) { 1.527 + return static_cast<double>(in); 1.528 + } 1.529 +}; 1.530 + 1.531 +// ------------------------------------------------------------------------------------------------ 1.532 +template <typename T> inline void ConvertDispatcher(T& out, const Structure& in,const FileDatabase& db) 1.533 +{ 1.534 + if (in.name == "int") { 1.535 + out = static_cast_silent<T>()(db.reader->GetU4()); 1.536 + } 1.537 + else if (in.name == "short") { 1.538 + out = static_cast_silent<T>()(db.reader->GetU2()); 1.539 + } 1.540 + else if (in.name == "char") { 1.541 + out = static_cast_silent<T>()(db.reader->GetU1()); 1.542 + } 1.543 + else if (in.name == "float") { 1.544 + out = static_cast<T>(db.reader->GetF4()); 1.545 + } 1.546 + else if (in.name == "double") { 1.547 + out = static_cast<T>(db.reader->GetF8()); 1.548 + } 1.549 + else { 1.550 + throw DeadlyImportError("Unknown source for conversion to primitive data type: "+in.name); 1.551 + } 1.552 +} 1.553 + 1.554 +// ------------------------------------------------------------------------------------------------ 1.555 +template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const 1.556 +{ 1.557 + ConvertDispatcher(dest,*this,db); 1.558 +} 1.559 + 1.560 +// ------------------------------------------------------------------------------------------------ 1.561 +template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const 1.562 +{ 1.563 + // automatic rescaling from short to float and vice versa (seems to be used by normals) 1.564 + if (name == "float") { 1.565 + dest = static_cast<short>(db.reader->GetF4() * 32767.f); 1.566 + //db.reader->IncPtr(-4); 1.567 + return; 1.568 + } 1.569 + else if (name == "double") { 1.570 + dest = static_cast<short>(db.reader->GetF8() * 32767.); 1.571 + //db.reader->IncPtr(-8); 1.572 + return; 1.573 + } 1.574 + ConvertDispatcher(dest,*this,db); 1.575 +} 1.576 + 1.577 +// ------------------------------------------------------------------------------------------------ 1.578 +template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const 1.579 +{ 1.580 + // automatic rescaling from char to float and vice versa (seems useful for RGB colors) 1.581 + if (name == "float") { 1.582 + dest = static_cast<char>(db.reader->GetF4() * 255.f); 1.583 + return; 1.584 + } 1.585 + else if (name == "double") { 1.586 + dest = static_cast<char>(db.reader->GetF8() * 255.f); 1.587 + return; 1.588 + } 1.589 + ConvertDispatcher(dest,*this,db); 1.590 +} 1.591 + 1.592 +// ------------------------------------------------------------------------------------------------ 1.593 +template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const 1.594 +{ 1.595 + // automatic rescaling from char to float and vice versa (seems useful for RGB colors) 1.596 + if (name == "char") { 1.597 + dest = db.reader->GetI1() / 255.f; 1.598 + return; 1.599 + } 1.600 + // automatic rescaling from short to float and vice versa (used by normals) 1.601 + else if (name == "short") { 1.602 + dest = db.reader->GetI2() / 32767.f; 1.603 + return; 1.604 + } 1.605 + ConvertDispatcher(dest,*this,db); 1.606 +} 1.607 + 1.608 +// ------------------------------------------------------------------------------------------------ 1.609 +template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const 1.610 +{ 1.611 + if (name == "char") { 1.612 + dest = db.reader->GetI1() / 255.; 1.613 + return; 1.614 + } 1.615 + else if (name == "short") { 1.616 + dest = db.reader->GetI2() / 32767.; 1.617 + return; 1.618 + } 1.619 + ConvertDispatcher(dest,*this,db); 1.620 +} 1.621 + 1.622 +// ------------------------------------------------------------------------------------------------ 1.623 +template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const 1.624 +{ 1.625 + if (db.i64bit) { 1.626 + dest.val = db.reader->GetU8(); 1.627 + //db.reader->IncPtr(-8); 1.628 + return; 1.629 + } 1.630 + dest.val = db.reader->GetU4(); 1.631 + //db.reader->IncPtr(-4); 1.632 +} 1.633 + 1.634 +//-------------------------------------------------------------------------------- 1.635 +const Structure& DNA :: operator [] (const std::string& ss) const 1.636 +{ 1.637 + std::map<std::string, size_t>::const_iterator it = indices.find(ss); 1.638 + if (it == indices.end()) { 1.639 + throw Error((Formatter::format(), 1.640 + "BlendDNA: Did not find a structure named `",ss,"`" 1.641 + )); 1.642 + } 1.643 + 1.644 + return structures[(*it).second]; 1.645 +} 1.646 + 1.647 +//-------------------------------------------------------------------------------- 1.648 +const Structure* DNA :: Get (const std::string& ss) const 1.649 +{ 1.650 + std::map<std::string, size_t>::const_iterator it = indices.find(ss); 1.651 + return it == indices.end() ? NULL : &structures[(*it).second]; 1.652 +} 1.653 + 1.654 +//-------------------------------------------------------------------------------- 1.655 +const Structure& DNA :: operator [] (const size_t i) const 1.656 +{ 1.657 + if (i >= structures.size()) { 1.658 + throw Error((Formatter::format(), 1.659 + "BlendDNA: There is no structure with index `",i,"`" 1.660 + )); 1.661 + } 1.662 + 1.663 + return structures[i]; 1.664 +} 1.665 + 1.666 +//-------------------------------------------------------------------------------- 1.667 +template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: get ( 1.668 + const Structure& s, 1.669 + TOUT<T>& out, 1.670 + const Pointer& ptr 1.671 +) const { 1.672 + 1.673 + if(s.cache_idx == static_cast<size_t>(-1)) { 1.674 + s.cache_idx = db.next_cache_idx++; 1.675 + caches.resize(db.next_cache_idx); 1.676 + return; 1.677 + } 1.678 + 1.679 + typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr); 1.680 + if (it != caches[s.cache_idx].end()) { 1.681 + out = boost::static_pointer_cast<T>( (*it).second ); 1.682 + 1.683 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.684 + ++db.stats().cache_hits; 1.685 +#endif 1.686 + } 1.687 + // otherwise, out remains untouched 1.688 +} 1.689 + 1.690 + 1.691 +//-------------------------------------------------------------------------------- 1.692 +template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: set ( 1.693 + const Structure& s, 1.694 + const TOUT<T>& out, 1.695 + const Pointer& ptr 1.696 +) { 1.697 + if(s.cache_idx == static_cast<size_t>(-1)) { 1.698 + s.cache_idx = db.next_cache_idx++; 1.699 + caches.resize(db.next_cache_idx); 1.700 + } 1.701 + caches[s.cache_idx][ptr] = boost::static_pointer_cast<ElemBase>( out ); 1.702 + 1.703 +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS 1.704 + ++db.stats().cached_objects; 1.705 +#endif 1.706 +} 1.707 + 1.708 +}} 1.709 +#endif