vrshoot
diff libs/assimp/PretransformVertices.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/PretransformVertices.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,712 @@ 1.4 +/* 1.5 +--------------------------------------------------------------------------- 1.6 +Open Asset Import Library (assimp) 1.7 +--------------------------------------------------------------------------- 1.8 + 1.9 +Copyright (c) 2006-2012, assimp team 1.10 + 1.11 +All rights reserved. 1.12 + 1.13 +Redistribution and use of this software in source and binary forms, 1.14 +with or without modification, are permitted provided that the following 1.15 +conditions are met: 1.16 + 1.17 +* Redistributions of source code must retain the above 1.18 + copyright notice, this list of conditions and the 1.19 + following disclaimer. 1.20 + 1.21 +* Redistributions in binary form must reproduce the above 1.22 + copyright notice, this list of conditions and the 1.23 + following disclaimer in the documentation and/or other 1.24 + materials provided with the distribution. 1.25 + 1.26 +* Neither the name of the assimp team, nor the names of its 1.27 + contributors may be used to endorse or promote products 1.28 + derived from this software without specific prior 1.29 + written permission of the assimp team. 1.30 + 1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.42 +--------------------------------------------------------------------------- 1.43 +*/ 1.44 + 1.45 +/** @file PretransformVertices.cpp 1.46 + * @brief Implementation of the "PretransformVertices" post processing step 1.47 +*/ 1.48 + 1.49 +#include "AssimpPCH.h" 1.50 +#include "PretransformVertices.h" 1.51 +#include "ProcessHelper.h" 1.52 +#include "SceneCombiner.h" 1.53 + 1.54 +using namespace Assimp; 1.55 + 1.56 +// some array offsets 1.57 +#define AI_PTVS_VERTEX 0x0 1.58 +#define AI_PTVS_FACE 0x1 1.59 + 1.60 +// ------------------------------------------------------------------------------------------------ 1.61 +// Constructor to be privately used by Importer 1.62 +PretransformVertices::PretransformVertices() 1.63 +: configKeepHierarchy (false) 1.64 +{ 1.65 +} 1.66 + 1.67 +// ------------------------------------------------------------------------------------------------ 1.68 +// Destructor, private as well 1.69 +PretransformVertices::~PretransformVertices() 1.70 +{ 1.71 + // nothing to do here 1.72 +} 1.73 + 1.74 +// ------------------------------------------------------------------------------------------------ 1.75 +// Returns whether the processing step is present in the given flag field. 1.76 +bool PretransformVertices::IsActive( unsigned int pFlags) const 1.77 +{ 1.78 + return (pFlags & aiProcess_PreTransformVertices) != 0; 1.79 +} 1.80 + 1.81 +// ------------------------------------------------------------------------------------------------ 1.82 +// Setup import configuration 1.83 +void PretransformVertices::SetupProperties(const Importer* pImp) 1.84 +{ 1.85 + // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY and AI_CONFIG_PP_PTV_NORMALIZE 1.86 + configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,0)); 1.87 + configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE,0)); 1.88 +} 1.89 + 1.90 +// ------------------------------------------------------------------------------------------------ 1.91 +// Count the number of nodes 1.92 +unsigned int PretransformVertices::CountNodes( aiNode* pcNode ) 1.93 +{ 1.94 + unsigned int iRet = 1; 1.95 + for (unsigned int i = 0;i < pcNode->mNumChildren;++i) 1.96 + { 1.97 + iRet += CountNodes(pcNode->mChildren[i]); 1.98 + } 1.99 + return iRet; 1.100 +} 1.101 + 1.102 +// ------------------------------------------------------------------------------------------------ 1.103 +// Get a bitwise combination identifying the vertex format of a mesh 1.104 +unsigned int PretransformVertices::GetMeshVFormat(aiMesh* pcMesh) 1.105 +{ 1.106 + // the vertex format is stored in aiMesh::mBones for later retrieval. 1.107 + // there isn't a good reason to compute it a few hundred times 1.108 + // from scratch. The pointer is unused as animations are lost 1.109 + // during PretransformVertices. 1.110 + if (pcMesh->mBones) 1.111 + return (unsigned int)(uint64_t)pcMesh->mBones; 1.112 + 1.113 + 1.114 + const unsigned int iRet = GetMeshVFormatUnique(pcMesh); 1.115 + 1.116 + // store the value for later use 1.117 + pcMesh->mBones = (aiBone**)(uint64_t)iRet; 1.118 + return iRet; 1.119 +} 1.120 + 1.121 +// ------------------------------------------------------------------------------------------------ 1.122 +// Count the number of vertices in the whole scene and a given 1.123 +// material index 1.124 +void PretransformVertices::CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat, 1.125 + unsigned int iVFormat, unsigned int* piFaces, unsigned int* piVertices) 1.126 +{ 1.127 + for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) 1.128 + { 1.129 + aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; 1.130 + if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh)) 1.131 + { 1.132 + *piVertices += pcMesh->mNumVertices; 1.133 + *piFaces += pcMesh->mNumFaces; 1.134 + } 1.135 + } 1.136 + for (unsigned int i = 0;i < pcNode->mNumChildren;++i) 1.137 + { 1.138 + CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat, 1.139 + iVFormat,piFaces,piVertices); 1.140 + } 1.141 +} 1.142 + 1.143 +// ------------------------------------------------------------------------------------------------ 1.144 +// Collect vertex/face data 1.145 +void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat, 1.146 + unsigned int iVFormat, aiMesh* pcMeshOut, 1.147 + unsigned int aiCurrent[2], unsigned int* num_refs) 1.148 +{ 1.149 + // No need to multiply if there's no transformation 1.150 + const bool identity = pcNode->mTransformation.IsIdentity(); 1.151 + for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) 1.152 + { 1.153 + aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; 1.154 + if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh)) 1.155 + { 1.156 + // Decrement mesh reference counter 1.157 + unsigned int& num_ref = num_refs[pcNode->mMeshes[i]]; 1.158 + ai_assert(0 != num_ref); 1.159 + --num_ref; 1.160 + 1.161 + if (identity) { 1.162 + // copy positions without modifying them 1.163 + ::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX], 1.164 + pcMesh->mVertices, 1.165 + pcMesh->mNumVertices * sizeof(aiVector3D)); 1.166 + 1.167 + if (iVFormat & 0x2) { 1.168 + // copy normals without modifying them 1.169 + ::memcpy(pcMeshOut->mNormals + aiCurrent[AI_PTVS_VERTEX], 1.170 + pcMesh->mNormals, 1.171 + pcMesh->mNumVertices * sizeof(aiVector3D)); 1.172 + } 1.173 + if (iVFormat & 0x4) 1.174 + { 1.175 + // copy tangents without modifying them 1.176 + ::memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX], 1.177 + pcMesh->mTangents, 1.178 + pcMesh->mNumVertices * sizeof(aiVector3D)); 1.179 + // copy bitangents without modifying them 1.180 + ::memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX], 1.181 + pcMesh->mBitangents, 1.182 + pcMesh->mNumVertices * sizeof(aiVector3D)); 1.183 + } 1.184 + } 1.185 + else 1.186 + { 1.187 + // copy positions, transform them to worldspace 1.188 + for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { 1.189 + pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcNode->mTransformation * pcMesh->mVertices[n]; 1.190 + } 1.191 + aiMatrix4x4 mWorldIT = pcNode->mTransformation; 1.192 + mWorldIT.Inverse().Transpose(); 1.193 + 1.194 + // TODO: implement Inverse() for aiMatrix3x3 1.195 + aiMatrix3x3 m = aiMatrix3x3(mWorldIT); 1.196 + 1.197 + if (iVFormat & 0x2) 1.198 + { 1.199 + // copy normals, transform them to worldspace 1.200 + for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { 1.201 + pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] = 1.202 + (m * pcMesh->mNormals[n]).Normalize(); 1.203 + } 1.204 + } 1.205 + if (iVFormat & 0x4) 1.206 + { 1.207 + // copy tangents and bitangents, transform them to worldspace 1.208 + for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { 1.209 + pcMeshOut->mTangents [aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mTangents[n]).Normalize(); 1.210 + pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mBitangents[n]).Normalize(); 1.211 + } 1.212 + } 1.213 + } 1.214 + unsigned int p = 0; 1.215 + while (iVFormat & (0x100 << p)) 1.216 + { 1.217 + // copy texture coordinates 1.218 + memcpy(pcMeshOut->mTextureCoords[p] + aiCurrent[AI_PTVS_VERTEX], 1.219 + pcMesh->mTextureCoords[p], 1.220 + pcMesh->mNumVertices * sizeof(aiVector3D)); 1.221 + ++p; 1.222 + } 1.223 + p = 0; 1.224 + while (iVFormat & (0x1000000 << p)) 1.225 + { 1.226 + // copy vertex colors 1.227 + memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX], 1.228 + pcMesh->mColors[p], 1.229 + pcMesh->mNumVertices * sizeof(aiColor4D)); 1.230 + ++p; 1.231 + } 1.232 + // now we need to copy all faces. since we will delete the source mesh afterwards, 1.233 + // we don't need to reallocate the array of indices except if this mesh is 1.234 + // referenced multiple times. 1.235 + for (unsigned int planck = 0;planck < pcMesh->mNumFaces;++planck) 1.236 + { 1.237 + aiFace& f_src = pcMesh->mFaces[planck]; 1.238 + aiFace& f_dst = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck]; 1.239 + 1.240 + const unsigned int num_idx = f_src.mNumIndices; 1.241 + 1.242 + f_dst.mNumIndices = num_idx; 1.243 + 1.244 + unsigned int* pi; 1.245 + if (!num_ref) { /* if last time the mesh is referenced -> no reallocation */ 1.246 + pi = f_dst.mIndices = f_src.mIndices; 1.247 + 1.248 + // offset all vertex indices 1.249 + for (unsigned int hahn = 0; hahn < num_idx;++hahn){ 1.250 + pi[hahn] += aiCurrent[AI_PTVS_VERTEX]; 1.251 + } 1.252 + } 1.253 + else { 1.254 + pi = f_dst.mIndices = new unsigned int[num_idx]; 1.255 + 1.256 + // copy and offset all vertex indices 1.257 + for (unsigned int hahn = 0; hahn < num_idx;++hahn){ 1.258 + pi[hahn] = f_src.mIndices[hahn] + aiCurrent[AI_PTVS_VERTEX]; 1.259 + } 1.260 + } 1.261 + 1.262 + // Update the mPrimitiveTypes member of the mesh 1.263 + switch (pcMesh->mFaces[planck].mNumIndices) 1.264 + { 1.265 + case 0x1: 1.266 + pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POINT; 1.267 + break; 1.268 + case 0x2: 1.269 + pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_LINE; 1.270 + break; 1.271 + case 0x3: 1.272 + pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; 1.273 + break; 1.274 + default: 1.275 + pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POLYGON; 1.276 + break; 1.277 + }; 1.278 + } 1.279 + aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices; 1.280 + aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces; 1.281 + } 1.282 + } 1.283 + 1.284 + // append all children of us 1.285 + for (unsigned int i = 0;i < pcNode->mNumChildren;++i) { 1.286 + CollectData(pcScene,pcNode->mChildren[i],iMat, 1.287 + iVFormat,pcMeshOut,aiCurrent,num_refs); 1.288 + } 1.289 +} 1.290 + 1.291 +// ------------------------------------------------------------------------------------------------ 1.292 +// Get a list of all vertex formats that occur for a given material index 1.293 +// The output list contains duplicate elements 1.294 +void PretransformVertices::GetVFormatList( aiScene* pcScene, unsigned int iMat, 1.295 + std::list<unsigned int>& aiOut) 1.296 +{ 1.297 + for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) 1.298 + { 1.299 + aiMesh* pcMesh = pcScene->mMeshes[ i ]; 1.300 + if (iMat == pcMesh->mMaterialIndex) { 1.301 + aiOut.push_back(GetMeshVFormat(pcMesh)); 1.302 + } 1.303 + } 1.304 +} 1.305 + 1.306 +// ------------------------------------------------------------------------------------------------ 1.307 +// Compute the absolute transformation matrices of each node 1.308 +void PretransformVertices::ComputeAbsoluteTransform( aiNode* pcNode ) 1.309 +{ 1.310 + if (pcNode->mParent) { 1.311 + pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation; 1.312 + } 1.313 + 1.314 + for (unsigned int i = 0;i < pcNode->mNumChildren;++i) { 1.315 + ComputeAbsoluteTransform(pcNode->mChildren[i]); 1.316 + } 1.317 +} 1.318 + 1.319 +// ------------------------------------------------------------------------------------------------ 1.320 +// Apply the node transformation to a mesh 1.321 +void PretransformVertices::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat) 1.322 +{ 1.323 + // Check whether we need to transform the coordinates at all 1.324 + if (!mat.IsIdentity()) { 1.325 + 1.326 + if (mesh->HasPositions()) { 1.327 + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { 1.328 + mesh->mVertices[i] = mat * mesh->mVertices[i]; 1.329 + } 1.330 + } 1.331 + if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { 1.332 + aiMatrix4x4 mWorldIT = mat; 1.333 + mWorldIT.Inverse().Transpose(); 1.334 + 1.335 + // TODO: implement Inverse() for aiMatrix3x3 1.336 + aiMatrix3x3 m = aiMatrix3x3(mWorldIT); 1.337 + 1.338 + if (mesh->HasNormals()) { 1.339 + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { 1.340 + mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize(); 1.341 + } 1.342 + } 1.343 + if (mesh->HasTangentsAndBitangents()) { 1.344 + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { 1.345 + mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); 1.346 + mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize(); 1.347 + } 1.348 + } 1.349 + } 1.350 + } 1.351 +} 1.352 + 1.353 +// ------------------------------------------------------------------------------------------------ 1.354 +// Simple routine to build meshes in worldspace, no further optimization 1.355 +void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in, 1.356 + unsigned int numIn, aiNode* node) 1.357 +{ 1.358 + // NOTE: 1.359 + // aiMesh::mNumBones store original source mesh, or UINT_MAX if not a copy 1.360 + // aiMesh::mBones store reference to abs. transform we multiplied with 1.361 + 1.362 + // process meshes 1.363 + for (unsigned int i = 0; i < node->mNumMeshes;++i) { 1.364 + aiMesh* mesh = in[node->mMeshes[i]]; 1.365 + 1.366 + // check whether we can operate on this mesh 1.367 + if (!mesh->mBones || *reinterpret_cast<aiMatrix4x4*>(mesh->mBones) == node->mTransformation) { 1.368 + // yes, we can. 1.369 + mesh->mBones = reinterpret_cast<aiBone**> (&node->mTransformation); 1.370 + mesh->mNumBones = UINT_MAX; 1.371 + } 1.372 + else { 1.373 + 1.374 + // try to find us in the list of newly created meshes 1.375 + for (unsigned int n = 0; n < out.size(); ++n) { 1.376 + aiMesh* ctz = out[n]; 1.377 + if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast<aiMatrix4x4*>(ctz->mBones) == node->mTransformation) { 1.378 + 1.379 + // ok, use this one. Update node mesh index 1.380 + node->mMeshes[i] = numIn + n; 1.381 + } 1.382 + } 1.383 + if (node->mMeshes[i] < numIn) { 1.384 + // Worst case. Need to operate on a full copy of the mesh 1.385 + DefaultLogger::get()->info("PretransformVertices: Copying mesh due to mismatching transforms"); 1.386 + aiMesh* ntz; 1.387 + 1.388 + const unsigned int tmp = mesh->mNumBones; // 1.389 + mesh->mNumBones = 0; 1.390 + SceneCombiner::Copy(&ntz,mesh); 1.391 + mesh->mNumBones = tmp; 1.392 + 1.393 + ntz->mNumBones = node->mMeshes[i]; 1.394 + ntz->mBones = reinterpret_cast<aiBone**> (&node->mTransformation); 1.395 + 1.396 + out.push_back(ntz); 1.397 + } 1.398 + } 1.399 + } 1.400 + 1.401 + // call children 1.402 + for (unsigned int i = 0; i < node->mNumChildren;++i) 1.403 + BuildWCSMeshes(out,in,numIn,node->mChildren[i]); 1.404 +} 1.405 + 1.406 +// ------------------------------------------------------------------------------------------------ 1.407 +// Reset transformation matrices to identity 1.408 +void PretransformVertices::MakeIdentityTransform(aiNode* nd) 1.409 +{ 1.410 + nd->mTransformation = aiMatrix4x4(); 1.411 + 1.412 + // call children 1.413 + for (unsigned int i = 0; i < nd->mNumChildren;++i) 1.414 + MakeIdentityTransform(nd->mChildren[i]); 1.415 +} 1.416 + 1.417 +// ------------------------------------------------------------------------------------------------ 1.418 +// Build reference counters for all meshes 1.419 +void PretransformVertices::BuildMeshRefCountArray(aiNode* nd, unsigned int * refs) 1.420 +{ 1.421 + for (unsigned int i = 0; i< nd->mNumMeshes;++i) 1.422 + refs[nd->mMeshes[i]]++; 1.423 + 1.424 + // call children 1.425 + for (unsigned int i = 0; i < nd->mNumChildren;++i) 1.426 + BuildMeshRefCountArray(nd->mChildren[i],refs); 1.427 +} 1.428 + 1.429 +// ------------------------------------------------------------------------------------------------ 1.430 +// Executes the post processing step on the given imported data. 1.431 +void PretransformVertices::Execute( aiScene* pScene) 1.432 +{ 1.433 + DefaultLogger::get()->debug("PretransformVerticesProcess begin"); 1.434 + 1.435 + // Return immediately if we have no meshes 1.436 + if (!pScene->mNumMeshes) 1.437 + return; 1.438 + 1.439 + const unsigned int iOldMeshes = pScene->mNumMeshes; 1.440 + const unsigned int iOldAnimationChannels = pScene->mNumAnimations; 1.441 + const unsigned int iOldNodes = CountNodes(pScene->mRootNode); 1.442 + 1.443 + // first compute absolute transformation matrices for all nodes 1.444 + ComputeAbsoluteTransform(pScene->mRootNode); 1.445 + 1.446 + // Delete aiMesh::mBones for all meshes. The bones are 1.447 + // removed during this step and we need the pointer as 1.448 + // temporary storage 1.449 + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { 1.450 + aiMesh* mesh = pScene->mMeshes[i]; 1.451 + 1.452 + for (unsigned int a = 0; a < mesh->mNumBones;++a) 1.453 + delete mesh->mBones[a]; 1.454 + 1.455 + delete[] mesh->mBones; 1.456 + mesh->mBones = NULL; 1.457 + } 1.458 + 1.459 + // now build a list of output meshes 1.460 + std::vector<aiMesh*> apcOutMeshes; 1.461 + 1.462 + // Keep scene hierarchy? It's an easy job in this case ... 1.463 + // we go on and transform all meshes, if one is referenced by nodes 1.464 + // with different absolute transformations a depth copy of the mesh 1.465 + // is required. 1.466 + if( configKeepHierarchy ) { 1.467 + 1.468 + // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones 1.469 + BuildWCSMeshes(apcOutMeshes,pScene->mMeshes,pScene->mNumMeshes, pScene->mRootNode); 1.470 + 1.471 + // ... if new meshes have been generated, append them to the end of the scene 1.472 + if (apcOutMeshes.size() > 0) { 1.473 + aiMesh** npp = new aiMesh*[pScene->mNumMeshes + apcOutMeshes.size()]; 1.474 + 1.475 + memcpy(npp,pScene->mMeshes,sizeof(aiMesh*)*pScene->mNumMeshes); 1.476 + memcpy(npp+pScene->mNumMeshes,&apcOutMeshes[0],sizeof(aiMesh*)*apcOutMeshes.size()); 1.477 + 1.478 + pScene->mNumMeshes += apcOutMeshes.size(); 1.479 + delete[] pScene->mMeshes; pScene->mMeshes = npp; 1.480 + } 1.481 + 1.482 + // now iterate through all meshes and transform them to worldspace 1.483 + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { 1.484 + ApplyTransform(pScene->mMeshes[i],*reinterpret_cast<aiMatrix4x4*>( pScene->mMeshes[i]->mBones )); 1.485 + 1.486 + // prevent improper destruction 1.487 + pScene->mMeshes[i]->mBones = NULL; 1.488 + pScene->mMeshes[i]->mNumBones = 0; 1.489 + } 1.490 + } 1.491 + else { 1.492 + 1.493 + apcOutMeshes.reserve(pScene->mNumMaterials<<1u); 1.494 + std::list<unsigned int> aiVFormats; 1.495 + 1.496 + std::vector<unsigned int> s(pScene->mNumMeshes,0); 1.497 + BuildMeshRefCountArray(pScene->mRootNode,&s[0]); 1.498 + 1.499 + for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { 1.500 + // get the list of all vertex formats for this material 1.501 + aiVFormats.clear(); 1.502 + GetVFormatList(pScene,i,aiVFormats); 1.503 + aiVFormats.sort(); 1.504 + aiVFormats.unique(); 1.505 + for (std::list<unsigned int>::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) { 1.506 + unsigned int iVertices = 0; 1.507 + unsigned int iFaces = 0; 1.508 + CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices); 1.509 + if (0 != iFaces && 0 != iVertices) 1.510 + { 1.511 + apcOutMeshes.push_back(new aiMesh()); 1.512 + aiMesh* pcMesh = apcOutMeshes.back(); 1.513 + pcMesh->mNumFaces = iFaces; 1.514 + pcMesh->mNumVertices = iVertices; 1.515 + pcMesh->mFaces = new aiFace[iFaces]; 1.516 + pcMesh->mVertices = new aiVector3D[iVertices]; 1.517 + pcMesh->mMaterialIndex = i; 1.518 + if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices]; 1.519 + if ((*j) & 0x4) 1.520 + { 1.521 + pcMesh->mTangents = new aiVector3D[iVertices]; 1.522 + pcMesh->mBitangents = new aiVector3D[iVertices]; 1.523 + } 1.524 + iFaces = 0; 1.525 + while ((*j) & (0x100 << iFaces)) 1.526 + { 1.527 + pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices]; 1.528 + if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3; 1.529 + else pcMesh->mNumUVComponents[iFaces] = 2; 1.530 + iFaces++; 1.531 + } 1.532 + iFaces = 0; 1.533 + while ((*j) & (0x1000000 << iFaces)) 1.534 + pcMesh->mColors[iFaces++] = new aiColor4D[iVertices]; 1.535 + 1.536 + // fill the mesh ... 1.537 + unsigned int aiTemp[2] = {0,0}; 1.538 + CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp,&s[0]); 1.539 + } 1.540 + } 1.541 + } 1.542 + 1.543 + // If no meshes are referenced in the node graph it is possible that we get no output meshes. 1.544 + if (apcOutMeshes.empty()) { 1.545 + throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes"); 1.546 + } 1.547 + else 1.548 + { 1.549 + // now delete all meshes in the scene and build a new mesh list 1.550 + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) 1.551 + { 1.552 + aiMesh* mesh = pScene->mMeshes[i]; 1.553 + mesh->mNumBones = 0; 1.554 + mesh->mBones = NULL; 1.555 + 1.556 + // we're reusing the face index arrays. avoid destruction 1.557 + for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { 1.558 + mesh->mFaces[a].mNumIndices = 0; 1.559 + mesh->mFaces[a].mIndices = NULL; 1.560 + } 1.561 + 1.562 + delete mesh; 1.563 + 1.564 + // Invalidate the contents of the old mesh array. We will most 1.565 + // likely have less output meshes now, so the last entries of 1.566 + // the mesh array are not overridden. We set them to NULL to 1.567 + // make sure the developer gets notified when his application 1.568 + // attempts to access these fields ... 1.569 + mesh = NULL; 1.570 + } 1.571 + 1.572 + // It is impossible that we have more output meshes than 1.573 + // input meshes, so we can easily reuse the old mesh array 1.574 + pScene->mNumMeshes = (unsigned int)apcOutMeshes.size(); 1.575 + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { 1.576 + pScene->mMeshes[i] = apcOutMeshes[i]; 1.577 + } 1.578 + } 1.579 + } 1.580 + 1.581 + // remove all animations from the scene 1.582 + for (unsigned int i = 0; i < pScene->mNumAnimations;++i) 1.583 + delete pScene->mAnimations[i]; 1.584 + delete[] pScene->mAnimations; 1.585 + 1.586 + pScene->mAnimations = NULL; 1.587 + pScene->mNumAnimations = 0; 1.588 + 1.589 + // --- we need to keep all cameras and lights 1.590 + for (unsigned int i = 0; i < pScene->mNumCameras;++i) 1.591 + { 1.592 + aiCamera* cam = pScene->mCameras[i]; 1.593 + const aiNode* nd = pScene->mRootNode->FindNode(cam->mName); 1.594 + ai_assert(NULL != nd); 1.595 + 1.596 + // multiply all properties of the camera with the absolute 1.597 + // transformation of the corresponding node 1.598 + cam->mPosition = nd->mTransformation * cam->mPosition; 1.599 + cam->mLookAt = aiMatrix3x3( nd->mTransformation ) * cam->mLookAt; 1.600 + cam->mUp = aiMatrix3x3( nd->mTransformation ) * cam->mUp; 1.601 + } 1.602 + 1.603 + for (unsigned int i = 0; i < pScene->mNumLights;++i) 1.604 + { 1.605 + aiLight* l = pScene->mLights[i]; 1.606 + const aiNode* nd = pScene->mRootNode->FindNode(l->mName); 1.607 + ai_assert(NULL != nd); 1.608 + 1.609 + // multiply all properties of the camera with the absolute 1.610 + // transformation of the corresponding node 1.611 + l->mPosition = nd->mTransformation * l->mPosition; 1.612 + l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection; 1.613 + } 1.614 + 1.615 + if( !configKeepHierarchy ) { 1.616 + 1.617 + // now delete all nodes in the scene and build a new 1.618 + // flat node graph with a root node and some level 1 children 1.619 + delete pScene->mRootNode; 1.620 + pScene->mRootNode = new aiNode(); 1.621 + pScene->mRootNode->mName.Set("<dummy_root>"); 1.622 + 1.623 + if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras) 1.624 + { 1.625 + pScene->mRootNode->mNumMeshes = 1; 1.626 + pScene->mRootNode->mMeshes = new unsigned int[1]; 1.627 + pScene->mRootNode->mMeshes[0] = 0; 1.628 + } 1.629 + else 1.630 + { 1.631 + pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras; 1.632 + aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren]; 1.633 + 1.634 + // generate mesh nodes 1.635 + for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes) 1.636 + { 1.637 + aiNode* pcNode = *nodes = new aiNode(); 1.638 + pcNode->mParent = pScene->mRootNode; 1.639 + pcNode->mName.length = ::sprintf(pcNode->mName.data,"mesh_%i",i); 1.640 + 1.641 + // setup mesh indices 1.642 + pcNode->mNumMeshes = 1; 1.643 + pcNode->mMeshes = new unsigned int[1]; 1.644 + pcNode->mMeshes[0] = i; 1.645 + } 1.646 + // generate light nodes 1.647 + for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes) 1.648 + { 1.649 + aiNode* pcNode = *nodes = new aiNode(); 1.650 + pcNode->mParent = pScene->mRootNode; 1.651 + pcNode->mName.length = ::sprintf(pcNode->mName.data,"light_%i",i); 1.652 + pScene->mLights[i]->mName = pcNode->mName; 1.653 + } 1.654 + // generate camera nodes 1.655 + for (unsigned int i = 0; i < pScene->mNumCameras;++i,++nodes) 1.656 + { 1.657 + aiNode* pcNode = *nodes = new aiNode(); 1.658 + pcNode->mParent = pScene->mRootNode; 1.659 + pcNode->mName.length = ::sprintf(pcNode->mName.data,"cam_%i",i); 1.660 + pScene->mCameras[i]->mName = pcNode->mName; 1.661 + } 1.662 + } 1.663 + } 1.664 + else { 1.665 + // ... and finally set the transformation matrix of all nodes to identity 1.666 + MakeIdentityTransform(pScene->mRootNode); 1.667 + } 1.668 + 1.669 + if (configNormalize) { 1.670 + // compute the boundary of all meshes 1.671 + aiVector3D min,max; 1.672 + MinMaxChooser<aiVector3D> ()(min,max); 1.673 + 1.674 + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { 1.675 + aiMesh* m = pScene->mMeshes[a]; 1.676 + for (unsigned int i = 0; i < m->mNumVertices;++i) { 1.677 + min = std::min(m->mVertices[i],min); 1.678 + max = std::max(m->mVertices[i],max); 1.679 + } 1.680 + } 1.681 + 1.682 + // find the dominant axis 1.683 + aiVector3D d = max-min; 1.684 + const float div = std::max(d.x,std::max(d.y,d.z))*0.5f; 1.685 + 1.686 + d = min+d*0.5f; 1.687 + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { 1.688 + aiMesh* m = pScene->mMeshes[a]; 1.689 + for (unsigned int i = 0; i < m->mNumVertices;++i) { 1.690 + m->mVertices[i] = (m->mVertices[i]-d)/div; 1.691 + } 1.692 + } 1.693 + } 1.694 + 1.695 + // print statistics 1.696 + if (!DefaultLogger::isNullLogger()) 1.697 + { 1.698 + char buffer[4096]; 1.699 + 1.700 + DefaultLogger::get()->debug("PretransformVerticesProcess finished"); 1.701 + 1.702 + sprintf(buffer,"Removed %i nodes and %i animation channels (%i output nodes)", 1.703 + iOldNodes,iOldAnimationChannels,CountNodes(pScene->mRootNode)); 1.704 + DefaultLogger::get()->info(buffer); 1.705 + 1.706 + sprintf(buffer,"Kept %i lights and %i cameras", 1.707 + pScene->mNumLights,pScene->mNumCameras); 1.708 + DefaultLogger::get()->info(buffer); 1.709 + 1.710 + sprintf(buffer,"Moved %i meshes to WCS (number of output meshes: %i)", 1.711 + iOldMeshes,pScene->mNumMeshes); 1.712 + DefaultLogger::get()->info(buffer); 1.713 + } 1.714 +} 1.715 +