vrshoot
diff libs/assimp/SceneCombiner.cpp @ 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/SceneCombiner.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,1146 @@ 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 + 1.45 +// ---------------------------------------------------------------------------- 1.46 +/** @file Implements Assimp::SceneCombiner. This is a smart utility 1.47 + * class that combines multiple scenes, meshes, ... into one. Currently 1.48 + * these utilities are used by the IRR and LWS loaders and the 1.49 + * OptimizeGraph step. 1.50 + */ 1.51 +// ---------------------------------------------------------------------------- 1.52 +#include "AssimpPCH.h" 1.53 +#include "SceneCombiner.h" 1.54 +#include "fast_atof.h" 1.55 +#include "Hash.h" 1.56 +#include "time.h" 1.57 + 1.58 +namespace Assimp { 1.59 + 1.60 +// ------------------------------------------------------------------------------------------------ 1.61 +// Add a prefix to a string 1.62 +inline void PrefixString(aiString& string,const char* prefix, unsigned int len) 1.63 +{ 1.64 + // If the string is already prefixed, we won't prefix it a second time 1.65 + if (string.length >= 1 && string.data[0] == '$') 1.66 + return; 1.67 + 1.68 + if (len+string.length>=MAXLEN-1) { 1.69 + DefaultLogger::get()->debug("Can't add an unique prefix because the string is too long"); 1.70 + ai_assert(false); 1.71 + return; 1.72 + } 1.73 + 1.74 + // Add the prefix 1.75 + ::memmove(string.data+len,string.data,string.length+1); 1.76 + ::memcpy (string.data, prefix, len); 1.77 + 1.78 + // And update the string's length 1.79 + string.length += len; 1.80 +} 1.81 + 1.82 +// ------------------------------------------------------------------------------------------------ 1.83 +// Add node identifiers to a hashing set 1.84 +void SceneCombiner::AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes) 1.85 +{ 1.86 + // Add node name to hashing set if it is non-empty - empty nodes are allowed 1.87 + // and they can't have any anims assigned so its absolutely safe to duplicate them. 1.88 + if (node->mName.length) { 1.89 + hashes.insert( SuperFastHash(node->mName.data,node->mName.length) ); 1.90 + } 1.91 + 1.92 + // Process all children recursively 1.93 + for (unsigned int i = 0; i < node->mNumChildren;++i) 1.94 + AddNodeHashes(node->mChildren[i],hashes); 1.95 +} 1.96 + 1.97 +// ------------------------------------------------------------------------------------------------ 1.98 +// Add a name prefix to all nodes in a hierarchy 1.99 +void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) 1.100 +{ 1.101 + ai_assert(NULL != prefix); 1.102 + PrefixString(node->mName,prefix,len); 1.103 + 1.104 + // Process all children recursively 1.105 + for (unsigned int i = 0; i < node->mNumChildren;++i) 1.106 + AddNodePrefixes(node->mChildren[i],prefix,len); 1.107 +} 1.108 + 1.109 +// ------------------------------------------------------------------------------------------------ 1.110 +// Search for matching names 1.111 +bool SceneCombiner::FindNameMatch(const aiString& name, std::vector<SceneHelper>& input, unsigned int cur) 1.112 +{ 1.113 + const unsigned int hash = SuperFastHash(name.data, name.length); 1.114 + 1.115 + // Check whether we find a positive match in one of the given sets 1.116 + for (unsigned int i = 0; i < input.size(); ++i) { 1.117 + 1.118 + if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) { 1.119 + return true; 1.120 + } 1.121 + } 1.122 + return false; 1.123 +} 1.124 + 1.125 +// ------------------------------------------------------------------------------------------------ 1.126 +// Add a name prefix to all nodes in a hierarchy if a hash match is found 1.127 +void SceneCombiner::AddNodePrefixesChecked(aiNode* node, const char* prefix, unsigned int len, 1.128 + std::vector<SceneHelper>& input, unsigned int cur) 1.129 +{ 1.130 + ai_assert(NULL != prefix); 1.131 + const unsigned int hash = SuperFastHash(node->mName.data,node->mName.length); 1.132 + 1.133 + // Check whether we find a positive match in one of the given sets 1.134 + for (unsigned int i = 0; i < input.size(); ++i) { 1.135 + 1.136 + if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) { 1.137 + PrefixString(node->mName,prefix,len); 1.138 + break; 1.139 + } 1.140 + } 1.141 + 1.142 + // Process all children recursively 1.143 + for (unsigned int i = 0; i < node->mNumChildren;++i) 1.144 + AddNodePrefixesChecked(node->mChildren[i],prefix,len,input,cur); 1.145 +} 1.146 + 1.147 +// ------------------------------------------------------------------------------------------------ 1.148 +// Add an offset to all mesh indices in a node graph 1.149 +void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset) 1.150 +{ 1.151 + for (unsigned int i = 0; i < node->mNumMeshes;++i) 1.152 + node->mMeshes[i] += offset; 1.153 + 1.154 + for (unsigned int i = 0; i < node->mNumChildren;++i) 1.155 + OffsetNodeMeshIndices(node->mChildren[i],offset); 1.156 +} 1.157 + 1.158 +// ------------------------------------------------------------------------------------------------ 1.159 +// Merges two scenes. Currently only used by the LWS loader. 1.160 +void SceneCombiner::MergeScenes(aiScene** _dest,std::vector<aiScene*>& src, 1.161 + unsigned int flags) 1.162 +{ 1.163 + ai_assert(NULL != _dest); 1.164 + 1.165 + // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it 1.166 + if (src.empty()) 1.167 + { 1.168 + if (*_dest) 1.169 + { 1.170 + (*_dest)->~aiScene(); 1.171 + SceneCombiner::CopySceneFlat(_dest,src[0]); 1.172 + } 1.173 + else *_dest = src[0]; 1.174 + return; 1.175 + } 1.176 + if (*_dest)(*_dest)->~aiScene(); 1.177 + else *_dest = new aiScene(); 1.178 + 1.179 + // Create a dummy scene to serve as master for the others 1.180 + aiScene* master = new aiScene(); 1.181 + master->mRootNode = new aiNode(); 1.182 + master->mRootNode->mName.Set("<MergeRoot>"); 1.183 + 1.184 + std::vector<AttachmentInfo> srcList (src.size()); 1.185 + for (unsigned int i = 0; i < srcList.size();++i) { 1.186 + srcList[i] = AttachmentInfo(src[i],master->mRootNode); 1.187 + } 1.188 + 1.189 + // 'master' will be deleted afterwards 1.190 + MergeScenes (_dest, master, srcList, flags); 1.191 +} 1.192 + 1.193 +// ------------------------------------------------------------------------------------------------ 1.194 +void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInfo>& srcList) 1.195 +{ 1.196 + unsigned int cnt; 1.197 + for (cnt = 0; cnt < attach->mNumChildren;++cnt) 1.198 + AttachToGraph(attach->mChildren[cnt],srcList); 1.199 + 1.200 + cnt = 0; 1.201 + for (std::vector<NodeAttachmentInfo>::iterator it = srcList.begin(); 1.202 + it != srcList.end(); ++it) 1.203 + { 1.204 + if ((*it).attachToNode == attach && !(*it).resolved) 1.205 + ++cnt; 1.206 + } 1.207 + 1.208 + if (cnt) { 1.209 + aiNode** n = new aiNode*[cnt+attach->mNumChildren]; 1.210 + if (attach->mNumChildren) { 1.211 + ::memcpy(n,attach->mChildren,sizeof(void*)*attach->mNumChildren); 1.212 + delete[] attach->mChildren; 1.213 + } 1.214 + attach->mChildren = n; 1.215 + 1.216 + n += attach->mNumChildren; 1.217 + attach->mNumChildren += cnt; 1.218 + 1.219 + for (unsigned int i = 0; i < srcList.size();++i) { 1.220 + NodeAttachmentInfo& att = srcList[i]; 1.221 + if (att.attachToNode == attach && !att.resolved) { 1.222 + *n = att.node; 1.223 + (**n).mParent = attach; 1.224 + ++n; 1.225 + 1.226 + // mark this attachment as resolved 1.227 + att.resolved = true; 1.228 + } 1.229 + } 1.230 + } 1.231 +} 1.232 + 1.233 +// ------------------------------------------------------------------------------------------------ 1.234 +void SceneCombiner::AttachToGraph ( aiScene* master, 1.235 + std::vector<NodeAttachmentInfo>& src) 1.236 +{ 1.237 + ai_assert(NULL != master); 1.238 + AttachToGraph(master->mRootNode,src); 1.239 +} 1.240 + 1.241 +// ------------------------------------------------------------------------------------------------ 1.242 +void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, 1.243 + std::vector<AttachmentInfo>& srcList, 1.244 + unsigned int flags) 1.245 +{ 1.246 + ai_assert(NULL != _dest); 1.247 + 1.248 + // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it 1.249 + if (srcList.empty()) { 1.250 + if (*_dest) { 1.251 + SceneCombiner::CopySceneFlat(_dest,master); 1.252 + } 1.253 + else *_dest = master; 1.254 + return; 1.255 + } 1.256 + if (*_dest) { 1.257 + (*_dest)->~aiScene(); 1.258 + new (*_dest) aiScene(); 1.259 + } 1.260 + else *_dest = new aiScene(); 1.261 + 1.262 + aiScene* dest = *_dest; 1.263 + 1.264 + std::vector<SceneHelper> src (srcList.size()+1); 1.265 + src[0].scene = master; 1.266 + for (unsigned int i = 0; i < srcList.size();++i) { 1.267 + src[i+1] = SceneHelper( srcList[i].scene ); 1.268 + } 1.269 + 1.270 + // this helper array specifies which scenes are duplicates of others 1.271 + std::vector<unsigned int> duplicates(src.size(),UINT_MAX); 1.272 + 1.273 + // this helper array is used as lookup table several times 1.274 + std::vector<unsigned int> offset(src.size()); 1.275 + 1.276 + // Find duplicate scenes 1.277 + for (unsigned int i = 0; i < src.size();++i) { 1.278 + if (duplicates[i] != i && duplicates[i] != UINT_MAX) { 1.279 + continue; 1.280 + } 1.281 + 1.282 + duplicates[i] = i; 1.283 + for ( unsigned int a = i+1; a < src.size(); ++a) { 1.284 + if (src[i].scene == src[a].scene) { 1.285 + duplicates[a] = i; 1.286 + } 1.287 + } 1.288 + } 1.289 + 1.290 + // Generate unique names for all named stuff? 1.291 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) 1.292 + { 1.293 +#if 0 1.294 + // Construct a proper random number generator 1.295 + boost::mt19937 rng( ); 1.296 + boost::uniform_int<> dist(1u,1 << 24u); 1.297 + boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rndGen(rng, dist); 1.298 +#endif 1.299 + for (unsigned int i = 1; i < src.size();++i) 1.300 + { 1.301 + //if (i != duplicates[i]) 1.302 + //{ 1.303 + // // duplicate scenes share the same UID 1.304 + // ::strcpy( src[i].id, src[duplicates[i]].id ); 1.305 + // src[i].idlen = src[duplicates[i]].idlen; 1.306 + 1.307 + // continue; 1.308 + //} 1.309 + 1.310 + src[i].idlen = ::sprintf(src[i].id,"$%.6X$_",i); 1.311 + 1.312 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { 1.313 + 1.314 + // Compute hashes for all identifiers in this scene and store them 1.315 + // in a sorted table (for convenience I'm using std::set). We hash 1.316 + // just the node and animation channel names, all identifiers except 1.317 + // the material names should be caught by doing this. 1.318 + AddNodeHashes(src[i]->mRootNode,src[i].hashes); 1.319 + 1.320 + for (unsigned int a = 0; a < src[i]->mNumAnimations;++a) { 1.321 + aiAnimation* anim = src[i]->mAnimations[a]; 1.322 + src[i].hashes.insert(SuperFastHash(anim->mName.data,anim->mName.length)); 1.323 + } 1.324 + } 1.325 + } 1.326 + } 1.327 + 1.328 + unsigned int cnt; 1.329 + 1.330 + // First find out how large the respective output arrays must be 1.331 + for ( unsigned int n = 0; n < src.size();++n ) 1.332 + { 1.333 + SceneHelper* cur = &src[n]; 1.334 + 1.335 + if (n == duplicates[n] || flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) { 1.336 + dest->mNumTextures += (*cur)->mNumTextures; 1.337 + dest->mNumMaterials += (*cur)->mNumMaterials; 1.338 + dest->mNumMeshes += (*cur)->mNumMeshes; 1.339 + } 1.340 + 1.341 + dest->mNumLights += (*cur)->mNumLights; 1.342 + dest->mNumCameras += (*cur)->mNumCameras; 1.343 + dest->mNumAnimations += (*cur)->mNumAnimations; 1.344 + 1.345 + // Combine the flags of all scenes 1.346 + // We need to process them flag-by-flag here to get correct results 1.347 + // dest->mFlags ; //|= (*cur)->mFlags; 1.348 + if ((*cur)->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { 1.349 + dest->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; 1.350 + } 1.351 + } 1.352 + 1.353 + // generate the output texture list + an offset table for all texture indices 1.354 + if (dest->mNumTextures) 1.355 + { 1.356 + aiTexture** pip = dest->mTextures = new aiTexture*[dest->mNumMaterials]; 1.357 + cnt = 0; 1.358 + for ( unsigned int n = 0; n < src.size();++n ) 1.359 + { 1.360 + SceneHelper* cur = &src[n]; 1.361 + for (unsigned int i = 0; i < (*cur)->mNumTextures;++i) 1.362 + { 1.363 + if (n != duplicates[n]) 1.364 + { 1.365 + if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) 1.366 + Copy(pip,(*cur)->mTextures[i]); 1.367 + 1.368 + else continue; 1.369 + } 1.370 + else *pip = (*cur)->mTextures[i]; 1.371 + ++pip; 1.372 + } 1.373 + 1.374 + offset[n] = cnt; 1.375 + cnt = (unsigned int)(pip - dest->mTextures); 1.376 + } 1.377 + } 1.378 + 1.379 + // generate the output material list + an offset table for all material indices 1.380 + if (dest->mNumMaterials) 1.381 + { 1.382 + aiMaterial** pip = dest->mMaterials = new aiMaterial*[dest->mNumMaterials]; 1.383 + cnt = 0; 1.384 + for ( unsigned int n = 0; n < src.size();++n ) { 1.385 + SceneHelper* cur = &src[n]; 1.386 + for (unsigned int i = 0; i < (*cur)->mNumMaterials;++i) 1.387 + { 1.388 + if (n != duplicates[n]) 1.389 + { 1.390 + if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) 1.391 + Copy(pip,(*cur)->mMaterials[i]); 1.392 + 1.393 + else continue; 1.394 + } 1.395 + else *pip = (*cur)->mMaterials[i]; 1.396 + 1.397 + if ((*cur)->mNumTextures != dest->mNumTextures) { 1.398 + // We need to update all texture indices of the mesh. So we need to search for 1.399 + // a material property called '$tex.file' 1.400 + 1.401 + for (unsigned int a = 0; a < (*pip)->mNumProperties;++a) 1.402 + { 1.403 + aiMaterialProperty* prop = (*pip)->mProperties[a]; 1.404 + if (!strncmp(prop->mKey.data,"$tex.file",9)) 1.405 + { 1.406 + // Check whether this texture is an embedded texture. 1.407 + // In this case the property looks like this: *<n>, 1.408 + // where n is the index of the texture. 1.409 + aiString& s = *((aiString*)prop->mData); 1.410 + if ('*' == s.data[0]) { 1.411 + // Offset the index and write it back .. 1.412 + const unsigned int idx = strtoul10(&s.data[1]) + offset[n]; 1.413 + ASSIMP_itoa10(&s.data[1],sizeof(s.data)-1,idx); 1.414 + } 1.415 + } 1.416 + 1.417 + // Need to generate new, unique material names? 1.418 + else if (!::strcmp( prop->mKey.data,"$mat.name" ) && flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) 1.419 + { 1.420 + aiString* pcSrc = (aiString*) prop->mData; 1.421 + PrefixString(*pcSrc, (*cur).id, (*cur).idlen); 1.422 + } 1.423 + } 1.424 + } 1.425 + ++pip; 1.426 + } 1.427 + 1.428 + offset[n] = cnt; 1.429 + cnt = (unsigned int)(pip - dest->mMaterials); 1.430 + } 1.431 + } 1.432 + 1.433 + // generate the output mesh list + again an offset table for all mesh indices 1.434 + if (dest->mNumMeshes) 1.435 + { 1.436 + aiMesh** pip = dest->mMeshes = new aiMesh*[dest->mNumMeshes]; 1.437 + cnt = 0; 1.438 + for ( unsigned int n = 0; n < src.size();++n ) 1.439 + { 1.440 + SceneHelper* cur = &src[n]; 1.441 + for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i) 1.442 + { 1.443 + if (n != duplicates[n]) { 1.444 + if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) 1.445 + Copy(pip, (*cur)->mMeshes[i]); 1.446 + 1.447 + else continue; 1.448 + } 1.449 + else *pip = (*cur)->mMeshes[i]; 1.450 + 1.451 + // update the material index of the mesh 1.452 + (*pip)->mMaterialIndex += offset[n]; 1.453 + ++pip; 1.454 + } 1.455 + 1.456 + // reuse the offset array - store now the mesh offset in it 1.457 + offset[n] = cnt; 1.458 + cnt = (unsigned int)(pip - dest->mMeshes); 1.459 + } 1.460 + } 1.461 + 1.462 + std::vector <NodeAttachmentInfo> nodes; 1.463 + nodes.reserve(srcList.size()); 1.464 + 1.465 + // ---------------------------------------------------------------------------- 1.466 + // Now generate the output node graph. We need to make those 1.467 + // names in the graph that are referenced by anims or lights 1.468 + // or cameras unique. So we add a prefix to them ... $<rand>_ 1.469 + // We could also use a counter, but using a random value allows us to 1.470 + // use just one prefix if we are joining multiple scene hierarchies recursively. 1.471 + // Chances are quite good we don't collide, so we try that ... 1.472 + // ---------------------------------------------------------------------------- 1.473 + 1.474 + // Allocate space for light sources, cameras and animations 1.475 + aiLight** ppLights = dest->mLights = (dest->mNumLights 1.476 + ? new aiLight*[dest->mNumLights] : NULL); 1.477 + 1.478 + aiCamera** ppCameras = dest->mCameras = (dest->mNumCameras 1.479 + ? new aiCamera*[dest->mNumCameras] : NULL); 1.480 + 1.481 + aiAnimation** ppAnims = dest->mAnimations = (dest->mNumAnimations 1.482 + ? new aiAnimation*[dest->mNumAnimations] : NULL); 1.483 + 1.484 + for ( int n = src.size()-1; n >= 0 ;--n ) /* !!! important !!! */ 1.485 + { 1.486 + SceneHelper* cur = &src[n]; 1.487 + aiNode* node; 1.488 + 1.489 + // To offset or not to offset, this is the question 1.490 + if (n != (int)duplicates[n]) 1.491 + { 1.492 + // Get full scenegraph copy 1.493 + Copy( &node, (*cur)->mRootNode ); 1.494 + OffsetNodeMeshIndices(node,offset[duplicates[n]]); 1.495 + 1.496 + if (flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) { 1.497 + // (note:) they are already 'offseted' by offset[duplicates[n]] 1.498 + OffsetNodeMeshIndices(node,offset[n] - offset[duplicates[n]]); 1.499 + } 1.500 + } 1.501 + else // if (n == duplicates[n]) 1.502 + { 1.503 + node = (*cur)->mRootNode; 1.504 + OffsetNodeMeshIndices(node,offset[n]); 1.505 + } 1.506 + if (n) // src[0] is the master node 1.507 + nodes.push_back(NodeAttachmentInfo( node,srcList[n-1].attachToNode,n )); 1.508 + 1.509 + // add name prefixes? 1.510 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { 1.511 + 1.512 + // or the whole scenegraph 1.513 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { 1.514 + AddNodePrefixesChecked(node,(*cur).id,(*cur).idlen,src,n); 1.515 + } 1.516 + else AddNodePrefixes(node,(*cur).id,(*cur).idlen); 1.517 + 1.518 + // meshes 1.519 + for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i) { 1.520 + aiMesh* mesh = (*cur)->mMeshes[i]; 1.521 + 1.522 + // rename all bones 1.523 + for (unsigned int a = 0; a < mesh->mNumBones;++a) { 1.524 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { 1.525 + if (!FindNameMatch(mesh->mBones[a]->mName,src,n)) 1.526 + continue; 1.527 + } 1.528 + PrefixString(mesh->mBones[a]->mName,(*cur).id,(*cur).idlen); 1.529 + } 1.530 + } 1.531 + } 1.532 + 1.533 + // -------------------------------------------------------------------- 1.534 + // Copy light sources 1.535 + for (unsigned int i = 0; i < (*cur)->mNumLights;++i,++ppLights) 1.536 + { 1.537 + if (n != (int)duplicates[n]) // duplicate scene? 1.538 + { 1.539 + Copy(ppLights, (*cur)->mLights[i]); 1.540 + } 1.541 + else *ppLights = (*cur)->mLights[i]; 1.542 + 1.543 + 1.544 + // Add name prefixes? 1.545 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { 1.546 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { 1.547 + if (!FindNameMatch((*ppLights)->mName,src,n)) 1.548 + continue; 1.549 + } 1.550 + 1.551 + PrefixString((*ppLights)->mName,(*cur).id,(*cur).idlen); 1.552 + } 1.553 + } 1.554 + 1.555 + // -------------------------------------------------------------------- 1.556 + // Copy cameras 1.557 + for (unsigned int i = 0; i < (*cur)->mNumCameras;++i,++ppCameras) { 1.558 + if (n != (int)duplicates[n]) // duplicate scene? 1.559 + { 1.560 + Copy(ppCameras, (*cur)->mCameras[i]); 1.561 + } 1.562 + else *ppCameras = (*cur)->mCameras[i]; 1.563 + 1.564 + // Add name prefixes? 1.565 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { 1.566 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { 1.567 + if (!FindNameMatch((*ppCameras)->mName,src,n)) 1.568 + continue; 1.569 + } 1.570 + 1.571 + PrefixString((*ppCameras)->mName,(*cur).id,(*cur).idlen); 1.572 + } 1.573 + } 1.574 + 1.575 + // -------------------------------------------------------------------- 1.576 + // Copy animations 1.577 + for (unsigned int i = 0; i < (*cur)->mNumAnimations;++i,++ppAnims) { 1.578 + if (n != (int)duplicates[n]) // duplicate scene? 1.579 + { 1.580 + Copy(ppAnims, (*cur)->mAnimations[i]); 1.581 + } 1.582 + else *ppAnims = (*cur)->mAnimations[i]; 1.583 + 1.584 + // Add name prefixes? 1.585 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { 1.586 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { 1.587 + if (!FindNameMatch((*ppAnims)->mName,src,n)) 1.588 + continue; 1.589 + } 1.590 + 1.591 + PrefixString((*ppAnims)->mName,(*cur).id,(*cur).idlen); 1.592 + 1.593 + // don't forget to update all node animation channels 1.594 + for (unsigned int a = 0; a < (*ppAnims)->mNumChannels;++a) { 1.595 + if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { 1.596 + if (!FindNameMatch((*ppAnims)->mChannels[a]->mNodeName,src,n)) 1.597 + continue; 1.598 + } 1.599 + 1.600 + PrefixString((*ppAnims)->mChannels[a]->mNodeName,(*cur).id,(*cur).idlen); 1.601 + } 1.602 + } 1.603 + } 1.604 + } 1.605 + 1.606 + // Now build the output graph 1.607 + AttachToGraph ( master, nodes); 1.608 + dest->mRootNode = master->mRootNode; 1.609 + 1.610 + // Check whether we succeeded at building the output graph 1.611 + for (std::vector <NodeAttachmentInfo> ::iterator it = nodes.begin(); 1.612 + it != nodes.end(); ++it) 1.613 + { 1.614 + if (!(*it).resolved) { 1.615 + if (flags & AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS) { 1.616 + // search for this attachment point in all other imported scenes, too. 1.617 + for ( unsigned int n = 0; n < src.size();++n ) { 1.618 + if (n != (*it).src_idx) { 1.619 + AttachToGraph(src[n].scene,nodes); 1.620 + if ((*it).resolved) 1.621 + break; 1.622 + } 1.623 + } 1.624 + } 1.625 + if (!(*it).resolved) { 1.626 + DefaultLogger::get()->error(std::string("SceneCombiner: Failed to resolve attachment ") 1.627 + + (*it).node->mName.data + " " + (*it).attachToNode->mName.data); 1.628 + } 1.629 + } 1.630 + } 1.631 + 1.632 + // now delete all input scenes. Make sure duplicate scenes aren't 1.633 + // deleted more than one time 1.634 + for ( unsigned int n = 0; n < src.size();++n ) { 1.635 + if (n != duplicates[n]) // duplicate scene? 1.636 + continue; 1.637 + 1.638 + aiScene* deleteMe = src[n].scene; 1.639 + 1.640 + // We need to delete the arrays before the destructor is called - 1.641 + // we are reusing the array members 1.642 + delete[] deleteMe->mMeshes; deleteMe->mMeshes = NULL; 1.643 + delete[] deleteMe->mCameras; deleteMe->mCameras = NULL; 1.644 + delete[] deleteMe->mLights; deleteMe->mLights = NULL; 1.645 + delete[] deleteMe->mMaterials; deleteMe->mMaterials = NULL; 1.646 + delete[] deleteMe->mAnimations; deleteMe->mAnimations = NULL; 1.647 + 1.648 + deleteMe->mRootNode = NULL; 1.649 + 1.650 + // Now we can safely delete the scene 1.651 + delete deleteMe; 1.652 + } 1.653 + 1.654 + // Check flags 1.655 + if (!dest->mNumMeshes || !dest->mNumMaterials) { 1.656 + dest->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; 1.657 + } 1.658 + 1.659 + // We're finished 1.660 +} 1.661 + 1.662 +// ------------------------------------------------------------------------------------------------ 1.663 +// Build a list of unique bones 1.664 +void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash>& asBones, 1.665 + std::vector<aiMesh*>::const_iterator it, 1.666 + std::vector<aiMesh*>::const_iterator end) 1.667 +{ 1.668 + unsigned int iOffset = 0; 1.669 + for (; it != end;++it) { 1.670 + for (unsigned int l = 0; l < (*it)->mNumBones;++l) { 1.671 + aiBone* p = (*it)->mBones[l]; 1.672 + uint32_t itml = SuperFastHash(p->mName.data,(unsigned int)p->mName.length); 1.673 + 1.674 + std::list<BoneWithHash>::iterator it2 = asBones.begin(); 1.675 + std::list<BoneWithHash>::iterator end2 = asBones.end(); 1.676 + 1.677 + for (;it2 != end2;++it2) { 1.678 + if ((*it2).first == itml) { 1.679 + (*it2).pSrcBones.push_back(BoneSrcIndex(p,iOffset)); 1.680 + break; 1.681 + } 1.682 + } 1.683 + if (end2 == it2) { 1.684 + // need to begin a new bone entry 1.685 + asBones.push_back(BoneWithHash()); 1.686 + BoneWithHash& btz = asBones.back(); 1.687 + 1.688 + // setup members 1.689 + btz.first = itml; 1.690 + btz.second = &p->mName; 1.691 + btz.pSrcBones.push_back(BoneSrcIndex(p,iOffset)); 1.692 + } 1.693 + } 1.694 + iOffset += (*it)->mNumVertices; 1.695 + } 1.696 +} 1.697 + 1.698 +// ------------------------------------------------------------------------------------------------ 1.699 +// Merge a list of bones 1.700 +void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it, 1.701 + std::vector<aiMesh*>::const_iterator end) 1.702 +{ 1.703 + ai_assert(NULL != out && !out->mNumBones); 1.704 + 1.705 + // find we need to build an unique list of all bones. 1.706 + // we work with hashes to make the comparisons MUCH faster, 1.707 + // at least if we have many bones. 1.708 + std::list<BoneWithHash> asBones; 1.709 + BuildUniqueBoneList(asBones, it,end); 1.710 + 1.711 + // now create the output bones 1.712 + out->mNumBones = 0; 1.713 + out->mBones = new aiBone*[asBones.size()]; 1.714 + 1.715 + for (std::list<BoneWithHash>::const_iterator it = asBones.begin(),end = asBones.end(); it != end;++it) { 1.716 + // Allocate a bone and setup it's name 1.717 + aiBone* pc = out->mBones[out->mNumBones++] = new aiBone(); 1.718 + pc->mName = aiString( *((*it).second )); 1.719 + 1.720 + std::vector< BoneSrcIndex >::const_iterator wend = (*it).pSrcBones.end(); 1.721 + 1.722 + // Loop through all bones to be joined for this bone 1.723 + for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).pSrcBones.begin(); wmit != wend; ++wmit) { 1.724 + pc->mNumWeights += (*wmit).first->mNumWeights; 1.725 + 1.726 + // NOTE: different offset matrices for bones with equal names 1.727 + // are - at the moment - not handled correctly. 1.728 + if (wmit != (*it).pSrcBones.begin() && pc->mOffsetMatrix != (*wmit).first->mOffsetMatrix) { 1.729 + DefaultLogger::get()->warn("Bones with equal names but different offset matrices can't be joined at the moment"); 1.730 + continue; 1.731 + } 1.732 + pc->mOffsetMatrix = (*wmit).first->mOffsetMatrix; 1.733 + } 1.734 + 1.735 + // Allocate the vertex weight array 1.736 + aiVertexWeight* avw = pc->mWeights = new aiVertexWeight[pc->mNumWeights]; 1.737 + 1.738 + // And copy the final weights - adjust the vertex IDs by the 1.739 + // face index offset of the coresponding mesh. 1.740 + for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).pSrcBones.begin(); wmit != wend; ++wmit) { 1.741 + aiBone* pip = (*wmit).first; 1.742 + for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) { 1.743 + const aiVertexWeight& vfi = pip->mWeights[mp]; 1.744 + avw->mWeight = vfi.mWeight; 1.745 + avw->mVertexId = vfi.mVertexId + (*wmit).second; 1.746 + } 1.747 + } 1.748 + } 1.749 +} 1.750 + 1.751 +// ------------------------------------------------------------------------------------------------ 1.752 +// Merge a list of meshes 1.753 +void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/, 1.754 + std::vector<aiMesh*>::const_iterator begin, 1.755 + std::vector<aiMesh*>::const_iterator end) 1.756 +{ 1.757 + ai_assert(NULL != _out); 1.758 + 1.759 + if (begin == end) { 1.760 + *_out = NULL; // no meshes ... 1.761 + return; 1.762 + } 1.763 + 1.764 + // Allocate the output mesh 1.765 + aiMesh* out = *_out = new aiMesh(); 1.766 + out->mMaterialIndex = (*begin)->mMaterialIndex; 1.767 + 1.768 + // Find out how much output storage we'll need 1.769 + for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { 1.770 + out->mNumVertices += (*it)->mNumVertices; 1.771 + out->mNumFaces += (*it)->mNumFaces; 1.772 + out->mNumBones += (*it)->mNumBones; 1.773 + 1.774 + // combine primitive type flags 1.775 + out->mPrimitiveTypes |= (*it)->mPrimitiveTypes; 1.776 + } 1.777 + 1.778 + if (out->mNumVertices) { 1.779 + aiVector3D* pv2; 1.780 + 1.781 + // copy vertex positions 1.782 + if ((**begin).HasPositions()) { 1.783 + 1.784 + pv2 = out->mVertices = new aiVector3D[out->mNumVertices]; 1.785 + for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { 1.786 + if ((*it)->mVertices) { 1.787 + ::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D)); 1.788 + } 1.789 + else DefaultLogger::get()->warn("JoinMeshes: Positions expected but input mesh contains no positions"); 1.790 + pv2 += (*it)->mNumVertices; 1.791 + } 1.792 + } 1.793 + // copy normals 1.794 + if ((**begin).HasNormals()) { 1.795 + 1.796 + pv2 = out->mNormals = new aiVector3D[out->mNumVertices]; 1.797 + for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { 1.798 + if ((*it)->mNormals) { 1.799 + ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D)); 1.800 + } 1.801 + else DefaultLogger::get()->warn("JoinMeshes: Normals expected but input mesh contains no normals"); 1.802 + pv2 += (*it)->mNumVertices; 1.803 + } 1.804 + } 1.805 + // copy tangents and bitangents 1.806 + if ((**begin).HasTangentsAndBitangents()) { 1.807 + 1.808 + pv2 = out->mTangents = new aiVector3D[out->mNumVertices]; 1.809 + aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices]; 1.810 + 1.811 + for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { 1.812 + if ((*it)->mTangents) { 1.813 + ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D)); 1.814 + ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D)); 1.815 + } 1.816 + else DefaultLogger::get()->warn("JoinMeshes: Tangents expected but input mesh contains no tangents"); 1.817 + pv2 += (*it)->mNumVertices; 1.818 + pv2b += (*it)->mNumVertices; 1.819 + } 1.820 + } 1.821 + // copy texture coordinates 1.822 + unsigned int n = 0; 1.823 + while ((**begin).HasTextureCoords(n)) { 1.824 + out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n]; 1.825 + 1.826 + pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices]; 1.827 + for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { 1.828 + 1.829 + if ((*it)->mTextureCoords[n]) { 1.830 + ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D)); 1.831 + } 1.832 + else DefaultLogger::get()->warn("JoinMeshes: UVs expected but input mesh contains no UVs"); 1.833 + pv2 += (*it)->mNumVertices; 1.834 + } 1.835 + ++n; 1.836 + } 1.837 + // copy vertex colors 1.838 + n = 0; 1.839 + while ((**begin).HasVertexColors(n)) { 1.840 + aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices]; 1.841 + for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { 1.842 + 1.843 + if ((*it)->mColors[n]) { 1.844 + ::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D)); 1.845 + } 1.846 + else DefaultLogger::get()->warn("JoinMeshes: VCs expected but input mesh contains no VCs"); 1.847 + pv2 += (*it)->mNumVertices; 1.848 + } 1.849 + ++n; 1.850 + } 1.851 + } 1.852 + 1.853 + if (out->mNumFaces) // just for safety 1.854 + { 1.855 + // copy faces 1.856 + out->mFaces = new aiFace[out->mNumFaces]; 1.857 + aiFace* pf2 = out->mFaces; 1.858 + 1.859 + unsigned int ofs = 0; 1.860 + for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { 1.861 + for (unsigned int m = 0; m < (*it)->mNumFaces;++m,++pf2) { 1.862 + aiFace& face = (*it)->mFaces[m]; 1.863 + pf2->mNumIndices = face.mNumIndices; 1.864 + pf2->mIndices = face.mIndices; 1.865 + 1.866 + if (ofs) { 1.867 + // add the offset to the vertex 1.868 + for (unsigned int q = 0; q < face.mNumIndices; ++q) 1.869 + face.mIndices[q] += ofs; 1.870 + } 1.871 + face.mIndices = NULL; 1.872 + } 1.873 + ofs += (*it)->mNumVertices; 1.874 + } 1.875 + } 1.876 + 1.877 + // bones - as this is quite lengthy, I moved the code to a separate function 1.878 + if (out->mNumBones) 1.879 + MergeBones(out,begin,end); 1.880 + 1.881 + // delete all source meshes 1.882 + for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) 1.883 + delete *it; 1.884 +} 1.885 + 1.886 +// ------------------------------------------------------------------------------------------------ 1.887 +template <typename Type> 1.888 +inline void CopyPtrArray (Type**& dest, const Type* const * src, unsigned int num) 1.889 +{ 1.890 + if (!num) 1.891 + { 1.892 + dest = NULL; 1.893 + return; 1.894 + } 1.895 + dest = new Type*[num]; 1.896 + for (unsigned int i = 0; i < num;++i) { 1.897 + SceneCombiner::Copy(&dest[i],src[i]); 1.898 + } 1.899 +} 1.900 + 1.901 +// ------------------------------------------------------------------------------------------------ 1.902 +template <typename Type> 1.903 +inline void GetArrayCopy (Type*& dest, unsigned int num ) 1.904 +{ 1.905 + if (!dest)return; 1.906 + Type* old = dest; 1.907 + 1.908 + dest = new Type[num]; 1.909 + ::memcpy(dest, old, sizeof(Type) * num); 1.910 +} 1.911 + 1.912 +// ------------------------------------------------------------------------------------------------ 1.913 +void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) 1.914 +{ 1.915 + // reuse the old scene or allocate a new? 1.916 + if (*_dest) { 1.917 + (*_dest)->~aiScene(); 1.918 + new (*_dest) aiScene(); 1.919 + } 1.920 + else *_dest = new aiScene(); 1.921 + 1.922 + ::memcpy(*_dest,src,sizeof(aiScene)); 1.923 +} 1.924 + 1.925 +// ------------------------------------------------------------------------------------------------ 1.926 +void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) 1.927 +{ 1.928 + ai_assert(NULL != _dest && NULL != src); 1.929 + 1.930 + if (allocate) { 1.931 + *_dest = new aiScene(); 1.932 + } 1.933 + aiScene* dest = *_dest; 1.934 + ai_assert(dest); 1.935 + 1.936 + // copy animations 1.937 + dest->mNumAnimations = src->mNumAnimations; 1.938 + CopyPtrArray(dest->mAnimations,src->mAnimations, 1.939 + dest->mNumAnimations); 1.940 + 1.941 + // copy textures 1.942 + dest->mNumTextures = src->mNumTextures; 1.943 + CopyPtrArray(dest->mTextures,src->mTextures, 1.944 + dest->mNumTextures); 1.945 + 1.946 + // copy materials 1.947 + dest->mNumMaterials = src->mNumMaterials; 1.948 + CopyPtrArray(dest->mMaterials,src->mMaterials, 1.949 + dest->mNumMaterials); 1.950 + 1.951 + // copy lights 1.952 + dest->mNumLights = src->mNumLights; 1.953 + CopyPtrArray(dest->mLights,src->mLights, 1.954 + dest->mNumLights); 1.955 + 1.956 + // copy cameras 1.957 + dest->mNumCameras = src->mNumCameras; 1.958 + CopyPtrArray(dest->mCameras,src->mCameras, 1.959 + dest->mNumCameras); 1.960 + 1.961 + // copy meshes 1.962 + dest->mNumMeshes = src->mNumMeshes; 1.963 + CopyPtrArray(dest->mMeshes,src->mMeshes, 1.964 + dest->mNumMeshes); 1.965 + 1.966 + // now - copy the root node of the scene (deep copy, too) 1.967 + Copy( &dest->mRootNode, src->mRootNode); 1.968 + 1.969 + // and keep the flags ... 1.970 + dest->mFlags = src->mFlags; 1.971 + 1.972 + // source private data might be NULL if the scene is user-allocated (i.e. for use with the export API) 1.973 + ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0; 1.974 +} 1.975 + 1.976 +// ------------------------------------------------------------------------------------------------ 1.977 +void SceneCombiner::Copy (aiMesh** _dest, const aiMesh* src) 1.978 +{ 1.979 + ai_assert(NULL != _dest && NULL != src); 1.980 + 1.981 + aiMesh* dest = *_dest = new aiMesh(); 1.982 + 1.983 + // get a flat copy 1.984 + ::memcpy(dest,src,sizeof(aiMesh)); 1.985 + 1.986 + // and reallocate all arrays 1.987 + GetArrayCopy( dest->mVertices, dest->mNumVertices ); 1.988 + GetArrayCopy( dest->mNormals , dest->mNumVertices ); 1.989 + GetArrayCopy( dest->mTangents, dest->mNumVertices ); 1.990 + GetArrayCopy( dest->mBitangents, dest->mNumVertices ); 1.991 + 1.992 + unsigned int n = 0; 1.993 + while (dest->HasTextureCoords(n)) 1.994 + GetArrayCopy( dest->mTextureCoords[n++], dest->mNumVertices ); 1.995 + 1.996 + n = 0; 1.997 + while (dest->HasVertexColors(n)) 1.998 + GetArrayCopy( dest->mColors[n++], dest->mNumVertices ); 1.999 + 1.1000 + // make a deep copy of all bones 1.1001 + CopyPtrArray(dest->mBones,dest->mBones,dest->mNumBones); 1.1002 + 1.1003 + // make a deep copy of all faces 1.1004 + GetArrayCopy(dest->mFaces,dest->mNumFaces); 1.1005 + for (unsigned int i = 0; i < dest->mNumFaces;++i) 1.1006 + { 1.1007 + aiFace& f = dest->mFaces[i]; 1.1008 + GetArrayCopy(f.mIndices,f.mNumIndices); 1.1009 + } 1.1010 +} 1.1011 + 1.1012 +// ------------------------------------------------------------------------------------------------ 1.1013 +void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) 1.1014 +{ 1.1015 + ai_assert(NULL != _dest && NULL != src); 1.1016 + 1.1017 + aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() ); 1.1018 + dest->mNumAllocated = src->mNumAllocated; 1.1019 + dest->mNumProperties = src->mNumProperties; 1.1020 + dest->mProperties = new aiMaterialProperty* [dest->mNumAllocated]; 1.1021 + 1.1022 + for (unsigned int i = 0; i < dest->mNumProperties;++i) 1.1023 + { 1.1024 + aiMaterialProperty* prop = dest->mProperties[i] = new aiMaterialProperty(); 1.1025 + aiMaterialProperty* sprop = src->mProperties[i]; 1.1026 + 1.1027 + prop->mDataLength = sprop->mDataLength; 1.1028 + prop->mData = new char[prop->mDataLength]; 1.1029 + ::memcpy(prop->mData,sprop->mData,prop->mDataLength); 1.1030 + 1.1031 + prop->mIndex = sprop->mIndex; 1.1032 + prop->mSemantic = sprop->mSemantic; 1.1033 + prop->mKey = sprop->mKey; 1.1034 + prop->mType = sprop->mType; 1.1035 + } 1.1036 +} 1.1037 + 1.1038 +// ------------------------------------------------------------------------------------------------ 1.1039 +void SceneCombiner::Copy (aiTexture** _dest, const aiTexture* src) 1.1040 +{ 1.1041 + ai_assert(NULL != _dest && NULL != src); 1.1042 + 1.1043 + aiTexture* dest = *_dest = new aiTexture(); 1.1044 + 1.1045 + // get a flat copy 1.1046 + ::memcpy(dest,src,sizeof(aiTexture)); 1.1047 + 1.1048 + // and reallocate all arrays. We must do it manually here 1.1049 + const char* old = (const char*)dest->pcData; 1.1050 + if (old) 1.1051 + { 1.1052 + unsigned int cpy; 1.1053 + if (!dest->mHeight)cpy = dest->mWidth; 1.1054 + else cpy = dest->mHeight * dest->mWidth * sizeof(aiTexel); 1.1055 + 1.1056 + if (!cpy) 1.1057 + { 1.1058 + dest->pcData = NULL; 1.1059 + return; 1.1060 + } 1.1061 + // the cast is legal, the aiTexel c'tor does nothing important 1.1062 + dest->pcData = (aiTexel*) new char[cpy]; 1.1063 + ::memcpy(dest->pcData, old, cpy); 1.1064 + } 1.1065 +} 1.1066 + 1.1067 +// ------------------------------------------------------------------------------------------------ 1.1068 +void SceneCombiner::Copy (aiAnimation** _dest, const aiAnimation* src) 1.1069 +{ 1.1070 + ai_assert(NULL != _dest && NULL != src); 1.1071 + 1.1072 + aiAnimation* dest = *_dest = new aiAnimation(); 1.1073 + 1.1074 + // get a flat copy 1.1075 + ::memcpy(dest,src,sizeof(aiAnimation)); 1.1076 + 1.1077 + // and reallocate all arrays 1.1078 + CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels ); 1.1079 +} 1.1080 + 1.1081 +// ------------------------------------------------------------------------------------------------ 1.1082 +void SceneCombiner::Copy (aiNodeAnim** _dest, const aiNodeAnim* src) 1.1083 +{ 1.1084 + ai_assert(NULL != _dest && NULL != src); 1.1085 + 1.1086 + aiNodeAnim* dest = *_dest = new aiNodeAnim(); 1.1087 + 1.1088 + // get a flat copy 1.1089 + ::memcpy(dest,src,sizeof(aiNodeAnim)); 1.1090 + 1.1091 + // and reallocate all arrays 1.1092 + GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys ); 1.1093 + GetArrayCopy( dest->mScalingKeys, dest->mNumScalingKeys ); 1.1094 + GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys ); 1.1095 +} 1.1096 + 1.1097 +// ------------------------------------------------------------------------------------------------ 1.1098 +void SceneCombiner::Copy (aiCamera** _dest,const aiCamera* src) 1.1099 +{ 1.1100 + ai_assert(NULL != _dest && NULL != src); 1.1101 + 1.1102 + aiCamera* dest = *_dest = new aiCamera(); 1.1103 + 1.1104 + // get a flat copy, that's already OK 1.1105 + ::memcpy(dest,src,sizeof(aiCamera)); 1.1106 +} 1.1107 + 1.1108 +// ------------------------------------------------------------------------------------------------ 1.1109 +void SceneCombiner::Copy (aiLight** _dest, const aiLight* src) 1.1110 +{ 1.1111 + ai_assert(NULL != _dest && NULL != src); 1.1112 + 1.1113 + aiLight* dest = *_dest = new aiLight(); 1.1114 + 1.1115 + // get a flat copy, that's already OK 1.1116 + ::memcpy(dest,src,sizeof(aiLight)); 1.1117 +} 1.1118 + 1.1119 +// ------------------------------------------------------------------------------------------------ 1.1120 +void SceneCombiner::Copy (aiBone** _dest, const aiBone* src) 1.1121 +{ 1.1122 + ai_assert(NULL != _dest && NULL != src); 1.1123 + 1.1124 + aiBone* dest = *_dest = new aiBone(); 1.1125 + 1.1126 + // get a flat copy 1.1127 + ::memcpy(dest,src,sizeof(aiBone)); 1.1128 + 1.1129 + // and reallocate all arrays 1.1130 + GetArrayCopy( dest->mWeights, dest->mNumWeights ); 1.1131 +} 1.1132 + 1.1133 +// ------------------------------------------------------------------------------------------------ 1.1134 +void SceneCombiner::Copy (aiNode** _dest, const aiNode* src) 1.1135 +{ 1.1136 + ai_assert(NULL != _dest && NULL != src); 1.1137 + 1.1138 + aiNode* dest = *_dest = new aiNode(); 1.1139 + 1.1140 + // get a flat copy 1.1141 + ::memcpy(dest,src,sizeof(aiNode)); 1.1142 + 1.1143 + // and reallocate all arrays 1.1144 + GetArrayCopy( dest->mMeshes, dest->mNumMeshes ); 1.1145 + CopyPtrArray( dest->mChildren, src->mChildren,dest->mNumChildren); 1.1146 +} 1.1147 + 1.1148 + 1.1149 +}