|
@@ -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];
|
|
|
-
|
|
|
-
|
|
|
- aiMatrix4x4 mWorldIT = pcNode->mTransformation;
|
|
|
- mWorldIT.Inverse().Transpose();
|
|
|
-
|
|
|
- // TODO: implement Inverse() for aiMatrix3x3
|
|
|
- aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
|
|
|
+ // Decrement mesh reference counter
|
|
|
+ unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
|
|
|
+ ai_assert(0 != num_ref);
|
|
|
+ --num_ref;
|
|
|
+
|
|
|
+ if (identity) {
|
|
|
+ // copy positions without modifying them
|
|
|
+ ::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX],
|
|
|
+ pcMesh->mVertices,
|
|
|
+ pcMesh->mNumVertices * sizeof(aiVector3D));
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
- // just make sure the array won't be deleted by the
|
|
|
- // aiFace destructor ...
|
|
|
- pcMesh->mFaces[planck].mIndices = NULL;
|
|
|
+ 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];
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// 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,49 +454,122 @@ 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))
|
|
|
+
|
|
|
+ // 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)
|
|
|
{
|
|
|
- pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
|
|
|
- if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
|
|
|
- else pcMesh->mNumUVComponents[iFaces] = 2;
|
|
|
- iFaces++;
|
|
|
+ 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]);
|
|
|
}
|
|
|
- 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);
|
|
|
+ // 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];
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -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,52 +607,59 @@ 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;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras;
|
|
|
- aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
|
|
|
+ // 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>");
|
|
|
|
|
|
- // generate mesh nodes
|
|
|
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes)
|
|
|
+ if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
|
|
|
{
|
|
|
- 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;
|
|
|
+ pScene->mRootNode->mNumMeshes = 1;
|
|
|
+ pScene->mRootNode->mMeshes = new unsigned int[1];
|
|
|
+ pScene->mRootNode->mMeshes[0] = 0;
|
|
|
}
|
|
|
- // generate light nodes
|
|
|
- for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes)
|
|
|
+ else
|
|
|
{
|
|
|
- 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;
|
|
|
+ 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
|
|
|
if (!DefaultLogger::isNullLogger())
|
|
@@ -467,7 +680,5 @@ void PretransformVertices::Execute( aiScene* pScene)
|
|
|
iOldMeshes,pScene->mNumMeshes);
|
|
|
DefaultLogger::get()->info(buffer);
|
|
|
}
|
|
|
-
|
|
|
- return;
|
|
|
}
|
|
|
|