- Added format auto-detection to most loaders
  - Simplified BaseImporter::CanRead() with some utility methods
  - improved fast_atof -> no overruns anymore. Fuck you, irrlicht.
  - added assimp_cmd tool to allow command line model processing. Mainly adebugging tool for internal purposes, but others might find it useful, too.
  - vc8/vc9: revision number is now written to DLL version header
  - mkutil: some batch scripts to simplify tagging & building of release versions
  - some API cleanup
  - fixing some doxygen markup (+now explicit use of @file <filename>)
  - Icon for assimp_view and assimp_cmd

3DS
  - Normal vectors are not anymore inverted in some cases
  - Improved pivot handling
  - Improved handling of x-flipped meshes

Collada
  - fixed a minor bug (visual_scene element)

LWS 
  - WIP implementation. No animations yet, some bugs and crashes.
  - Animation system remains disabled, WIP code
  - many test files for LWS, but most of them test the anim support, which is, read above, currently disabled.

STL
  - fixing a log warning which appears for every model
  - added binary&ascii test spider, exported from truespace

MD3 
  - Cleaning up output tags for automatically joined player models.


IRR
  - Fixing coordinate system issues. 
  - Instance handling improved.
  - Some of the reported crashes not yet fixed.

PretransformVertices
  - Numerous performance improvements.
  - Added config option to preserve the hierarchy during the step.

RemoveRedundantMaterials
  - Added config option to specify a list of materials which are kept in every case.

UNREAL
  - Added support for the old unreal data format (*.a,*.d,*.uc)
  - tested only with exports from Milkshape
  - more Unreal stuff to come soon



git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@356 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
aramis_acg
2009-03-05 22:32:13 +00:00
parent caaf02b0e4
commit 4bbc03332b
237 changed files with 33463 additions and 2245 deletions

View File

