vrshoot
diff libs/assimp/SortByPTypeProcess.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/SortByPTypeProcess.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,405 @@ 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 Implementation of the DeterminePTypeHelperProcess and 1.46 + * SortByPTypeProcess post-process steps. 1.47 +*/ 1.48 + 1.49 +#include "AssimpPCH.h" 1.50 + 1.51 +// internal headers 1.52 +#include "ProcessHelper.h" 1.53 +#include "SortByPTypeProcess.h" 1.54 + 1.55 +using namespace Assimp; 1.56 + 1.57 +// ------------------------------------------------------------------------------------------------ 1.58 +// Constructor to be privately used by Importer 1.59 +SortByPTypeProcess::SortByPTypeProcess() 1.60 +{ 1.61 + configRemoveMeshes = 0; 1.62 +} 1.63 + 1.64 +// ------------------------------------------------------------------------------------------------ 1.65 +// Destructor, private as well 1.66 +SortByPTypeProcess::~SortByPTypeProcess() 1.67 +{ 1.68 + // nothing to do here 1.69 +} 1.70 + 1.71 +// ------------------------------------------------------------------------------------------------ 1.72 +// Returns whether the processing step is present in the given flag field. 1.73 +bool SortByPTypeProcess::IsActive( unsigned int pFlags) const 1.74 +{ 1.75 + return (pFlags & aiProcess_SortByPType) != 0; 1.76 +} 1.77 + 1.78 +// ------------------------------------------------------------------------------------------------ 1.79 +void SortByPTypeProcess::SetupProperties(const Importer* pImp) 1.80 +{ 1.81 + configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0); 1.82 +} 1.83 + 1.84 +// ------------------------------------------------------------------------------------------------ 1.85 +// Update changed meshes in all nodes 1.86 +void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node) 1.87 +{ 1.88 +// std::vector<unsigned int>::const_iterator it; 1.89 + 1.90 + if (node->mNumMeshes) 1.91 + { 1.92 + unsigned int newSize = 0; 1.93 + for (unsigned int m = 0; m< node->mNumMeshes; ++m) 1.94 + { 1.95 + unsigned int add = node->mMeshes[m]<<2; 1.96 + for (unsigned int i = 0; i < 4;++i) 1.97 + { 1.98 + if (UINT_MAX != replaceMeshIndex[add+i])++newSize; 1.99 + } 1.100 + } 1.101 + if (!newSize) 1.102 + { 1.103 + delete[] node->mMeshes; 1.104 + node->mNumMeshes = 0; 1.105 + node->mMeshes = NULL; 1.106 + } 1.107 + else 1.108 + { 1.109 + // Try to reuse the old array if possible 1.110 + unsigned int* newMeshes = (newSize > node->mNumMeshes 1.111 + ? new unsigned int[newSize] : node->mMeshes); 1.112 + 1.113 + for (unsigned int m = 0; m< node->mNumMeshes; ++m) 1.114 + { 1.115 + unsigned int add = node->mMeshes[m]<<2; 1.116 + for (unsigned int i = 0; i < 4;++i) 1.117 + { 1.118 + if (UINT_MAX != replaceMeshIndex[add+i]) 1.119 + *newMeshes++ = replaceMeshIndex[add+i]; 1.120 + } 1.121 + } 1.122 + if (newSize > node->mNumMeshes) 1.123 + delete[] node->mMeshes; 1.124 + 1.125 + node->mMeshes = newMeshes-(node->mNumMeshes = newSize); 1.126 + } 1.127 + } 1.128 + 1.129 + // call all subnodes recursively 1.130 + for (unsigned int m = 0; m < node->mNumChildren; ++m) 1.131 + UpdateNodes(replaceMeshIndex,node->mChildren[m]); 1.132 +} 1.133 + 1.134 +// ------------------------------------------------------------------------------------------------ 1.135 +// Executes the post processing step on the given imported data. 1.136 +void SortByPTypeProcess::Execute( aiScene* pScene) 1.137 +{ 1.138 + if (!pScene->mNumMeshes) 1.139 + { 1.140 + DefaultLogger::get()->debug("SortByPTypeProcess skipped, there are no meshes"); 1.141 + return; 1.142 + } 1.143 + 1.144 + DefaultLogger::get()->debug("SortByPTypeProcess begin"); 1.145 + 1.146 + unsigned int aiNumMeshesPerPType[4] = {0,0,0,0}; 1.147 + 1.148 + std::vector<aiMesh*> outMeshes; 1.149 + outMeshes.reserve(pScene->mNumMeshes<<1u); 1.150 + 1.151 + bool bAnyChanges = false; 1.152 + 1.153 + std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX); 1.154 + std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin(); 1.155 + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) 1.156 + { 1.157 + aiMesh* mesh = pScene->mMeshes[i]; 1.158 + ai_assert(0 != mesh->mPrimitiveTypes); 1.159 + 1.160 + // if there's just one primitive type in the mesh there's nothing to do for us 1.161 + unsigned int num = 0; 1.162 + if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) 1.163 + { 1.164 + ++aiNumMeshesPerPType[0]; 1.165 + ++num; 1.166 + } 1.167 + if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) 1.168 + { 1.169 + ++aiNumMeshesPerPType[1]; 1.170 + ++num; 1.171 + } 1.172 + if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) 1.173 + { 1.174 + ++aiNumMeshesPerPType[2]; 1.175 + ++num; 1.176 + } 1.177 + if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) 1.178 + { 1.179 + ++aiNumMeshesPerPType[3]; 1.180 + ++num; 1.181 + } 1.182 + 1.183 + if (1 == num) 1.184 + { 1.185 + if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) 1.186 + { 1.187 + *meshIdx = (unsigned int) outMeshes.size(); 1.188 + outMeshes.push_back(mesh); 1.189 + } 1.190 + else bAnyChanges = true; 1.191 + 1.192 + meshIdx += 4; 1.193 + continue; 1.194 + } 1.195 + bAnyChanges = true; 1.196 + 1.197 + // reuse our current mesh arrays for the submesh 1.198 + // with the largest numer of primitives 1.199 + unsigned int aiNumPerPType[4] = {0,0,0,0}; 1.200 + aiFace* pFirstFace = mesh->mFaces; 1.201 + aiFace* const pLastFace = pFirstFace + mesh->mNumFaces; 1.202 + 1.203 + unsigned int numPolyVerts = 0; 1.204 + for (;pFirstFace != pLastFace; ++pFirstFace) 1.205 + { 1.206 + if (pFirstFace->mNumIndices <= 3) 1.207 + ++aiNumPerPType[pFirstFace->mNumIndices-1]; 1.208 + else 1.209 + { 1.210 + ++aiNumPerPType[3]; 1.211 + numPolyVerts += pFirstFace-> mNumIndices; 1.212 + } 1.213 + } 1.214 + 1.215 + VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh); 1.216 + for (unsigned int real = 0; real < 4; ++real,++meshIdx) 1.217 + { 1.218 + if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real)) 1.219 + { 1.220 + continue; 1.221 + } 1.222 + 1.223 + *meshIdx = (unsigned int) outMeshes.size(); 1.224 + outMeshes.push_back(new aiMesh()); 1.225 + aiMesh* out = outMeshes.back(); 1.226 + 1.227 + // the name carries the adjacency information between the meshes 1.228 + out->mName = mesh->mName; 1.229 + 1.230 + // copy data members 1.231 + out->mPrimitiveTypes = 1u << real; 1.232 + out->mMaterialIndex = mesh->mMaterialIndex; 1.233 + 1.234 + // allocate output storage 1.235 + out->mNumFaces = aiNumPerPType[real]; 1.236 + aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces]; 1.237 + 1.238 + out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1)); 1.239 + 1.240 + aiVector3D *vert(NULL), *nor(NULL), *tan(NULL), *bit(NULL); 1.241 + aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS]; 1.242 + aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS]; 1.243 + 1.244 + if (mesh->mVertices) 1.245 + vert = out->mVertices = new aiVector3D[out->mNumVertices]; 1.246 + 1.247 + if (mesh->mNormals) 1.248 + nor = out->mNormals = new aiVector3D[out->mNumVertices]; 1.249 + 1.250 + if (mesh->mTangents) 1.251 + { 1.252 + tan = out->mTangents = new aiVector3D[out->mNumVertices]; 1.253 + bit = out->mBitangents = new aiVector3D[out->mNumVertices]; 1.254 + } 1.255 + 1.256 + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) 1.257 + { 1.258 + if (mesh->mTextureCoords[i]) 1.259 + uv[i] = out->mTextureCoords[i] = new aiVector3D[out->mNumVertices]; 1.260 + else uv[i] = NULL; 1.261 + 1.262 + out->mNumUVComponents[i] = mesh->mNumUVComponents[i]; 1.263 + } 1.264 + 1.265 + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS;++i) 1.266 + { 1.267 + if (mesh->mColors[i]) 1.268 + cols[i] = out->mColors[i] = new aiColor4D[out->mNumVertices]; 1.269 + else cols[i] = NULL; 1.270 + } 1.271 + 1.272 + typedef std::vector< aiVertexWeight > TempBoneInfo; 1.273 + std::vector< TempBoneInfo > tempBones(mesh->mNumBones); 1.274 + 1.275 + // try to guess how much storage we'll need 1.276 + for (unsigned int q = 0; q < mesh->mNumBones;++q) 1.277 + { 1.278 + tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1)); 1.279 + } 1.280 + 1.281 + unsigned int outIdx = 0; 1.282 + for (unsigned int m = 0; m < mesh->mNumFaces; ++m) 1.283 + { 1.284 + aiFace& in = mesh->mFaces[m]; 1.285 + if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1)) 1.286 + { 1.287 + continue; 1.288 + } 1.289 + 1.290 + outFaces->mNumIndices = in.mNumIndices; 1.291 + outFaces->mIndices = in.mIndices; 1.292 + 1.293 + for (unsigned int q = 0; q < in.mNumIndices; ++q) 1.294 + { 1.295 + register unsigned int idx = in.mIndices[q]; 1.296 + 1.297 + // process all bones of this index 1.298 + if (avw) 1.299 + { 1.300 + VertexWeightTable& tbl = avw[idx]; 1.301 + for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end(); 1.302 + it != end; ++it) 1.303 + { 1.304 + tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) ); 1.305 + } 1.306 + } 1.307 + 1.308 + if (vert) 1.309 + { 1.310 + *vert++ = mesh->mVertices[idx]; 1.311 + //mesh->mVertices[idx].x = get_qnan(); 1.312 + } 1.313 + if (nor )*nor++ = mesh->mNormals[idx]; 1.314 + if (tan ) 1.315 + { 1.316 + *tan++ = mesh->mTangents[idx]; 1.317 + *bit++ = mesh->mBitangents[idx]; 1.318 + } 1.319 + 1.320 + for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) 1.321 + { 1.322 + if (!uv[pp])break; 1.323 + *uv[pp]++ = mesh->mTextureCoords[pp][idx]; 1.324 + } 1.325 + 1.326 + for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) 1.327 + { 1.328 + if (!cols[pp])break; 1.329 + *cols[pp]++ = mesh->mColors[pp][idx]; 1.330 + } 1.331 + 1.332 + in.mIndices[q] = outIdx++; 1.333 + } 1.334 + 1.335 + in.mIndices = NULL; 1.336 + ++outFaces; 1.337 + } 1.338 + ai_assert(outFaces == out->mFaces + out->mNumFaces); 1.339 + 1.340 + // now generate output bones 1.341 + for (unsigned int q = 0; q < mesh->mNumBones;++q) 1.342 + if (!tempBones[q].empty())++out->mNumBones; 1.343 + 1.344 + if (out->mNumBones) 1.345 + { 1.346 + out->mBones = new aiBone*[out->mNumBones]; 1.347 + for (unsigned int q = 0, real = 0; q < mesh->mNumBones;++q) 1.348 + { 1.349 + TempBoneInfo& in = tempBones[q]; 1.350 + if (in.empty())continue; 1.351 + 1.352 + aiBone* srcBone = mesh->mBones[q]; 1.353 + aiBone* bone = out->mBones[real] = new aiBone(); 1.354 + 1.355 + bone->mName = srcBone->mName; 1.356 + bone->mOffsetMatrix = srcBone->mOffsetMatrix; 1.357 + 1.358 + bone->mNumWeights = (unsigned int)in.size(); 1.359 + bone->mWeights = new aiVertexWeight[bone->mNumWeights]; 1.360 + 1.361 + ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight)); 1.362 + 1.363 + ++real; 1.364 + } 1.365 + } 1.366 + } 1.367 + 1.368 + // delete the per-vertex bone weights table 1.369 + delete[] avw; 1.370 + 1.371 + // delete the input mesh 1.372 + delete mesh; 1.373 + } 1.374 + 1.375 + if (outMeshes.empty()) 1.376 + { 1.377 + // This should not occur 1.378 + throw DeadlyImportError("No meshes remaining"); 1.379 + } 1.380 + 1.381 + // If we added at least one mesh process all nodes in the node 1.382 + // graph and update their respective mesh indices. 1.383 + if (bAnyChanges) 1.384 + { 1.385 + UpdateNodes(replaceMeshIndex,pScene->mRootNode); 1.386 + } 1.387 + 1.388 + if (outMeshes.size() != pScene->mNumMeshes) 1.389 + { 1.390 + delete[] pScene->mMeshes; 1.391 + pScene->mNumMeshes = (unsigned int)outMeshes.size(); 1.392 + pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; 1.393 + } 1.394 + ::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*)); 1.395 + 1.396 + if (!DefaultLogger::isNullLogger()) 1.397 + { 1.398 + char buffer[1024]; 1.399 + ::sprintf(buffer,"Points: %i%s, Lines: %i%s, Triangles: %i%s, Polygons: %i%s (Meshes, X = removed)", 1.400 + aiNumMeshesPerPType[0], (configRemoveMeshes & aiPrimitiveType_POINT ? "X" : ""), 1.401 + aiNumMeshesPerPType[1], (configRemoveMeshes & aiPrimitiveType_LINE ? "X" : ""), 1.402 + aiNumMeshesPerPType[2], (configRemoveMeshes & aiPrimitiveType_TRIANGLE ? "X" : ""), 1.403 + aiNumMeshesPerPType[3], (configRemoveMeshes & aiPrimitiveType_POLYGON ? "X" : "")); 1.404 + DefaultLogger::get()->info(buffer); 1.405 + DefaultLogger::get()->debug("SortByPTypeProcess finished"); 1.406 + } 1.407 +} 1.408 +