vrshoot

annotate 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
rev   line source
nuclear@0 1 /*
nuclear@0 2 ---------------------------------------------------------------------------
nuclear@0 3 Open Asset Import Library (assimp)
nuclear@0 4 ---------------------------------------------------------------------------
nuclear@0 5
nuclear@0 6 Copyright (c) 2006-2012, assimp team
nuclear@0 7
nuclear@0 8 All rights reserved.
nuclear@0 9
nuclear@0 10 Redistribution and use of this software in source and binary forms,
nuclear@0 11 with or without modification, are permitted provided that the following
nuclear@0 12 conditions are met:
nuclear@0 13
nuclear@0 14 * Redistributions of source code must retain the above
nuclear@0 15 copyright notice, this list of conditions and the
nuclear@0 16 following disclaimer.
nuclear@0 17
nuclear@0 18 * Redistributions in binary form must reproduce the above
nuclear@0 19 copyright notice, this list of conditions and the
nuclear@0 20 following disclaimer in the documentation and/or other
nuclear@0 21 materials provided with the distribution.
nuclear@0 22
nuclear@0 23 * Neither the name of the assimp team, nor the names of its
nuclear@0 24 contributors may be used to endorse or promote products
nuclear@0 25 derived from this software without specific prior
nuclear@0 26 written permission of the assimp team.
nuclear@0 27
nuclear@0 28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 39 ---------------------------------------------------------------------------
nuclear@0 40 */
nuclear@0 41
nuclear@0 42 /** @file Implementation of the DeterminePTypeHelperProcess and
nuclear@0 43 * SortByPTypeProcess post-process steps.
nuclear@0 44 */
nuclear@0 45
nuclear@0 46 #include "AssimpPCH.h"
nuclear@0 47
nuclear@0 48 // internal headers
nuclear@0 49 #include "ProcessHelper.h"
nuclear@0 50 #include "SortByPTypeProcess.h"
nuclear@0 51
nuclear@0 52 using namespace Assimp;
nuclear@0 53
nuclear@0 54 // ------------------------------------------------------------------------------------------------
nuclear@0 55 // Constructor to be privately used by Importer
nuclear@0 56 SortByPTypeProcess::SortByPTypeProcess()
nuclear@0 57 {
nuclear@0 58 configRemoveMeshes = 0;
nuclear@0 59 }
nuclear@0 60
nuclear@0 61 // ------------------------------------------------------------------------------------------------
nuclear@0 62 // Destructor, private as well
nuclear@0 63 SortByPTypeProcess::~SortByPTypeProcess()
nuclear@0 64 {
nuclear@0 65 // nothing to do here
nuclear@0 66 }
nuclear@0 67
nuclear@0 68 // ------------------------------------------------------------------------------------------------
nuclear@0 69 // Returns whether the processing step is present in the given flag field.
nuclear@0 70 bool SortByPTypeProcess::IsActive( unsigned int pFlags) const
nuclear@0 71 {
nuclear@0 72 return (pFlags & aiProcess_SortByPType) != 0;
nuclear@0 73 }
nuclear@0 74
nuclear@0 75 // ------------------------------------------------------------------------------------------------
nuclear@0 76 void SortByPTypeProcess::SetupProperties(const Importer* pImp)
nuclear@0 77 {
nuclear@0 78 configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0);
nuclear@0 79 }
nuclear@0 80
nuclear@0 81 // ------------------------------------------------------------------------------------------------
nuclear@0 82 // Update changed meshes in all nodes
nuclear@0 83 void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node)
nuclear@0 84 {
nuclear@0 85 // std::vector<unsigned int>::const_iterator it;
nuclear@0 86
nuclear@0 87 if (node->mNumMeshes)
nuclear@0 88 {
nuclear@0 89 unsigned int newSize = 0;
nuclear@0 90 for (unsigned int m = 0; m< node->mNumMeshes; ++m)
nuclear@0 91 {
nuclear@0 92 unsigned int add = node->mMeshes[m]<<2;
nuclear@0 93 for (unsigned int i = 0; i < 4;++i)
nuclear@0 94 {
nuclear@0 95 if (UINT_MAX != replaceMeshIndex[add+i])++newSize;
nuclear@0 96 }
nuclear@0 97 }
nuclear@0 98 if (!newSize)
nuclear@0 99 {
nuclear@0 100 delete[] node->mMeshes;
nuclear@0 101 node->mNumMeshes = 0;
nuclear@0 102 node->mMeshes = NULL;
nuclear@0 103 }
nuclear@0 104 else
nuclear@0 105 {
nuclear@0 106 // Try to reuse the old array if possible
nuclear@0 107 unsigned int* newMeshes = (newSize > node->mNumMeshes
nuclear@0 108 ? new unsigned int[newSize] : node->mMeshes);
nuclear@0 109
nuclear@0 110 for (unsigned int m = 0; m< node->mNumMeshes; ++m)
nuclear@0 111 {
nuclear@0 112 unsigned int add = node->mMeshes[m]<<2;
nuclear@0 113 for (unsigned int i = 0; i < 4;++i)
nuclear@0 114 {
nuclear@0 115 if (UINT_MAX != replaceMeshIndex[add+i])
nuclear@0 116 *newMeshes++ = replaceMeshIndex[add+i];
nuclear@0 117 }
nuclear@0 118 }
nuclear@0 119 if (newSize > node->mNumMeshes)
nuclear@0 120 delete[] node->mMeshes;
nuclear@0 121
nuclear@0 122 node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
nuclear@0 123 }
nuclear@0 124 }
nuclear@0 125
nuclear@0 126 // call all subnodes recursively
nuclear@0 127 for (unsigned int m = 0; m < node->mNumChildren; ++m)
nuclear@0 128 UpdateNodes(replaceMeshIndex,node->mChildren[m]);
nuclear@0 129 }
nuclear@0 130
nuclear@0 131 // ------------------------------------------------------------------------------------------------
nuclear@0 132 // Executes the post processing step on the given imported data.
nuclear@0 133 void SortByPTypeProcess::Execute( aiScene* pScene)
nuclear@0 134 {
nuclear@0 135 if (!pScene->mNumMeshes)
nuclear@0 136 {
nuclear@0 137 DefaultLogger::get()->debug("SortByPTypeProcess skipped, there are no meshes");
nuclear@0 138 return;
nuclear@0 139 }
nuclear@0 140
nuclear@0 141 DefaultLogger::get()->debug("SortByPTypeProcess begin");
nuclear@0 142
nuclear@0 143 unsigned int aiNumMeshesPerPType[4] = {0,0,0,0};
nuclear@0 144
nuclear@0 145 std::vector<aiMesh*> outMeshes;
nuclear@0 146 outMeshes.reserve(pScene->mNumMeshes<<1u);
nuclear@0 147
nuclear@0 148 bool bAnyChanges = false;
nuclear@0 149
nuclear@0 150 std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX);
nuclear@0 151 std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
nuclear@0 152 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
nuclear@0 153 {
nuclear@0 154 aiMesh* mesh = pScene->mMeshes[i];
nuclear@0 155 ai_assert(0 != mesh->mPrimitiveTypes);
nuclear@0 156
nuclear@0 157 // if there's just one primitive type in the mesh there's nothing to do for us
nuclear@0 158 unsigned int num = 0;
nuclear@0 159 if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT)
nuclear@0 160 {
nuclear@0 161 ++aiNumMeshesPerPType[0];
nuclear@0 162 ++num;
nuclear@0 163 }
nuclear@0 164 if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE)
nuclear@0 165 {
nuclear@0 166 ++aiNumMeshesPerPType[1];
nuclear@0 167 ++num;
nuclear@0 168 }
nuclear@0 169 if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)
nuclear@0 170 {
nuclear@0 171 ++aiNumMeshesPerPType[2];
nuclear@0 172 ++num;
nuclear@0 173 }
nuclear@0 174 if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)
nuclear@0 175 {
nuclear@0 176 ++aiNumMeshesPerPType[3];
nuclear@0 177 ++num;
nuclear@0 178 }
nuclear@0 179
nuclear@0 180 if (1 == num)
nuclear@0 181 {
nuclear@0 182 if (!(configRemoveMeshes & mesh->mPrimitiveTypes))
nuclear@0 183 {
nuclear@0 184 *meshIdx = (unsigned int) outMeshes.size();
nuclear@0 185 outMeshes.push_back(mesh);
nuclear@0 186 }
nuclear@0 187 else bAnyChanges = true;
nuclear@0 188
nuclear@0 189 meshIdx += 4;
nuclear@0 190 continue;
nuclear@0 191 }
nuclear@0 192 bAnyChanges = true;
nuclear@0 193
nuclear@0 194 // reuse our current mesh arrays for the submesh
nuclear@0 195 // with the largest numer of primitives
nuclear@0 196 unsigned int aiNumPerPType[4] = {0,0,0,0};
nuclear@0 197 aiFace* pFirstFace = mesh->mFaces;
nuclear@0 198 aiFace* const pLastFace = pFirstFace + mesh->mNumFaces;
nuclear@0 199
nuclear@0 200 unsigned int numPolyVerts = 0;
nuclear@0 201 for (;pFirstFace != pLastFace; ++pFirstFace)
nuclear@0 202 {
nuclear@0 203 if (pFirstFace->mNumIndices <= 3)
nuclear@0 204 ++aiNumPerPType[pFirstFace->mNumIndices-1];
nuclear@0 205 else
nuclear@0 206 {
nuclear@0 207 ++aiNumPerPType[3];
nuclear@0 208 numPolyVerts += pFirstFace-> mNumIndices;
nuclear@0 209 }
nuclear@0 210 }
nuclear@0 211
nuclear@0 212 VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh);
nuclear@0 213 for (unsigned int real = 0; real < 4; ++real,++meshIdx)
nuclear@0 214 {
nuclear@0 215 if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real))
nuclear@0 216 {
nuclear@0 217 continue;
nuclear@0 218 }
nuclear@0 219
nuclear@0 220 *meshIdx = (unsigned int) outMeshes.size();
nuclear@0 221 outMeshes.push_back(new aiMesh());
nuclear@0 222 aiMesh* out = outMeshes.back();
nuclear@0 223
nuclear@0 224 // the name carries the adjacency information between the meshes
nuclear@0 225 out->mName = mesh->mName;
nuclear@0 226
nuclear@0 227 // copy data members
nuclear@0 228 out->mPrimitiveTypes = 1u << real;
nuclear@0 229 out->mMaterialIndex = mesh->mMaterialIndex;
nuclear@0 230
nuclear@0 231 // allocate output storage
nuclear@0 232 out->mNumFaces = aiNumPerPType[real];
nuclear@0 233 aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces];
nuclear@0 234
nuclear@0 235 out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1));
nuclear@0 236
nuclear@0 237 aiVector3D *vert(NULL), *nor(NULL), *tan(NULL), *bit(NULL);
nuclear@0 238 aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS];
nuclear@0 239 aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS];
nuclear@0 240
nuclear@0 241 if (mesh->mVertices)
nuclear@0 242 vert = out->mVertices = new aiVector3D[out->mNumVertices];
nuclear@0 243
nuclear@0 244 if (mesh->mNormals)
nuclear@0 245 nor = out->mNormals = new aiVector3D[out->mNumVertices];
nuclear@0 246
nuclear@0 247 if (mesh->mTangents)
nuclear@0 248 {
nuclear@0 249 tan = out->mTangents = new aiVector3D[out->mNumVertices];
nuclear@0 250 bit = out->mBitangents = new aiVector3D[out->mNumVertices];
nuclear@0 251 }
nuclear@0 252
nuclear@0 253 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
nuclear@0 254 {
nuclear@0 255 if (mesh->mTextureCoords[i])
nuclear@0 256 uv[i] = out->mTextureCoords[i] = new aiVector3D[out->mNumVertices];
nuclear@0 257 else uv[i] = NULL;
nuclear@0 258
nuclear@0 259 out->mNumUVComponents[i] = mesh->mNumUVComponents[i];
nuclear@0 260 }
nuclear@0 261
nuclear@0 262 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
nuclear@0 263 {
nuclear@0 264 if (mesh->mColors[i])
nuclear@0 265 cols[i] = out->mColors[i] = new aiColor4D[out->mNumVertices];
nuclear@0 266 else cols[i] = NULL;
nuclear@0 267 }
nuclear@0 268
nuclear@0 269 typedef std::vector< aiVertexWeight > TempBoneInfo;
nuclear@0 270 std::vector< TempBoneInfo > tempBones(mesh->mNumBones);
nuclear@0 271
nuclear@0 272 // try to guess how much storage we'll need
nuclear@0 273 for (unsigned int q = 0; q < mesh->mNumBones;++q)
nuclear@0 274 {
nuclear@0 275 tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1));
nuclear@0 276 }
nuclear@0 277
nuclear@0 278 unsigned int outIdx = 0;
nuclear@0 279 for (unsigned int m = 0; m < mesh->mNumFaces; ++m)
nuclear@0 280 {
nuclear@0 281 aiFace& in = mesh->mFaces[m];
nuclear@0 282 if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1))
nuclear@0 283 {
nuclear@0 284 continue;
nuclear@0 285 }
nuclear@0 286
nuclear@0 287 outFaces->mNumIndices = in.mNumIndices;
nuclear@0 288 outFaces->mIndices = in.mIndices;
nuclear@0 289
nuclear@0 290 for (unsigned int q = 0; q < in.mNumIndices; ++q)
nuclear@0 291 {
nuclear@0 292 register unsigned int idx = in.mIndices[q];
nuclear@0 293
nuclear@0 294 // process all bones of this index
nuclear@0 295 if (avw)
nuclear@0 296 {
nuclear@0 297 VertexWeightTable& tbl = avw[idx];
nuclear@0 298 for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end();
nuclear@0 299 it != end; ++it)
nuclear@0 300 {
nuclear@0 301 tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) );
nuclear@0 302 }
nuclear@0 303 }
nuclear@0 304
nuclear@0 305 if (vert)
nuclear@0 306 {
nuclear@0 307 *vert++ = mesh->mVertices[idx];
nuclear@0 308 //mesh->mVertices[idx].x = get_qnan();
nuclear@0 309 }
nuclear@0 310 if (nor )*nor++ = mesh->mNormals[idx];
nuclear@0 311 if (tan )
nuclear@0 312 {
nuclear@0 313 *tan++ = mesh->mTangents[idx];
nuclear@0 314 *bit++ = mesh->mBitangents[idx];
nuclear@0 315 }
nuclear@0 316
nuclear@0 317 for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp)
nuclear@0 318 {
nuclear@0 319 if (!uv[pp])break;
nuclear@0 320 *uv[pp]++ = mesh->mTextureCoords[pp][idx];
nuclear@0 321 }
nuclear@0 322
nuclear@0 323 for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp)
nuclear@0 324 {
nuclear@0 325 if (!cols[pp])break;
nuclear@0 326 *cols[pp]++ = mesh->mColors[pp][idx];
nuclear@0 327 }
nuclear@0 328
nuclear@0 329 in.mIndices[q] = outIdx++;
nuclear@0 330 }
nuclear@0 331
nuclear@0 332 in.mIndices = NULL;
nuclear@0 333 ++outFaces;
nuclear@0 334 }
nuclear@0 335 ai_assert(outFaces == out->mFaces + out->mNumFaces);
nuclear@0 336
nuclear@0 337 // now generate output bones
nuclear@0 338 for (unsigned int q = 0; q < mesh->mNumBones;++q)
nuclear@0 339 if (!tempBones[q].empty())++out->mNumBones;
nuclear@0 340
nuclear@0 341 if (out->mNumBones)
nuclear@0 342 {
nuclear@0 343 out->mBones = new aiBone*[out->mNumBones];
nuclear@0 344 for (unsigned int q = 0, real = 0; q < mesh->mNumBones;++q)
nuclear@0 345 {
nuclear@0 346 TempBoneInfo& in = tempBones[q];
nuclear@0 347 if (in.empty())continue;
nuclear@0 348
nuclear@0 349 aiBone* srcBone = mesh->mBones[q];
nuclear@0 350 aiBone* bone = out->mBones[real] = new aiBone();
nuclear@0 351
nuclear@0 352 bone->mName = srcBone->mName;
nuclear@0 353 bone->mOffsetMatrix = srcBone->mOffsetMatrix;
nuclear@0 354
nuclear@0 355 bone->mNumWeights = (unsigned int)in.size();
nuclear@0 356 bone->mWeights = new aiVertexWeight[bone->mNumWeights];
nuclear@0 357
nuclear@0 358 ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight));
nuclear@0 359
nuclear@0 360 ++real;
nuclear@0 361 }
nuclear@0 362 }
nuclear@0 363 }
nuclear@0 364
nuclear@0 365 // delete the per-vertex bone weights table
nuclear@0 366 delete[] avw;
nuclear@0 367
nuclear@0 368 // delete the input mesh
nuclear@0 369 delete mesh;
nuclear@0 370 }
nuclear@0 371
nuclear@0 372 if (outMeshes.empty())
nuclear@0 373 {
nuclear@0 374 // This should not occur
nuclear@0 375 throw DeadlyImportError("No meshes remaining");
nuclear@0 376 }
nuclear@0 377
nuclear@0 378 // If we added at least one mesh process all nodes in the node
nuclear@0 379 // graph and update their respective mesh indices.
nuclear@0 380 if (bAnyChanges)
nuclear@0 381 {
nuclear@0 382 UpdateNodes(replaceMeshIndex,pScene->mRootNode);
nuclear@0 383 }
nuclear@0 384
nuclear@0 385 if (outMeshes.size() != pScene->mNumMeshes)
nuclear@0 386 {
nuclear@0 387 delete[] pScene->mMeshes;
nuclear@0 388 pScene->mNumMeshes = (unsigned int)outMeshes.size();
nuclear@0 389 pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
nuclear@0 390 }
nuclear@0 391 ::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
nuclear@0 392
nuclear@0 393 if (!DefaultLogger::isNullLogger())
nuclear@0 394 {
nuclear@0 395 char buffer[1024];
nuclear@0 396 ::sprintf(buffer,"Points: %i%s, Lines: %i%s, Triangles: %i%s, Polygons: %i%s (Meshes, X = removed)",
nuclear@0 397 aiNumMeshesPerPType[0], (configRemoveMeshes & aiPrimitiveType_POINT ? "X" : ""),
nuclear@0 398 aiNumMeshesPerPType[1], (configRemoveMeshes & aiPrimitiveType_LINE ? "X" : ""),
nuclear@0 399 aiNumMeshesPerPType[2], (configRemoveMeshes & aiPrimitiveType_TRIANGLE ? "X" : ""),
nuclear@0 400 aiNumMeshesPerPType[3], (configRemoveMeshes & aiPrimitiveType_POLYGON ? "X" : ""));
nuclear@0 401 DefaultLogger::get()->info(buffer);
nuclear@0 402 DefaultLogger::get()->debug("SortByPTypeProcess finished");
nuclear@0 403 }
nuclear@0 404 }
nuclear@0 405