@@ -39,12 +39,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the "PretransformVertices" post processing step
/** @file PretransformVertices.cpp
* @brief Implementation of the "PretransformVertices" post processing step
*/
#include "AssimpPCH.h"
#include "PretransformVertices.h"
#include "ProcessHelper.h"
#include "SceneCombiner.h"
using namespace Assimp;
@@ -55,6 +57,7 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
PretransformVertices::PretransformVertices()
: configKeepHierarchy (false)
{
}
@@ -72,9 +75,17 @@ bool PretransformVertices::IsActive( unsigned int pFlags) const
return (pFlags & aiProcess_PreTransformVertices) != 0;
}
// ------------------------------------------------------------------------------------------------
// Setup import configuration
void PretransformVertices::SetupProperties(const Importer* pImp)
{
// Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY
configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,0));
}
// ------------------------------------------------------------------------------------------------
// Count the number of nodes
unsigned int CountNodes( aiNode* pcNode )
unsigned int PretransformVertices::CountNodes( aiNode* pcNode )
{
unsigned int iRet = 1;
for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
@@ -86,7 +97,7 @@ unsigned int CountNodes( aiNode* pcNode )
// ------------------------------------------------------------------------------------------------
// Get a bitwise combination identifying the vertex format of a mesh
unsigned int GetMeshVFormat(aiMesh* pcMesh)
unsigned int PretransformVertices::GetMeshVFormat(aiMesh* pcMesh)
{
// the vertex format is stored in aiMesh::mBones for later retrieval.
// there isn't a good reason to compute it a few hundred times
@@ -106,7 +117,7 @@ unsigned int GetMeshVFormat(aiMesh* pcMesh)
// ------------------------------------------------------------------------------------------------
// Count the number of vertices in the whole scene and a given
// material index
void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
void PretransformVertices::CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
unsigned int iVFormat, unsigned int* piFaces, unsigned int* piVertices)
{
for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
@@ -127,39 +138,73 @@ void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
// ------------------------------------------------------------------------------------------------
// Collect vertex/face data
void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
unsigned int iVFormat, aiMesh* pcMeshOut,
unsigned int aiCurrent[2])
unsigned int aiCurrent[2], unsigned int* num_refs)
{
// No need to multiply if there's no transformation
const bool identity = pcNode->mTransformation.IsIdentity();
for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
{
aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ];
if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
{
// copy positions, transform them to worldspace
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcNode->mTransformation * pcMesh->mVertices[n];
// Decrement mesh reference counter
unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
ai_assert(0 != num_ref);
--num_ref;
aiMatrix4x4 mWorldIT = pcNode->mTransformation;
mWorldIT.Inverse().Transpose();
if (identity) {
// copy positions without modifying them
::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX],
pcMesh->mVertices,
pcMesh->mNumVertices * sizeof(aiVector3D));
// TODO: implement Inverse() for aiMatrix3x3
aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
if (iVFormat & 0x2)
{
// copy normals, transform them to worldspace
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] = m * pcMesh->mNormals[n];
if (iVFormat & 0x2) {
// copy normals without modifying them
::memcpy(pcMeshOut->mNormals + aiCurrent[AI_PTVS_VERTEX],
pcMesh->mNormals,
pcMesh->mNumVertices * sizeof(aiVector3D));
}
if (iVFormat & 0x4)
{
// copy tangents without modifying them
::memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX],
pcMesh->mTangents,
pcMesh->mNumVertices * sizeof(aiVector3D));
// copy bitangents without modifying them
::memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX],
pcMesh->mBitangents,
pcMesh->mNumVertices * sizeof(aiVector3D));
}
}
if (iVFormat & 0x4)
else
{
// copy tangents and bitangents, transform them to worldspace
// copy positions, transform them to worldspace
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
pcMeshOut->mTangents [aiCurrent[AI_PTVS_VERTEX]+n] = m * pcMesh->mTangents[n];
pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX]+n] = m * pcMesh->mBitangents[n];
pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcNode->mTransformation * pcMesh->mVertices[n];
}
aiMatrix4x4 mWorldIT = pcNode->mTransformation;
mWorldIT.Inverse().Transpose();
// TODO: implement Inverse() for aiMatrix3x3
aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
if (iVFormat & 0x2)
{
// copy normals, transform them to worldspace
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] =
m * pcMesh->mNormals[n];
}
}
if (iVFormat & 0x4)
{
// copy tangents and bitangents, transform them to worldspace
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
pcMeshOut->mTangents [aiCurrent[AI_PTVS_VERTEX]+n] = m * pcMesh->mTangents[n];
pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX]+n] = m * pcMesh->mBitangents[n];
}
}
}
unsigned int p = 0;
@@ -180,26 +225,35 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
pcMesh->mNumVertices * sizeof(aiColor4D));
++p;
}
// now we need to copy all faces
// since we will delete the source mesh afterwards,
// we don't need to reallocate the array of indices
for (unsigned int planck = 0;planck<pcMesh->mNumFaces;++planck)
// now we need to copy all faces. since we will delete the source mesh afterwards,
// we don't need to reallocate the array of indices except if this mesh is
// referenced multiple times.
for (unsigned int planck = 0;planck < pcMesh->mNumFaces;++planck)
{
pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck].mNumIndices =
pcMesh->mFaces[planck].mNumIndices;
aiFace& f_src = pcMesh->mFaces[planck];
aiFace& f_dst = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck];
unsigned int* pi = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck].
mIndices = pcMesh->mFaces[planck].mIndices;
const unsigned int num_idx = f_src.mNumIndices;
// offset all vrtex indices
for (unsigned int hahn = 0; hahn < pcMesh->mFaces[planck].mNumIndices;++hahn)
{
pi[hahn] += aiCurrent[AI_PTVS_VERTEX];
f_dst.mNumIndices = num_idx;
unsigned int* pi;
if (!num_ref) { /* if last time the mesh is referenced -> no reallocation */
pi = f_dst.mIndices = f_src.mIndices;
// offset all vertex indices
for (unsigned int hahn = 0; hahn < num_idx;++hahn){
pi[hahn] += aiCurrent[AI_PTVS_VERTEX];
}
}
else {
pi = f_dst.mIndices = new unsigned int[num_idx];
// copy and offset all vertex indices
for (unsigned int hahn = 0; hahn < num_idx;++hahn){
pi[hahn] = f_src.mIndices[hahn] + aiCurrent[AI_PTVS_VERTEX];
}
}
// just make sure the array won't be deleted by the
// aiFace destructor ...
pcMesh->mFaces[planck].mIndices = NULL;
// Update the mPrimitiveTypes member of the mesh
switch (pcMesh->mFaces[planck].mNumIndices)
@@ -222,24 +276,24 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces;
}
}
for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
{
// append all children of us
for (unsigned int i = 0;i < pcNode->mNumChildren;++i) {
CollectData(pcScene,pcNode->mChildren[i],iMat,
iVFormat,pcMeshOut,aiCurrent);
iVFormat,pcMeshOut,aiCurrent,num_refs);
}
}
// ------------------------------------------------------------------------------------------------
// Get a list of all vertex formats that occur for a given material index
// The output list contains duplicate elements
void GetVFormatList( aiScene* pcScene, unsigned int iMat,
void PretransformVertices::GetVFormatList( aiScene* pcScene, unsigned int iMat,
std::list<unsigned int>& aiOut)
{
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
{
aiMesh* pcMesh = pcScene->mMeshes[ i ];
if (iMat == pcMesh->mMaterialIndex)
{
if (iMat == pcMesh->mMaterialIndex) {
aiOut.push_back(GetMeshVFormat(pcMesh));
}
}
@@ -247,7 +301,7 @@ void GetVFormatList( aiScene* pcScene, unsigned int iMat,
// ------------------------------------------------------------------------------------------------
// Compute the absolute transformation matrices of each node
void ComputeAbsoluteTransform( aiNode* pcNode )
void PretransformVertices::ComputeAbsoluteTransform( aiNode* pcNode )
{
if (pcNode->mParent) {
pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation;
@@ -258,12 +312,126 @@ void ComputeAbsoluteTransform( aiNode* pcNode )
}
}
// ------------------------------------------------------------------------------------------------
// Apply the node transformation to a mesh
void PretransformVertices::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)
{
// Check whether we need to transform the coordinates at all
if (!mat.IsIdentity()) {
if (mesh->HasPositions()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mVertices[i] = mat * mesh->mVertices[i];
}
}
if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
aiMatrix4x4 mWorldIT = mat;
mWorldIT.Inverse().Transpose();
// TODO: implement Inverse() for aiMatrix3x3
aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
if (mesh->HasNormals()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mNormals[i] = m * mesh->mNormals[i];
}
}
if (mesh->HasTangentsAndBitangents()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mTangents[i] = m * mesh->mTangents[i];
mesh->mBitangents[i] = m * mesh->mBitangents[i];
}
}
}
}
}
// ------------------------------------------------------------------------------------------------
// Simple routine to build meshes in worldspace, no further optimization
void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in,
unsigned int numIn, aiNode* node)
{
// NOTE:
// aiMesh::mNumBones store original source mesh, or 0xffffffff if not a copy
// aiMesh::mBones store reference to abs. transform we multiplied with
// process meshes
for (unsigned int i = 0; i < node->mNumMeshes;++i) {
aiMesh* mesh = in[node->mMeshes[i]];
// check whether we can operate on this mesh
if (!mesh->mBones || *reinterpret_cast<aiMatrix4x4*>(mesh->mBones) == node->mTransformation) {
// yes, we can.
mesh->mBones = reinterpret_cast<aiBone**> (&node->mTransformation);
mesh->mNumBones = 0xffffffff;
}
else {
// try to find us in the list of newly created meshes
for (unsigned int n = 0; n < out.size(); ++n) {
aiMesh* ctz = out[n];
if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast<aiMatrix4x4*>(ctz->mBones) == node->mTransformation) {
// ok, use this one. Update node mesh index
node->mMeshes[i] = numIn + n;
}
}
if (node->mMeshes[i] < numIn) {
// Worst case. Need to operate on a full copy of the mesh
DefaultLogger::get()->info("PretransformVertices: Copying mesh due to mismatching transforms");
aiMesh* ntz;
const unsigned int tmp = mesh->mNumBones; //
mesh->mNumBones = 0;
SceneCombiner::Copy(&ntz,mesh);
mesh->mNumBones = tmp;
ntz->mNumBones = node->mMeshes[i];
ntz->mBones = reinterpret_cast<aiBone**> (&node->mTransformation);
out.push_back(ntz);
}
}
}
// call children
for (unsigned int i = 0; i < node->mNumChildren;++i)
BuildWCSMeshes(out,in,numIn,node->mChildren[i]);
}
// ------------------------------------------------------------------------------------------------
// Reset transformation matrices to identity
void PretransformVertices::MakeIdentityTransform(aiNode* nd)
{
nd->mTransformation = aiMatrix4x4();
// call children
for (unsigned int i = 0; i < nd->mNumChildren;++i)
MakeIdentityTransform(nd->mChildren[i]);
}
// ------------------------------------------------------------------------------------------------
// Build reference counters for all meshes
void PretransformVertices::BuildMeshRefCountArray(aiNode* nd, unsigned int * refs)
{
for (unsigned int i = 0; i< nd->mNumMeshes;++i)
refs[nd->mMeshes[i]]++;
// call children
for (unsigned int i = 0; i < nd->mNumChildren;++i)
BuildMeshRefCountArray(nd->mChildren[i],refs);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void PretransformVertices::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("PretransformVerticesProcess begin");
// Return immediately if we have no meshes
if (!pScene->mNumMeshes)
return;
const unsigned int iOldMeshes = pScene->mNumMeshes;
const unsigned int iOldAnimationChannels = pScene->mNumAnimations;
const unsigned int iOldNodes = CountNodes(pScene->mRootNode);
@@ -271,11 +439,10 @@ void PretransformVertices::Execute( aiScene* pScene)
// first compute absolute transformation matrices for all nodes
ComputeAbsoluteTransform(pScene->mRootNode);
// delete aiMesh::mBones for all meshes. The bones are
// Delete aiMesh::mBones for all meshes. The bones are
// removed during this step and we need the pointer as
// temporary storage
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
aiMesh* mesh = pScene->mMeshes[i];
for (unsigned int a = 0; a < mesh->mNumBones;++a)
@@ -287,50 +454,123 @@ void PretransformVertices::Execute( aiScene* pScene)
// now build a list of output meshes
std::vector<aiMesh*> apcOutMeshes;
apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
std::list<unsigned int> aiVFormats;
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
// get the list of all vertex formats for this material
aiVFormats.clear();
GetVFormatList(pScene,i,aiVFormats);
aiVFormats.sort();
aiVFormats.unique();
for (std::list<unsigned int>::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) {
unsigned int iVertices = 0;
unsigned int iFaces = 0;
CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices);
if (iFaces && iVertices)
{
apcOutMeshes.push_back(new aiMesh());
aiMesh* pcMesh = apcOutMeshes.back();
pcMesh->mNumFaces = iFaces;
pcMesh->mNumVertices = iVertices;
pcMesh->mFaces = new aiFace[iFaces];
pcMesh->mVertices = new aiVector3D[iVertices];
pcMesh->mMaterialIndex = i;
if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices];
if ((*j) & 0x4)
{
pcMesh->mTangents = new aiVector3D[iVertices];
pcMesh->mBitangents = new aiVector3D[iVertices];
}
iFaces = 0;
while ((*j) & (0x100 << iFaces))
{
pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
else pcMesh->mNumUVComponents[iFaces] = 2;
iFaces++;
}
iFaces = 0;
while ((*j) & (0x1000000 << iFaces))
pcMesh->mColors[iFaces++] = new aiColor4D[iVertices];
// fill the mesh ...
unsigned int aiTemp[2] = {0,0};
CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp);
// Keep scene hierarchy? It's an easy job in this case ...
// we go on and transform all meshes, if one is referenced by nodes
// with different absolute transformations a depth copy of the mesh
// is required.
if( configKeepHierarchy ) {
// Hack: store the matrix we're transforming a mesh with in aiMesh::mBones
BuildWCSMeshes(apcOutMeshes,pScene->mMeshes,pScene->mNumMeshes, pScene->mRootNode);
// ... if new meshes have been generated, append them to the end of the scene
if (apcOutMeshes.size() > 0) {
aiMesh** npp = new aiMesh*[pScene->mNumMeshes + apcOutMeshes.size()];
::memcpy(npp,pScene->mMeshes,sizeof(aiMesh*)*pScene->mNumMeshes);
::memcpy(npp+pScene->mNumMeshes,&apcOutMeshes[0],sizeof(aiMesh*)*apcOutMeshes.size());
pScene->mNumMeshes += apcOutMeshes.size();
delete[] pScene->mMeshes; pScene->mMeshes = npp;
}
// now iterate through all meshes and transform them to worldspace
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
ApplyTransform(pScene->mMeshes[i],*reinterpret_cast<aiMatrix4x4*>( pScene->mMeshes[i]->mBones ));
// prevent improper destruction
pScene->mMeshes[i]->mBones = NULL;
pScene->mMeshes[i]->mNumBones = 0;
}
}
else {
apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
std::list<unsigned int> aiVFormats;
std::vector<unsigned int> s(pScene->mNumMeshes,0);
BuildMeshRefCountArray(pScene->mRootNode,&s[0]);
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
// get the list of all vertex formats for this material
aiVFormats.clear();
GetVFormatList(pScene,i,aiVFormats);
aiVFormats.sort();
aiVFormats.unique();
for (std::list<unsigned int>::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) {
unsigned int iVertices = 0;
unsigned int iFaces = 0;
CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices);
if (0 != iFaces && 0 != iVertices)
{
apcOutMeshes.push_back(new aiMesh());
aiMesh* pcMesh = apcOutMeshes.back();
pcMesh->mNumFaces = iFaces;
pcMesh->mNumVertices = iVertices;
pcMesh->mFaces = new aiFace[iFaces];
pcMesh->mVertices = new aiVector3D[iVertices];
pcMesh->mMaterialIndex = i;
if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices];
if ((*j) & 0x4)
{
pcMesh->mTangents = new aiVector3D[iVertices];
pcMesh->mBitangents = new aiVector3D[iVertices];
}
iFaces = 0;
while ((*j) & (0x100 << iFaces))
{
pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
else pcMesh->mNumUVComponents[iFaces] = 2;
iFaces++;
}
iFaces = 0;
while ((*j) & (0x1000000 << iFaces))
pcMesh->mColors[iFaces++] = new aiColor4D[iVertices];
// fill the mesh ...
unsigned int aiTemp[2] = {0,0};
CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp,&s[0]);
}
}
}
// now delete all meshes in the scene and build a new mesh list
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{
aiMesh* mesh = pScene->mMeshes[i];
mesh->mNumBones = 0;
mesh->mBones = NULL;
// we're reusing the face index arrays. avoid destruction
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
mesh->mFaces[a].mNumIndices = 0;
mesh->mFaces[a].mIndices = NULL;
}
delete mesh;
// Invalidate the contents of the old mesh array. We will most
// likely have less output meshes now, so the last entries of
// the mesh array are not overridden. We set them to NULL to
// make sure the developer gets notified when his application
// attempts to access these fields ...
mesh = NULL;
}
// If no meshes are referenced in the node graph it is possible that we get no output meshes.
if (apcOutMeshes.empty()) {
throw new ImportErrorException("No output meshes: all meshes are orphaned and are not referenced by nodes");
}
else
{
// It is impossible that we have more output meshes than
// input meshes, so we can easily reuse the old mesh array
pScene->mNumMeshes = (unsigned int)apcOutMeshes.size();
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
pScene->mMeshes[i] = apcOutMeshes[i];
}
}
// remove all animations from the scene
@@ -341,40 +581,6 @@ void PretransformVertices::Execute( aiScene* pScene)
pScene->mAnimations = NULL;
pScene->mNumAnimations = 0;
// now delete all meshes in the scene and build a new mesh list
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{
pScene->mMeshes[i]->mBones = NULL;
delete pScene->mMeshes[i];
// invalidate the contents of the old mesh array. We will most
// likely have less output meshes now, so the last entries of
// the mesh array are not overridden. We set them to NULL to
// make sure the developer gets notified when his application
// attempts to access these fields ...
pScene->mMeshes[i] = NULL;
}
// If no meshes are referenced in the node graph it is
// possible that we get no output meshes. However, this
// is OK if we had no input meshes, too
if (apcOutMeshes.empty())
{
if (pScene->mNumMeshes)
{
throw new ImportErrorException("No output meshes: all meshes are orphaned "
"and have no node references");
}
}
else
{
// It is impossible that we have more output meshes than
// input meshes, so we can easily reuse the old mesh array
pScene->mNumMeshes = (unsigned int)apcOutMeshes.size();
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
pScene->mMeshes[i] = apcOutMeshes[i];
}
// --- we need to keep all cameras and lights
for (unsigned int i = 0; i < pScene->mNumCameras;++i)
{
@@ -401,51 +607,58 @@ void PretransformVertices::Execute( aiScene* pScene)
l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection;
}
// now delete all nodes in the scene and build a new
// flat node graph with a root node and some level 1 children
delete pScene->mRootNode;
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<dummy_root>");
if( !configKeepHierarchy ) {
if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
{
pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int[1];
pScene->mRootNode->mMeshes[0] = 0;
// now delete all nodes in the scene and build a new
// flat node graph with a root node and some level 1 children
delete pScene->mRootNode;
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<dummy_root>");
if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
{
pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int[1];
pScene->mRootNode->mMeshes[0] = 0;
}
else
{
pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras;
aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
// generate mesh nodes
for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes)
{
aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::sprintf(pcNode->mName.data,"mesh_%i",i);
// setup mesh indices
pcNode->mNumMeshes = 1;
pcNode->mMeshes = new unsigned int[1];
pcNode->mMeshes[0] = i;
}
// generate light nodes
for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes)
{
aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::sprintf(pcNode->mName.data,"light_%i",i);
pScene->mLights[i]->mName = pcNode->mName;
}
// generate camera nodes
for (unsigned int i = 0; i < pScene->mNumCameras;++i,++nodes)
{
aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::sprintf(pcNode->mName.data,"cam_%i",i);
pScene->mCameras[i]->mName = pcNode->mName;
}
}
}
else
{
pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras;
aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
// generate mesh nodes
for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes)
{
aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::sprintf(pcNode->mName.data,"mesh_%i",i);
// setup mesh indices
pcNode->mNumMeshes = 1;
pcNode->mMeshes = new unsigned int[1];
pcNode->mMeshes[0] = i;
}
// generate light nodes
for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes)
{
aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::sprintf(pcNode->mName.data,"light_%i",i);
pScene->mLights[i]->mName = pcNode->mName;
}
// generate camera nodes
for (unsigned int i = 0; i < pScene->mNumCameras;++i,++nodes)
{
aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::sprintf(pcNode->mName.data,"cam_%i",i);
pScene->mCameras[i]->mName = pcNode->mName;
}
else {
// ... and finally set the transformation matrix of all nodes to identity
MakeIdentityTransform(pScene->mRootNode);
}
// print statistics
@@ -467,7 +680,5 @@ void PretransformVertices::Execute( aiScene* pScene)
iOldMeshes,pScene->mNumMeshes);
DefaultLogger::get()->info(buffer);
}
return;
}