Fixed bug in the AC loader causing lines to load incorrectly. Seems to work now.
Added some more essential includes to AssimpPCH.hAdded support for line and point meshes to most steps - I did nto yet adapt all unit tests, so meshes with mixed primitive types are not absolutely safe at the moment. Added camera and light support to the PretransformVert step. Fixed some small inaccuracies and fixed a bug reported by Mark Sibly causing all transformations to be invalid. However the step is nto yet completely correct, there are still some small artifacts. Updated light and camera data structures, added temporary validation code for the Renamed AI_SCENE_FLAGS_ANIM_SKELETON_ONLY to a more generic AI_SCENE_FLAGS_INCOMPLETE flag. Fixed bug in the OFF loader causing meshes with polygons to crash Added line support to the DXF loader - seems to fail for the moment cause of SortByPType. Added support for lights and cameras to NFF, implemented another NFF format subtype (file starts with 'nff'). Implemented NFF 'tpp' chunk and a corresponding texture extension. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@185 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
3aecad406c
commit
2da2835b29
|
@ -126,9 +126,13 @@ bool AC3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) cons
|
||||||
if( pos == std::string::npos)return false;
|
if( pos == std::string::npos)return false;
|
||||||
std::string extension = pFile.substr( pos);
|
std::string extension = pFile.substr( pos);
|
||||||
|
|
||||||
return !(extension.length() != 3 || extension[0] != '.' ||
|
for( std::string::iterator it = extension.begin(); it != extension.end(); ++it)
|
||||||
extension[1] != 'a' && extension[1] != 'A' ||
|
*it = tolower( *it);
|
||||||
extension[2] != 'c' && extension[2] != 'C');
|
|
||||||
|
if( extension == ".ac" || extension == "ac")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -308,9 +312,16 @@ void AC3DImporter::ConvertMaterial(const Object& object,
|
||||||
matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE);
|
matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE);
|
||||||
matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR);
|
matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR);
|
||||||
|
|
||||||
float f = 1.f - matSrc.trans;
|
int n;
|
||||||
|
if (matSrc.shin)
|
||||||
|
{
|
||||||
|
n = aiShadingMode_Phong;
|
||||||
|
matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS);
|
||||||
|
}
|
||||||
|
else n = aiShadingMode_Gouraud;
|
||||||
|
matDest.AddProperty<int>(&n,1,AI_MATKEY_SHADING_MODEL);
|
||||||
|
|
||||||
matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS);
|
float f = 1.f - matSrc.trans;
|
||||||
matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
|
matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,6 +363,13 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
||||||
faces->mIndices = new unsigned int[1];
|
faces->mIndices = new unsigned int[1];
|
||||||
faces->mIndices[0] = i;
|
faces->mIndices[0] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use the primary material in this case. this should be the
|
||||||
|
// default material if all objects of the file contain points
|
||||||
|
// and no faces.
|
||||||
|
mesh->mMaterialIndex = 0;
|
||||||
|
outMaterials.push_back(new MaterialHelper());
|
||||||
|
ConvertMaterial(object, materials[0], *outMaterials.back());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -501,7 +519,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
|
||||||
face.mNumIndices = 2;
|
face.mNumIndices = 2;
|
||||||
face.mIndices = new unsigned int[2];
|
face.mIndices = new unsigned int[2];
|
||||||
face.mIndices[0] = cur++;
|
face.mIndices[0] = cur++;
|
||||||
face.mIndices[1] = cur;
|
face.mIndices[1] = cur++;
|
||||||
|
|
||||||
// copy vertex positions
|
// copy vertex positions
|
||||||
*vertices++ = object.vertices[(*it2).first];
|
*vertices++ = object.vertices[(*it2).first];
|
||||||
|
@ -660,6 +678,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
|
||||||
if (1 != rootObjects.size())delete root;
|
if (1 != rootObjects.size())delete root;
|
||||||
|
|
||||||
// build output arrays
|
// build output arrays
|
||||||
|
ai_assert(!meshes.empty());
|
||||||
pScene->mNumMeshes = (unsigned int)meshes.size();
|
pScene->mNumMeshes = (unsigned int)meshes.size();
|
||||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||||
::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
|
::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
|
||||||
|
|
|
@ -162,7 +162,7 @@ protected:
|
||||||
*/
|
*/
|
||||||
void GetExtensionList(std::string& append)
|
void GetExtensionList(std::string& append)
|
||||||
{
|
{
|
||||||
append.append("*.ac");
|
append.append("*.ac;*.acc");
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
|
@ -1,9 +1,72 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (ASSIMP)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2008, ASSIMP Development Team
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the following
|
||||||
|
conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the ASSIMP team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the ASSIMP Development Team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef ASSIMP_PCH_INCLUDED
|
#ifndef ASSIMP_PCH_INCLUDED
|
||||||
#define ASSIMP_PCH_INCLUDED
|
#define ASSIMP_PCH_INCLUDED
|
||||||
|
|
||||||
// STL headers
|
// *******************************************************************
|
||||||
|
// Print detailled memory allocation statistics? In this case we'll
|
||||||
|
// need to overload all C++ memory management functions. It is assumed
|
||||||
|
// that old C routines, such as malloc(), are NOT used in Assimp.
|
||||||
|
// *******************************************************************
|
||||||
|
#ifdef ASSIMP_BUILD_MEMORY_STATISTICS
|
||||||
|
|
||||||
|
void *operator new (size_t);
|
||||||
|
void operator delete (void *);
|
||||||
|
void *operator new[] (size_t);
|
||||||
|
void operator delete[] (void *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// *******************************************************************
|
||||||
|
// If we have at least VC8 some C string manipulation functions
|
||||||
|
// are mapped to their safe _s counterparts (e.g. _itoa_s).
|
||||||
|
// *******************************************************************
|
||||||
|
# if _MSC_VER >= 1400 && !(defined _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
||||||
|
# define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// *******************************************************************
|
||||||
|
// STL headers - we need quite a lot of them
|
||||||
|
// *******************************************************************
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -16,7 +79,10 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
// *******************************************************************
|
||||||
// public ASSIMP headers
|
// public ASSIMP headers
|
||||||
|
// *******************************************************************
|
||||||
#include "../include/DefaultLogger.h"
|
#include "../include/DefaultLogger.h"
|
||||||
#include "../include/IOStream.h"
|
#include "../include/IOStream.h"
|
||||||
#include "../include/IOSystem.h"
|
#include "../include/IOSystem.h"
|
||||||
|
@ -24,21 +90,32 @@
|
||||||
#include "../include/aiPostProcess.h"
|
#include "../include/aiPostProcess.h"
|
||||||
#include "../include/assimp.hpp"
|
#include "../include/assimp.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
// *******************************************************************
|
||||||
// internal headers that are nearly always required
|
// internal headers that are nearly always required
|
||||||
|
// *******************************************************************
|
||||||
#include "MaterialSystem.h"
|
#include "MaterialSystem.h"
|
||||||
#include "StringComparison.h"
|
#include "StringComparison.h"
|
||||||
#include "ByteSwap.h"
|
#include "StreamReader.h"
|
||||||
#include "qnan.h"
|
#include "qnan.h"
|
||||||
|
|
||||||
|
// *******************************************************************
|
||||||
// boost headers - take them from the workaround dir if possible
|
// boost headers - take them from the workaround dir if possible
|
||||||
|
// *******************************************************************
|
||||||
#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
|
#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
|
||||||
|
|
||||||
# include "../include/BoostWorkaround/boost/scoped_ptr.hpp"
|
# include "../include/BoostWorkaround/boost/scoped_ptr.hpp"
|
||||||
# include "../include/BoostWorkaround/boost/format.hpp"
|
# include "../include/BoostWorkaround/boost/format.hpp"
|
||||||
|
# include "../include/BoostWorkaround/boost/multi_array.hpp"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
// NOTE: boost::multi_array is nto yet supported by the workaround
|
||||||
|
#define AI_BUILD_NO_BVH_IMPORTER
|
||||||
|
|
||||||
# include <boost/scoped_ptr.hpp>
|
# include <boost/scoped_ptr.hpp>
|
||||||
# include <boost/format.hpp>
|
# include <boost/format.hpp>
|
||||||
|
# include <boost/multi_array.hpp>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ protected:
|
||||||
* a face is unique. Or the other way round: a vertex index may
|
* a face is unique. Or the other way round: a vertex index may
|
||||||
* not occur twice in a single aiMesh.
|
* not occur twice in a single aiMesh.
|
||||||
*
|
*
|
||||||
* If the "AnimationSkeletonOnly"-Flag is not set:<br>
|
* If the AI_SCENE_FLAGS_INCOMPLETE-Flag is not set:<br>
|
||||||
* - at least one mesh must be there<br>
|
* - at least one mesh must be there<br>
|
||||||
* - at least one material must be there<br>
|
* - at least one material must be there<br>
|
||||||
* - there may be no meshes with 0 vertices or faces<br>
|
* - there may be no meshes with 0 vertices or faces<br>
|
||||||
|
|
|
@ -246,12 +246,16 @@ void DXFImporter::InternReadFile( const std::string& pFile,
|
||||||
{
|
{
|
||||||
aiFace& face = pMesh->mFaces[i];
|
aiFace& face = pMesh->mFaces[i];
|
||||||
|
|
||||||
// check whether we need four indices here
|
// check whether we need four,three or two indices here
|
||||||
if (vp[3] != vp[2])
|
if (vp[1] == vp[2])
|
||||||
{
|
{
|
||||||
face.mNumIndices = 4;
|
face.mNumIndices = 2;
|
||||||
}
|
}
|
||||||
else face.mNumIndices = 3;
|
else if (vp[3] == vp[2])
|
||||||
|
{
|
||||||
|
face.mNumIndices = 3;
|
||||||
|
}
|
||||||
|
else face.mNumIndices = 4;
|
||||||
face.mIndices = new unsigned int[face.mNumIndices];
|
face.mIndices = new unsigned int[face.mNumIndices];
|
||||||
|
|
||||||
for (unsigned int a = 0; a < face.mNumIndices;++a)
|
for (unsigned int a = 0; a < face.mNumIndices;++a)
|
||||||
|
@ -323,7 +327,7 @@ bool DXFImporter::ParseEntities()
|
||||||
{
|
{
|
||||||
if (!groupCode)
|
if (!groupCode)
|
||||||
{
|
{
|
||||||
if (!::strcmp(cursor,"3DFACE"))
|
if (!::strcmp(cursor,"3DFACE") || !::strcmp(cursor,"LINE") || !::strcmp(cursor,"3DLINE"))
|
||||||
if (!Parse3DFace()) return false; else bRepeat = true;
|
if (!Parse3DFace()) return false; else bRepeat = true;
|
||||||
|
|
||||||
if (!::strcmp(cursor,"POLYLINE") || !::strcmp(cursor,"LWPOLYLINE"))
|
if (!::strcmp(cursor,"POLYLINE") || !::strcmp(cursor,"LWPOLYLINE"))
|
||||||
|
@ -524,6 +528,10 @@ bool DXFImporter::Parse3DFace()
|
||||||
|
|
||||||
aiVector3D vip[4]; // -- vectors are initialized to zero
|
aiVector3D vip[4]; // -- vectors are initialized to zero
|
||||||
aiColor4D clr(g_clrInvalid);
|
aiColor4D clr(g_clrInvalid);
|
||||||
|
|
||||||
|
// this is also used for for parsing line entities
|
||||||
|
bool bThird = false;
|
||||||
|
|
||||||
while (GetNextToken())
|
while (GetNextToken())
|
||||||
{
|
{
|
||||||
switch (groupCode)
|
switch (groupCode)
|
||||||
|
@ -556,22 +564,28 @@ bool DXFImporter::Parse3DFace()
|
||||||
case 31: vip[1].z = fast_atof(cursor);break;
|
case 31: vip[1].z = fast_atof(cursor);break;
|
||||||
|
|
||||||
// x position of the third corner
|
// x position of the third corner
|
||||||
case 12: vip[2].x = fast_atof(cursor);break;
|
case 12: vip[2].x = fast_atof(cursor);
|
||||||
|
bThird = true;break;
|
||||||
|
|
||||||
// y position of the third corner
|
// y position of the third corner
|
||||||
case 22: vip[2].y = -fast_atof(cursor);break;
|
case 22: vip[2].y = -fast_atof(cursor);
|
||||||
|
bThird = true;break;
|
||||||
|
|
||||||
// z position of the third corner
|
// z position of the third corner
|
||||||
case 32: vip[2].z = fast_atof(cursor);break;
|
case 32: vip[2].z = fast_atof(cursor);
|
||||||
|
bThird = true;break;
|
||||||
|
|
||||||
// x position of the fourth corner
|
// x position of the fourth corner
|
||||||
case 13: vip[3].x = fast_atof(cursor);break;
|
case 13: vip[3].x = fast_atof(cursor);
|
||||||
|
bThird = true;break;
|
||||||
|
|
||||||
// y position of the fourth corner
|
// y position of the fourth corner
|
||||||
case 23: vip[3].y = -fast_atof(cursor);break;
|
case 23: vip[3].y = -fast_atof(cursor);
|
||||||
|
bThird = true;break;
|
||||||
|
|
||||||
// z position of the fourth corner
|
// z position of the fourth corner
|
||||||
case 33: vip[3].z = fast_atof(cursor);break;
|
case 33: vip[3].z = fast_atof(cursor);
|
||||||
|
bThird = true;break;
|
||||||
|
|
||||||
// color
|
// color
|
||||||
case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break;
|
case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break;
|
||||||
|
@ -579,6 +593,8 @@ bool DXFImporter::Parse3DFace()
|
||||||
if (ret)break;
|
if (ret)break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bThird)vip[2] = vip[1];
|
||||||
|
|
||||||
// use a default layer if necessary
|
// use a default layer if necessary
|
||||||
if (!out)SetDefaultLayer(out);
|
if (!out)SetDefaultLayer(out);
|
||||||
|
|
||||||
|
@ -592,3 +608,5 @@ bool DXFImporter::Parse3DFace()
|
||||||
out->vColors.push_back(clr);
|
out->vColors.push_back(clr);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,10 @@ protected:
|
||||||
|
|
||||||
char name[4096];
|
char name[4096];
|
||||||
|
|
||||||
// face buffer - order is x,y,z,w v1,v2,v3 (w is equal to z if unused)
|
// face buffer - order is x,y,z v1,v2,v3,v4
|
||||||
|
// if v2 = v3: line
|
||||||
|
// elsif v3 = v2: triangle
|
||||||
|
// else: polygon
|
||||||
std::vector<aiVector3D> vPositions;
|
std::vector<aiVector3D> vPositions;
|
||||||
std::vector<aiColor4D> vColors;
|
std::vector<aiColor4D> vColors;
|
||||||
};
|
};
|
||||||
|
|
|
@ -91,7 +91,11 @@ void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMap
|
||||||
}
|
}
|
||||||
// just let the members that are unused, that's much cheaper
|
// just let the members that are unused, that's much cheaper
|
||||||
// than a full array realloc'n'copy party ...
|
// than a full array realloc'n'copy party ...
|
||||||
node->mNumMeshes = out;
|
if(!(node->mNumMeshes = out))
|
||||||
|
{
|
||||||
|
delete[] node->mMeshes;
|
||||||
|
node->mMeshes = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// recursively update all children
|
// recursively update all children
|
||||||
for (unsigned int i = 0; i < node->mNumChildren;++i)
|
for (unsigned int i = 0; i < node->mNumChildren;++i)
|
||||||
|
@ -173,7 +177,8 @@ inline const char* ValidateArrayContents<aiVector3D>(const aiVector3D* arr, unsi
|
||||||
}
|
}
|
||||||
if (i && v != arr[i-1])b = true;
|
if (i && v != arr[i-1])b = true;
|
||||||
}
|
}
|
||||||
if (!b)return "All vectors are identical";
|
if (!b)
|
||||||
|
return "All vectors are identical";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,11 +97,31 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
|
||||||
{
|
{
|
||||||
if (NULL != pMesh->mNormals)return false;
|
if (NULL != pMesh->mNormals)return false;
|
||||||
|
|
||||||
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
// If the mesh consists of lines and/or points but not of
|
||||||
|
// triangles or higher-order polygons the normal vectors
|
||||||
|
// are undefined.
|
||||||
|
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate an array to hold the output normals
|
||||||
|
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||||
|
const float qnan = std::numeric_limits<float>::quiet_NaN();
|
||||||
|
|
||||||
|
// iterate through all faces and compute per-face normals but store
|
||||||
|
// them per-vertex.
|
||||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
||||||
{
|
{
|
||||||
const aiFace& face = pMesh->mFaces[a];
|
const aiFace& face = pMesh->mFaces[a];
|
||||||
|
if (face.mNumIndices < 3)
|
||||||
|
{
|
||||||
|
// either a point or a line -> no well-defined normal vector
|
||||||
|
for (unsigned int i = 0;i < face.mNumIndices;++i)
|
||||||
|
pMesh->mNormals[face.mIndices[i]] = qnan;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||||
aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||||
|
|
|
@ -110,10 +110,30 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
||||||
{
|
{
|
||||||
if (NULL != pMesh->mNormals)return false;
|
if (NULL != pMesh->mNormals)return false;
|
||||||
|
|
||||||
|
// If the mesh consists of lines and/or points but not of
|
||||||
|
// triangles or higher-order polygons the normal vectors
|
||||||
|
// are undefined.
|
||||||
|
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate an array to hold the output normals
|
||||||
|
const float qnan = std::numeric_limits<float>::quiet_NaN();
|
||||||
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||||
|
|
||||||
|
// compute per-face normals but store them per-vertex
|
||||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
||||||
{
|
{
|
||||||
const aiFace& face = pMesh->mFaces[a];
|
const aiFace& face = pMesh->mFaces[a];
|
||||||
|
if (face.mNumIndices < 3)
|
||||||
|
{
|
||||||
|
// either a point or a line -> no normal vector
|
||||||
|
for (unsigned int i = 0;i < face.mNumIndices;++i)
|
||||||
|
pMesh->mNormals[face.mIndices[i]] = qnan;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||||
aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||||
|
@ -167,9 +187,10 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
||||||
aiVector3D pcNor;
|
aiVector3D pcNor;
|
||||||
for (unsigned int a = 0; a < verticesFound.size(); ++a)
|
for (unsigned int a = 0; a < verticesFound.size(); ++a)
|
||||||
{
|
{
|
||||||
register unsigned int vidx = verticesFound[a];
|
const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
|
||||||
pcNor += pMesh->mNormals[vidx];
|
if (is_not_qnan(v.x))pcNor += v;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcNor.Normalize();
|
pcNor.Normalize();
|
||||||
|
|
||||||
// write the smoothed normal back to all affected normals
|
// write the smoothed normal back to all affected normals
|
||||||
|
@ -183,7 +204,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const float fLimit = cos(configMaxAngle);
|
const float fLimit = ::cos(configMaxAngle);
|
||||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
||||||
{
|
{
|
||||||
// get all vertices that share this one ...
|
// get all vertices that share this one ...
|
||||||
|
@ -192,16 +213,18 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
|
||||||
aiVector3D pcNor;
|
aiVector3D pcNor;
|
||||||
for (unsigned int a = 0; a < verticesFound.size(); ++a)
|
for (unsigned int a = 0; a < verticesFound.size(); ++a)
|
||||||
{
|
{
|
||||||
register unsigned int vidx = verticesFound[a];
|
const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
|
||||||
|
|
||||||
// check whether the angle between the two normals is not too large
|
// check whether the angle between the two normals is not too large
|
||||||
if (pMesh->mNormals[vidx] * pMesh->mNormals[i] < fLimit)
|
// HACK: if v.x is qnan the dot product will become qnan, too
|
||||||
|
// therefore the comparison against fLimit should be false
|
||||||
|
// in every case. Contact me if you disagree with this assumption
|
||||||
|
if (v * pMesh->mNormals[i] < fLimit)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pcNor += pMesh->mNormals[vidx];
|
pcNor += v;
|
||||||
}
|
}
|
||||||
pcNor.Normalize();
|
pcNew[i] = pcNor.Normalize();
|
||||||
pcNew[i] = pcNor;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,10 +176,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
# include "SortByPTypeProcess.h"
|
# include "SortByPTypeProcess.h"
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor.
|
// Constructor.
|
||||||
Importer::Importer() :
|
Importer::Importer() :
|
||||||
|
@ -276,6 +276,9 @@ Importer::Importer() :
|
||||||
mPostProcessingSteps.push_back( new RemoveVCProcess());
|
mPostProcessingSteps.push_back( new RemoveVCProcess());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
|
||||||
|
mPostProcessingSteps.push_back( new PretransformVertices());
|
||||||
|
#endif
|
||||||
#if (!defined AI_BUILD_NO_TRIANGULATE_PROCESS)
|
#if (!defined AI_BUILD_NO_TRIANGULATE_PROCESS)
|
||||||
mPostProcessingSteps.push_back( new TriangulateProcess());
|
mPostProcessingSteps.push_back( new TriangulateProcess());
|
||||||
#endif
|
#endif
|
||||||
|
@ -294,9 +297,6 @@ Importer::Importer() :
|
||||||
#if (!defined AI_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
|
#if (!defined AI_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
|
||||||
mPostProcessingSteps.push_back( new OptimizeGraphProcess());
|
mPostProcessingSteps.push_back( new OptimizeGraphProcess());
|
||||||
#endif
|
#endif
|
||||||
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
|
|
||||||
mPostProcessingSteps.push_back( new PretransformVertices());
|
|
||||||
#endif
|
|
||||||
#if (!defined AI_BUILD_NO_FIXINFACINGNORMALS_PROCESS)
|
#if (!defined AI_BUILD_NO_FIXINFACINGNORMALS_PROCESS)
|
||||||
mPostProcessingSteps.push_back( new FixInfacingNormalsProcess());
|
mPostProcessingSteps.push_back( new FixInfacingNormalsProcess());
|
||||||
#endif
|
#endif
|
||||||
|
@ -488,105 +488,121 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
|
||||||
// validate the flags
|
// validate the flags
|
||||||
ai_assert(ValidateFlags(pFlags));
|
ai_assert(ValidateFlags(pFlags));
|
||||||
|
|
||||||
// check whether this Importer instance has already loaded
|
// put a large try block around everything to catch all std::exception's
|
||||||
// a scene. In this case we need to delete the old one
|
// that might be thrown by STL containers or by new().
|
||||||
if (this->mScene)
|
// ImportErrorException's are throw by ourselves and caught elsewhere.
|
||||||
|
try
|
||||||
{
|
{
|
||||||
delete mScene;
|
// check whether this Importer instance has already loaded
|
||||||
this->mScene = NULL;
|
// a scene. In this case we need to delete the old one
|
||||||
}
|
if (this->mScene)
|
||||||
|
|
||||||
// first check if the file is accessable at all
|
|
||||||
if( !mIOHandler->Exists( pFile))
|
|
||||||
{
|
|
||||||
mErrorString = "Unable to open file \"" + pFile + "\".";
|
|
||||||
DefaultLogger::get()->error(mErrorString);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find an worker class which can handle the file
|
|
||||||
BaseImporter* imp = NULL;
|
|
||||||
for( unsigned int a = 0; a < mImporter.size(); a++)
|
|
||||||
{
|
|
||||||
if( mImporter[a]->CanRead( pFile, mIOHandler))
|
|
||||||
{
|
{
|
||||||
imp = mImporter[a];
|
DefaultLogger::get()->debug("The previous scene has been deleted");
|
||||||
break;
|
delete mScene;
|
||||||
|
this->mScene = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// put a proper error message if no suitable importer was found
|
// first check if the file is accessable at all
|
||||||
if( !imp)
|
if( !mIOHandler->Exists( pFile))
|
||||||
{
|
|
||||||
mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
|
|
||||||
DefaultLogger::get()->error(mErrorString);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispatch the reading to the worker class for this format
|
|
||||||
imp->SetupProperties( this );
|
|
||||||
mScene = imp->ReadFile( pFile, mIOHandler);
|
|
||||||
|
|
||||||
// if successful, apply all active post processing steps to the imported data
|
|
||||||
if( mScene)
|
|
||||||
{
|
|
||||||
#ifdef _DEBUG
|
|
||||||
if (bExtraVerbose)
|
|
||||||
{
|
{
|
||||||
|
mErrorString = "Unable to open file \"" + pFile + "\".";
|
||||||
|
DefaultLogger::get()->error(mErrorString);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find an worker class which can handle the file
|
||||||
|
BaseImporter* imp = NULL;
|
||||||
|
for( unsigned int a = 0; a < mImporter.size(); a++)
|
||||||
|
{
|
||||||
|
if( mImporter[a]->CanRead( pFile, mIOHandler))
|
||||||
|
{
|
||||||
|
imp = mImporter[a];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// put a proper error message if no suitable importer was found
|
||||||
|
if( !imp)
|
||||||
|
{
|
||||||
|
mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
|
||||||
|
DefaultLogger::get()->error(mErrorString);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispatch the reading to the worker class for this format
|
||||||
|
DefaultLogger::get()->info("Found a matching importer for this file format");
|
||||||
|
imp->SetupProperties( this );
|
||||||
|
mScene = imp->ReadFile( pFile, mIOHandler);
|
||||||
|
|
||||||
|
// if successful, apply all active post processing steps to the imported data
|
||||||
|
DefaultLogger::get()->info("Import succesful, entering postprocessing-steps");
|
||||||
|
if( mScene)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
if (bExtraVerbose)
|
||||||
|
{
|
||||||
#if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS)
|
#if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS)
|
||||||
|
|
||||||
DefaultLogger::get()->error("Extra verbose mode not available, library"
|
DefaultLogger::get()->error("Extra verbose mode not available, library"
|
||||||
" wasn't build with the ValidateDS-Step");
|
" wasn't build with the ValidateDS-Step");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
pFlags |= aiProcess_ValidateDataStructure;
|
pFlags |= aiProcess_ValidateDataStructure;
|
||||||
|
|
||||||
// use the MSB to tell the ValidateDS-Step that e're in extra verbose mode
|
|
||||||
// TODO: temporary solution, clean up later
|
|
||||||
mScene->mFlags |= 0x80000000;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (bExtraVerbose)DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
|
|
||||||
#endif // ! DEBUG
|
|
||||||
for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++)
|
|
||||||
{
|
|
||||||
BaseProcess* process = mPostProcessingSteps[a];
|
|
||||||
if( process->IsActive( pFlags))
|
|
||||||
{
|
|
||||||
process->SetupProperties( this );
|
|
||||||
process->ExecuteOnScene ( this );
|
|
||||||
}
|
}
|
||||||
if( !mScene)break;
|
#else
|
||||||
|
if (bExtraVerbose)DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
|
||||||
|
#endif // ! DEBUG
|
||||||
|
for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++)
|
||||||
|
{
|
||||||
|
BaseProcess* process = mPostProcessingSteps[a];
|
||||||
|
if( process->IsActive( pFlags))
|
||||||
|
{
|
||||||
|
process->SetupProperties( this );
|
||||||
|
process->ExecuteOnScene ( this );
|
||||||
|
}
|
||||||
|
if( !mScene)break;
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
|
||||||
#ifndef AI_BUILD_NO_VALIDATEDS_PROCESS
|
#ifndef AI_BUILD_NO_VALIDATEDS_PROCESS
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// if the extra verbose mode is active execute the
|
// if the extra verbose mode is active execute the
|
||||||
// VaidateDataStructureStep again after each step
|
// VaidateDataStructureStep again after each step
|
||||||
if (bExtraVerbose && a)
|
if (bExtraVerbose && a)
|
||||||
{
|
|
||||||
DefaultLogger::get()->debug("Extra verbose: revalidating data structures");
|
|
||||||
((ValidateDSProcess*)mPostProcessingSteps[0])->ExecuteOnScene (this);
|
|
||||||
if( !mScene)
|
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->error("Extra verbose: failed to revalidate data structures");
|
DefaultLogger::get()->debug("Extra verbose: revalidating data structures");
|
||||||
break;
|
((ValidateDSProcess*)mPostProcessingSteps[0])->ExecuteOnScene (this);
|
||||||
|
if( !mScene)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->error("Extra verbose: failed to revalidate data structures");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif // ! DEBUG
|
||||||
}
|
}
|
||||||
#endif // ! DEBUG
|
|
||||||
}
|
}
|
||||||
#ifdef _DEBUG
|
// if failed, extract the error string
|
||||||
if (bExtraVerbose)mScene->mFlags &= ~0x80000000;
|
else if( !mScene)mErrorString = imp->GetErrorText();
|
||||||
#endif // ! DEBUG
|
|
||||||
}
|
|
||||||
// if failed, extract the error string
|
|
||||||
else if( !mScene)mErrorString = imp->GetErrorText();
|
|
||||||
|
|
||||||
// clear any data allocated by post-process steps
|
// clear any data allocated by post-process steps
|
||||||
mPPShared->Clean();
|
mPPShared->Clean();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
|
#if (defined _MSC_VER) && (defined _CPPRTTI) && (defined _DEBUG)
|
||||||
|
|
||||||
|
// if we have RTTI get the full name of the exception that occured
|
||||||
|
mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
|
||||||
|
#else
|
||||||
|
mErrorString = std::string("std::exception: ") + e.what();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DefaultLogger::get()->error(mErrorString);
|
||||||
|
delete mScene;mScene = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// either successful or failure - the pointer expresses it anyways
|
// either successful or failure - the pointer expresses it anyways
|
||||||
return mScene;
|
return mScene;
|
||||||
|
|
|
@ -84,6 +84,12 @@ bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const
|
||||||
// Executes the post processing step on the given imported data.
|
// Executes the post processing step on the given imported data.
|
||||||
void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
|
void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
|
||||||
{
|
{
|
||||||
|
if (!pScene->mNumMeshes)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->debug("ImproveCacheLocalityProcess skipped; there are no meshes");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin");
|
DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin");
|
||||||
|
|
||||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
||||||
|
@ -102,7 +108,14 @@ void ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshN
|
||||||
// check whether the input data is valid ->
|
// check whether the input data is valid ->
|
||||||
// - there must be vertices and faces (haha)
|
// - there must be vertices and faces (haha)
|
||||||
// - all faces must be triangulated
|
// - all faces must be triangulated
|
||||||
if (!pMesh->HasFaces() || !pMesh->HasPositions())return;
|
if (!pMesh->HasFaces() || !pMesh->HasPositions())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->error("This algorithm works on triangle meshes only");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// find the input ACMR ...
|
// find the input ACMR ...
|
||||||
unsigned int* piFIFOStack = new unsigned int[this->configCacheDepth];
|
unsigned int* piFIFOStack = new unsigned int[this->configCacheDepth];
|
||||||
|
@ -116,26 +129,6 @@ void ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshN
|
||||||
const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces;
|
const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces;
|
||||||
for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace)
|
for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace)
|
||||||
{
|
{
|
||||||
if (3 != pcFace->mNumIndices)
|
|
||||||
{
|
|
||||||
DefaultLogger::get()->error("Unable to improve cache locality of non-triangulated faces");
|
|
||||||
delete[] piFIFOStack;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// although it has not been tested, I'm quite sure degenerated triangles
|
|
||||||
// would crash if the algorithm was applied to them
|
|
||||||
|
|
||||||
#if (defined _DEBUG)
|
|
||||||
if (pcFace->mIndices[0] == pcFace->mIndices[1] ||
|
|
||||||
pcFace->mIndices[2] == pcFace->mIndices[1] ||
|
|
||||||
pcFace->mIndices[2] == pcFace->mIndices[0])
|
|
||||||
{
|
|
||||||
DefaultLogger::get()->error("ImproveCacheLocalityProcess: There may be no degenerated triangles ");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (unsigned int qq = 0; qq < 3;++qq)
|
for (unsigned int qq = 0; qq < 3;++qq)
|
||||||
{
|
{
|
||||||
bool bInCache = false;
|
bool bInCache = false;
|
||||||
|
|
|
@ -109,6 +109,8 @@ void JoinVerticesProcess::Execute( aiScene* pScene)
|
||||||
DefaultLogger::get()->info(szBuff);
|
DefaultLogger::get()->info(szBuff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -183,12 +183,12 @@ void MD2Importer::InternReadFile( const std::string& pFile,
|
||||||
if( fileSize < sizeof(MD2::Header))
|
if( fileSize < sizeof(MD2::Header))
|
||||||
throw new ImportErrorException( "MD2 File is too small");
|
throw new ImportErrorException( "MD2 File is too small");
|
||||||
|
|
||||||
std::vector<unsigned char> mBuffer2(fileSize);
|
std::vector<uint8_t> mBuffer2(fileSize);
|
||||||
file->Read(&mBuffer2[0], 1, fileSize);
|
file->Read(&mBuffer2[0], 1, fileSize);
|
||||||
mBuffer = &mBuffer2[0];
|
mBuffer = &mBuffer2[0];
|
||||||
|
|
||||||
|
|
||||||
m_pcHeader = (const MD2::Header*)mBuffer;
|
m_pcHeader = (BE_NCONST MD2::Header*)mBuffer;
|
||||||
|
|
||||||
#ifdef AI_BUILD_BIG_ENDIAN
|
#ifdef AI_BUILD_BIG_ENDIAN
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
|
||||||
pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||||
|
|
||||||
// navigate to the begin of the frame data
|
// navigate to the begin of the frame data
|
||||||
const MD2::Frame* pcFrame = (const MD2::Frame*) ((uint8_t*)
|
BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*)
|
||||||
m_pcHeader + m_pcHeader->offsetFrames);
|
m_pcHeader + m_pcHeader->offsetFrames);
|
||||||
|
|
||||||
pcFrame += configFrameID;
|
pcFrame += configFrameID;
|
||||||
|
@ -239,11 +239,11 @@ void MD2Importer::InternReadFile( const std::string& pFile,
|
||||||
m_pcHeader + m_pcHeader->offsetTriangles);
|
m_pcHeader + m_pcHeader->offsetTriangles);
|
||||||
|
|
||||||
// navigate to the begin of the tex coords data
|
// navigate to the begin of the tex coords data
|
||||||
const MD2::TexCoord* pcTexCoords = (const MD2::TexCoord*) ((uint8_t*)
|
BE_NCONST MD2::TexCoord* pcTexCoords = (BE_NCONST MD2::TexCoord*) ((uint8_t*)
|
||||||
m_pcHeader + m_pcHeader->offsetTexCoords);
|
m_pcHeader + m_pcHeader->offsetTexCoords);
|
||||||
|
|
||||||
// navigate to the begin of the vertex data
|
// navigate to the begin of the vertex data
|
||||||
const MD2::Vertex* pcVerts = (const MD2::Vertex*) (pcFrame->vertices);
|
BE_NCONST MD2::Vertex* pcVerts = (BE_NCONST MD2::Vertex*) (pcFrame->vertices);
|
||||||
|
|
||||||
#ifdef AI_BUILD_BIG_ENDIAN
|
#ifdef AI_BUILD_BIG_ENDIAN
|
||||||
for (uint32_t i = 0; i< m_pcHeader->numTriangles)
|
for (uint32_t i = 0; i< m_pcHeader->numTriangles)
|
||||||
|
@ -410,14 +410,11 @@ void MD2Importer::InternReadFile( const std::string& pFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent];
|
aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent];
|
||||||
float u,v;
|
|
||||||
|
|
||||||
// the texture coordinates are absolute values but we
|
// the texture coordinates are absolute values but we
|
||||||
// need relative values between 0 and 1
|
// need relative values between 0 and 1
|
||||||
u = pcTexCoords[iIndex].s / fDivisorU;
|
pcOut.x = pcTexCoords[iIndex].s / fDivisorU;
|
||||||
v = pcTexCoords[iIndex].t / fDivisorV;
|
pcOut.y = 1.f- pcTexCoords[iIndex].t / fDivisorV;
|
||||||
pcOut.x = u;
|
|
||||||
pcOut.y = 1.0f - v; // FIXME: Is this correct for MD2?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIX: flip the face order for use with OpenGL
|
// FIX: flip the face order for use with OpenGL
|
||||||
|
|
|
@ -113,10 +113,10 @@ protected:
|
||||||
unsigned int configFrameID;
|
unsigned int configFrameID;
|
||||||
|
|
||||||
/** Header of the MD2 file */
|
/** Header of the MD2 file */
|
||||||
const MD2::Header* m_pcHeader;
|
BE_NCONST MD2::Header* m_pcHeader;
|
||||||
|
|
||||||
/** Buffer to hold the loaded file */
|
/** Buffer to hold the loaded file */
|
||||||
const unsigned char* mBuffer;
|
BE_NCONST uint8_t* mBuffer;
|
||||||
|
|
||||||
/** Size of the file, in bytes */
|
/** Size of the file, in bytes */
|
||||||
unsigned int fileSize;
|
unsigned int fileSize;
|
||||||
|
|
|
@ -107,7 +107,7 @@ void MD5Importer::InternReadFile(
|
||||||
if (!bHadMD5Mesh && !bHadMD5Anim)
|
if (!bHadMD5Mesh && !bHadMD5Anim)
|
||||||
throw new ImportErrorException("Failed to read valid data from this MD5");
|
throw new ImportErrorException("Failed to read valid data from this MD5");
|
||||||
|
|
||||||
if (!bHadMD5Mesh)pScene->mFlags |= AI_SCENE_FLAGS_ANIM_SKELETON_ONLY;
|
if (!bHadMD5Mesh)pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MD5Importer::LoadFileIntoMemory (IOStream* file)
|
void MD5Importer::LoadFileIntoMemory (IOStream* file)
|
||||||
|
|
|
@ -242,16 +242,16 @@ MaterialHelper::MaterialHelper()
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
MaterialHelper::~MaterialHelper()
|
MaterialHelper::~MaterialHelper()
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < this->mNumProperties;++i)
|
Clear();
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void MaterialHelper::Clear()
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < mNumProperties;++i)
|
||||||
{
|
{
|
||||||
// be careful ...
|
// delete this entry
|
||||||
if(NULL != this->mProperties[i])
|
delete mProperties[i];
|
||||||
{
|
|
||||||
delete[] this->mProperties[i]->mData;
|
|
||||||
delete this->mProperties[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
uint32_t MaterialHelper::ComputeHash()
|
uint32_t MaterialHelper::ComputeHash()
|
||||||
|
@ -282,7 +282,6 @@ aiReturn MaterialHelper::RemoveProperty (const char* pKey)
|
||||||
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey.data, pKey ))
|
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey.data, pKey ))
|
||||||
{
|
{
|
||||||
// delete this entry
|
// delete this entry
|
||||||
delete[] this->mProperties[i]->mData;
|
|
||||||
delete this->mProperties[i];
|
delete this->mProperties[i];
|
||||||
|
|
||||||
// collapse the array behind --.
|
// collapse the array behind --.
|
||||||
|
@ -318,7 +317,6 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
|
||||||
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey.data, pKey ))
|
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey.data, pKey ))
|
||||||
{
|
{
|
||||||
// delete this entry
|
// delete this entry
|
||||||
delete[] this->mProperties[i]->mData;
|
|
||||||
delete this->mProperties[i];
|
delete this->mProperties[i];
|
||||||
iOutIndex = i;
|
iOutIndex = i;
|
||||||
}
|
}
|
||||||
|
@ -402,8 +400,7 @@ void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest,
|
||||||
for (unsigned int q = 0; q < iOldNum;++q)
|
for (unsigned int q = 0; q < iOldNum;++q)
|
||||||
{
|
{
|
||||||
prop = pcDest->mProperties[q];
|
prop = pcDest->mProperties[q];
|
||||||
if (propSrc->mKey.length == prop->mKey.length &&
|
if (!ASSIMP_stricmp(propSrc->mKey.data,prop->mKey.data))
|
||||||
!ASSIMP_stricmp(propSrc->mKey.data,prop->mKey.data))
|
|
||||||
{
|
{
|
||||||
delete prop;
|
delete prop;
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,12 @@ public:
|
||||||
aiReturn RemoveProperty (const char* pKey);
|
aiReturn RemoveProperty (const char* pKey);
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Removes all properties from the material
|
||||||
|
*/
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Computes a hash (hopefully unique) from all material properties
|
/** Computes a hash (hopefully unique) from all material properties
|
||||||
* The hash value must be updated after material properties have
|
* The hash value must be updated after material properties have
|
||||||
|
|
|
@ -74,10 +74,19 @@ bool NFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
||||||
if( pos == std::string::npos)return false;
|
if( pos == std::string::npos)return false;
|
||||||
std::string extension = pFile.substr( pos);
|
std::string extension = pFile.substr( pos);
|
||||||
|
|
||||||
return !(extension.length() != 4 || extension[0] != '.' ||
|
// extensions: enff and nff
|
||||||
extension[1] != 'n' && extension[1] != 'N' ||
|
if (!extension.length() || extension[0] != '.')return false;
|
||||||
extension[2] != 'f' && extension[2] != 'F' ||
|
if (extension.length() == 4)
|
||||||
extension[3] != 'f' && extension[3] != 'F');
|
{
|
||||||
|
return !(extension[1] != 'n' && extension[1] != 'N' ||
|
||||||
|
extension[2] != 'f' && extension[2] != 'F' ||
|
||||||
|
extension[3] != 'f' && extension[3] != 'F');
|
||||||
|
}
|
||||||
|
else return !( extension.length() != 5 ||
|
||||||
|
extension[1] != 'e' && extension[1] != 'E' ||
|
||||||
|
extension[2] != 'n' && extension[2] != 'N' ||
|
||||||
|
extension[3] != 'f' && extension[3] != 'F' ||
|
||||||
|
extension[4] != 'f' && extension[4] != 'F');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -87,9 +96,9 @@ bool NFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#define AI_NFF_PARSE_TRIPLE(v) \
|
#define AI_NFF_PARSE_TRIPLE(v) \
|
||||||
AI_NFF_PARSE_FLOAT(v.x) \
|
AI_NFF_PARSE_FLOAT(v[0]) \
|
||||||
AI_NFF_PARSE_FLOAT(v.y) \
|
AI_NFF_PARSE_FLOAT(v[1]) \
|
||||||
AI_NFF_PARSE_FLOAT(v.z)
|
AI_NFF_PARSE_FLOAT(v[2])
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#define AI_NFF_PARSE_SHAPE_INFORMATION() \
|
#define AI_NFF_PARSE_SHAPE_INFORMATION() \
|
||||||
|
@ -125,252 +134,504 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
// the pointers below easier.
|
// the pointers below easier.
|
||||||
std::vector<MeshInfo> meshes;
|
std::vector<MeshInfo> meshes;
|
||||||
std::vector<MeshInfo> meshesWithNormals;
|
std::vector<MeshInfo> meshesWithNormals;
|
||||||
|
std::vector<MeshInfo> meshesWithUVCoords;
|
||||||
std::vector<MeshInfo> meshesLocked;
|
std::vector<MeshInfo> meshesLocked;
|
||||||
|
|
||||||
|
char line[4096];
|
||||||
|
const char* sz;
|
||||||
|
|
||||||
|
// camera parameters
|
||||||
|
aiVector3D camPos, camUp(0.f,1.f,0.f), camLookAt(0.f,0.f,1.f);
|
||||||
|
float angle;
|
||||||
|
aiVector2D resolution;
|
||||||
|
|
||||||
|
bool hasCam = false;
|
||||||
|
|
||||||
MeshInfo* currentMeshWithNormals = NULL;
|
MeshInfo* currentMeshWithNormals = NULL;
|
||||||
MeshInfo* currentMesh = NULL;
|
MeshInfo* currentMesh = NULL;
|
||||||
|
MeshInfo* currentMeshWithUVCoords = NULL;
|
||||||
|
|
||||||
ShadingInfo s; // current material info
|
ShadingInfo s; // current material info
|
||||||
|
|
||||||
// degree of tesselation
|
// degree of tesselation
|
||||||
unsigned int iTesselation = 4;
|
unsigned int iTesselation = 4;
|
||||||
|
|
||||||
char line[4096];
|
// some temporary variables we need to parse the file
|
||||||
const char* sz;
|
unsigned int sphere = 0,
|
||||||
unsigned int sphere = 0,cylinder = 0,cone = 0,numNamed = 0,
|
cylinder = 0,
|
||||||
dodecahedron = 0,octahedron = 0,tetrahedron = 0, hexahedron = 0;
|
cone = 0,
|
||||||
|
numNamed = 0,
|
||||||
|
dodecahedron = 0,
|
||||||
|
octahedron = 0,
|
||||||
|
tetrahedron = 0,
|
||||||
|
hexahedron = 0;
|
||||||
|
|
||||||
while (GetNextLine(buffer,line))
|
// lights imported from the file
|
||||||
|
std::vector<Light> lights;
|
||||||
|
|
||||||
|
// check whether this is the NFF2 file format
|
||||||
|
if (TokenMatch(buffer,"nff",3))
|
||||||
{
|
{
|
||||||
if ('p' == line[0])
|
// another NFF file format ... just a raw parser has been implemented
|
||||||
|
// no support for textures yet, I don't think it is worth the effort
|
||||||
|
// http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/nff/nff2.html
|
||||||
|
|
||||||
|
while (GetNextLine(buffer,line))
|
||||||
{
|
{
|
||||||
MeshInfo* out = NULL;
|
sz = line;
|
||||||
// 'pp' - polygon patch primitive
|
if (TokenMatch(sz,"version",7))
|
||||||
if ('p' == line[1])
|
|
||||||
{
|
{
|
||||||
if (meshesWithNormals.empty())
|
DefaultLogger::get()->info("NFF (alt.) file format: " + std::string(sz));
|
||||||
{
|
|
||||||
meshesWithNormals.push_back(MeshInfo(true));
|
|
||||||
currentMeshWithNormals = &meshesWithNormals.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
sz = &line[2];out = currentMeshWithNormals;
|
|
||||||
}
|
}
|
||||||
// 'p' - polygon primitive
|
else if (TokenMatch(sz,"viewpos",7))
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (meshes.empty())
|
AI_NFF_PARSE_TRIPLE(camPos);
|
||||||
{
|
hasCam = true;
|
||||||
meshes.push_back(MeshInfo(false));
|
|
||||||
currentMesh = &meshes.back();
|
|
||||||
}
|
|
||||||
sz = &line[1];out = currentMesh;
|
|
||||||
}
|
}
|
||||||
SkipSpaces(sz,&sz);
|
else if (TokenMatch(sz,"viewdir",7))
|
||||||
m = strtol10(sz);
|
|
||||||
|
|
||||||
// ---- flip the face order
|
|
||||||
out->vertices.resize(out->vertices.size()+m);
|
|
||||||
if (out == currentMeshWithNormals)
|
|
||||||
{
|
{
|
||||||
out->normals.resize(out->vertices.size());
|
AI_NFF_PARSE_TRIPLE(camLookAt);
|
||||||
|
hasCam = true;
|
||||||
}
|
}
|
||||||
for (unsigned int n = 0; n < m;++n)
|
else if (TokenMatch(sz,"//",2))
|
||||||
{
|
{
|
||||||
if(!GetNextLine(buffer,line))
|
// comment ...
|
||||||
{
|
DefaultLogger::get()->info(sz);
|
||||||
DefaultLogger::get()->error("NFF: Unexpected EOF was encountered");
|
}
|
||||||
continue;
|
else if (!IsSpace(*sz))
|
||||||
}
|
{
|
||||||
|
// must be a new object
|
||||||
|
meshes.push_back(MeshInfo(PatchType_Simple));
|
||||||
|
MeshInfo& mesh = meshes.back();
|
||||||
|
|
||||||
aiVector3D v; sz = &line[0];
|
if (!GetNextLine(buffer,line))
|
||||||
AI_NFF_PARSE_TRIPLE(v);
|
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read number of vertices");break;}
|
||||||
out->vertices[out->vertices.size()-n-1] = v;
|
|
||||||
|
|
||||||
if (out == currentMeshWithNormals)
|
SkipSpaces(line,&sz);
|
||||||
|
unsigned int num = ::strtol10(sz,&sz);
|
||||||
|
|
||||||
|
std::vector<aiVector3D> tempPositions;
|
||||||
|
std::vector<aiVector3D> outPositions;
|
||||||
|
mesh.vertices.reserve(num*3);
|
||||||
|
mesh.colors.reserve (num*3);
|
||||||
|
tempPositions.reserve(num);
|
||||||
|
for (unsigned int i = 0; i < num; ++i)
|
||||||
{
|
{
|
||||||
|
if (!GetNextLine(buffer,line))
|
||||||
|
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read vertices");break;}
|
||||||
|
|
||||||
|
sz = line;
|
||||||
|
aiVector3D v;
|
||||||
AI_NFF_PARSE_TRIPLE(v);
|
AI_NFF_PARSE_TRIPLE(v);
|
||||||
out->normals[out->vertices.size()-n-1] = v;
|
tempPositions.push_back(v);
|
||||||
}
|
}
|
||||||
}
|
if (!GetNextLine(buffer,line))
|
||||||
out->faces.push_back(m);
|
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read number of faces");break;}
|
||||||
}
|
|
||||||
// 'f' - shading information block
|
|
||||||
else if ('f' == line[0] && IsSpace(line[1]))
|
|
||||||
{
|
|
||||||
SkipSpaces(&line[1],&sz);
|
|
||||||
|
|
||||||
// read just the RGB colors, the rest is ignored for the moment
|
if (!num)throw new ImportErrorException("NFF2: There are zero vertices");
|
||||||
sz = fast_atof_move(sz, (float&)s.color.r);
|
|
||||||
SkipSpaces(&sz);
|
|
||||||
sz = fast_atof_move(sz, (float&)s.color.g);
|
|
||||||
SkipSpaces(&sz);
|
|
||||||
sz = fast_atof_move(sz, (float&)s.color.b);
|
|
||||||
|
|
||||||
// check whether we have this material already -
|
SkipSpaces(line,&sz);
|
||||||
// although we have the RRM-Step, this is necessary here.
|
num = ::strtol10(sz,&sz);
|
||||||
// otherwise we would generate hundreds of small meshes
|
mesh.faces.reserve(num);
|
||||||
// with just a few faces - this is surely never wanted.
|
|
||||||
currentMesh = currentMeshWithNormals = NULL;
|
for (unsigned int i = 0; i < num; ++i)
|
||||||
for (std::vector<MeshInfo>::iterator it = meshes.begin(), end = meshes.end();
|
|
||||||
it != end;++it)
|
|
||||||
{
|
|
||||||
if ((*it).bLocked)continue;
|
|
||||||
if ((*it).shader == s)
|
|
||||||
{
|
{
|
||||||
if ((*it).bHasNormals)currentMeshWithNormals = &(*it);
|
if (!GetNextLine(buffer,line))
|
||||||
else currentMesh = &(*it);
|
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read faces");break;}
|
||||||
|
|
||||||
|
SkipSpaces(line,&sz);
|
||||||
|
unsigned int idx, numIdx = ::strtol10(sz,&sz);
|
||||||
|
if (numIdx)
|
||||||
|
{
|
||||||
|
mesh.faces.push_back(numIdx);
|
||||||
|
for (unsigned int a = 0; a < numIdx;++a)
|
||||||
|
{
|
||||||
|
SkipSpaces(sz,&sz);
|
||||||
|
idx = ::strtol10(sz,&sz);
|
||||||
|
if (idx >= (unsigned int)tempPositions.size())
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->error("NFF2: Index overflow");
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
|
mesh.vertices.push_back(tempPositions[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkipSpaces(sz,&sz);
|
||||||
|
idx = ::strtol_cppstyle(sz,&sz);
|
||||||
|
aiColor4D clr;
|
||||||
|
clr.r = ((numIdx >> 8u) & 0xf) / 16.f;
|
||||||
|
clr.g = ((numIdx >> 4u) & 0xf) / 16.f;
|
||||||
|
clr.b = ((numIdx) & 0xf) / 16.f;
|
||||||
|
clr.a = 1.f;
|
||||||
|
for (unsigned int a = 0; a < numIdx;++a)
|
||||||
|
mesh.colors.push_back(clr);
|
||||||
|
}
|
||||||
|
if (!num)throw new ImportErrorException("NFF2: There are zero faces");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
camLookAt = camLookAt + camPos;
|
||||||
|
}
|
||||||
|
else // "Normal" Neutral file format that is quite more common
|
||||||
|
{
|
||||||
|
while (GetNextLine(buffer,line))
|
||||||
|
{
|
||||||
|
sz = line;
|
||||||
|
if ('p' == line[0] || TokenMatch(sz,"tpp",3))
|
||||||
|
{
|
||||||
|
MeshInfo* out = NULL;
|
||||||
|
|
||||||
|
// 'tpp' - texture polygon patch primitive
|
||||||
|
if ('t' == line[0])
|
||||||
|
{
|
||||||
|
if (meshesWithUVCoords.empty())
|
||||||
|
{
|
||||||
|
meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
|
||||||
|
currentMeshWithUVCoords = &meshesWithUVCoords.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
out = currentMeshWithUVCoords;
|
||||||
|
}
|
||||||
|
// 'pp' - polygon patch primitive
|
||||||
|
else if ('p' == line[1])
|
||||||
|
{
|
||||||
|
if (meshesWithNormals.empty())
|
||||||
|
{
|
||||||
|
meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
|
||||||
|
currentMeshWithNormals = &meshesWithNormals.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = &line[2];out = currentMeshWithNormals;
|
||||||
|
}
|
||||||
|
// 'p' - polygon primitive
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (meshes.empty())
|
||||||
|
{
|
||||||
|
meshes.push_back(MeshInfo(PatchType_Simple));
|
||||||
|
currentMesh = &meshes.back();
|
||||||
|
}
|
||||||
|
sz = &line[1];out = currentMesh;
|
||||||
|
}
|
||||||
|
SkipSpaces(sz,&sz);
|
||||||
|
m = strtol10(sz);
|
||||||
|
|
||||||
|
// ---- flip the face order
|
||||||
|
out->vertices.resize(out->vertices.size()+m);
|
||||||
|
if (out != currentMesh)
|
||||||
|
{
|
||||||
|
out->normals.resize(out->vertices.size());
|
||||||
|
}
|
||||||
|
if (out == currentMeshWithUVCoords)
|
||||||
|
{
|
||||||
|
out->uvs.resize(out->vertices.size());
|
||||||
|
}
|
||||||
|
for (unsigned int n = 0; n < m;++n)
|
||||||
|
{
|
||||||
|
if(!GetNextLine(buffer,line))
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->error("NFF: Unexpected EOF was encountered");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
aiVector3D v; sz = &line[0];
|
||||||
|
AI_NFF_PARSE_TRIPLE(v);
|
||||||
|
out->vertices[out->vertices.size()-n-1] = v;
|
||||||
|
|
||||||
|
if (out != currentMesh)
|
||||||
|
{
|
||||||
|
AI_NFF_PARSE_TRIPLE(v);
|
||||||
|
out->normals[out->vertices.size()-n-1] = v;
|
||||||
|
}
|
||||||
|
if (out == currentMeshWithUVCoords)
|
||||||
|
{
|
||||||
|
// FIX: in one test file this wraps over multiple lines
|
||||||
|
SkipSpaces(&sz);
|
||||||
|
if (IsLineEnd(*sz))
|
||||||
|
{
|
||||||
|
GetNextLine(buffer,line);
|
||||||
|
sz = line;
|
||||||
|
}
|
||||||
|
AI_NFF_PARSE_FLOAT(v.x);
|
||||||
|
SkipSpaces(&sz);
|
||||||
|
if (IsLineEnd(*sz))
|
||||||
|
{
|
||||||
|
GetNextLine(buffer,line);
|
||||||
|
sz = line;
|
||||||
|
}
|
||||||
|
AI_NFF_PARSE_FLOAT(v.y);
|
||||||
|
v.y = 1.f - v.y;
|
||||||
|
out->uvs[out->vertices.size()-n-1] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out->faces.push_back(m);
|
||||||
|
}
|
||||||
|
// 'f' - shading information block
|
||||||
|
else if (TokenMatch(sz,"f",1))
|
||||||
|
{
|
||||||
|
float d;
|
||||||
|
|
||||||
|
// read the RGB colors
|
||||||
|
AI_NFF_PARSE_TRIPLE(s.color);
|
||||||
|
|
||||||
|
// read the other properties
|
||||||
|
AI_NFF_PARSE_FLOAT(s.diffuse);
|
||||||
|
AI_NFF_PARSE_FLOAT(s.specular);
|
||||||
|
AI_NFF_PARSE_FLOAT(d); // skip shininess and transmittance
|
||||||
|
AI_NFF_PARSE_FLOAT(d);
|
||||||
|
AI_NFF_PARSE_FLOAT(s.refracti);
|
||||||
|
|
||||||
|
// if the next one is NOT a number we assume it is a texture file name
|
||||||
|
// this feature is used by some NFF files on the internet and it has
|
||||||
|
// been implemented as it can be really useful
|
||||||
|
SkipSpaces(&sz);
|
||||||
|
if (!IsNumeric(*sz))
|
||||||
|
{
|
||||||
|
// TODO: Support full file names with spaces and quotation marks ...
|
||||||
|
const char* p = sz;
|
||||||
|
while (!IsSpaceOrNewLine( *sz ))++sz;
|
||||||
|
|
||||||
|
unsigned int diff = (unsigned int)(sz-p);
|
||||||
|
if (diff)
|
||||||
|
{
|
||||||
|
s.texFile = std::string(p,diff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AI_NFF_PARSE_FLOAT(s.ambient); // optional
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether we have this material already -
|
||||||
|
// although we have the RRM-Step, this is necessary here.
|
||||||
|
// otherwise we would generate hundreds of small meshes
|
||||||
|
// with just a few faces - this is surely never wanted.
|
||||||
|
currentMesh = currentMeshWithNormals = currentMeshWithUVCoords = NULL;
|
||||||
|
for (std::vector<MeshInfo>::iterator it = meshes.begin(), end = meshes.end();
|
||||||
|
it != end;++it)
|
||||||
|
{
|
||||||
|
if ((*it).bLocked)continue;
|
||||||
|
if ((*it).shader == s)
|
||||||
|
{
|
||||||
|
switch ((*it).pType)
|
||||||
|
{
|
||||||
|
case PatchType_Normals:
|
||||||
|
currentMeshWithNormals = &(*it);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PatchType_Simple:
|
||||||
|
currentMesh = &(*it);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
currentMeshWithUVCoords = &(*it);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currentMesh)
|
||||||
|
{
|
||||||
|
meshes.push_back(MeshInfo(PatchType_Simple));
|
||||||
|
currentMesh = &meshes.back();
|
||||||
|
currentMesh->shader = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currentMeshWithNormals)
|
||||||
|
{
|
||||||
|
meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
|
||||||
|
currentMeshWithNormals = &meshesWithNormals.back();
|
||||||
|
currentMeshWithNormals->shader = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currentMeshWithUVCoords)
|
||||||
|
{
|
||||||
|
meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
|
||||||
|
currentMeshWithUVCoords = &meshesWithUVCoords.back();
|
||||||
|
currentMeshWithUVCoords->shader = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 'l' - light source
|
||||||
if (!currentMesh)
|
else if (TokenMatch(sz,"l",1))
|
||||||
{
|
{
|
||||||
meshes.push_back(MeshInfo(false));
|
lights.push_back(Light());
|
||||||
currentMesh = &meshes.back();
|
Light& light = lights.back();
|
||||||
currentMesh->shader = s;
|
|
||||||
|
AI_NFF_PARSE_TRIPLE(light.position);
|
||||||
|
AI_NFF_PARSE_FLOAT (light.intensity);
|
||||||
|
AI_NFF_PARSE_TRIPLE(light.color);
|
||||||
|
}
|
||||||
|
// 's' - sphere
|
||||||
|
else if (TokenMatch(sz,"s",1))
|
||||||
|
{
|
||||||
|
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||||
|
MeshInfo& currentMesh = meshesLocked.back();
|
||||||
|
currentMesh.shader = s;
|
||||||
|
|
||||||
|
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||||
|
|
||||||
|
// we don't need scaling or translation here - we do it in the node's transform
|
||||||
|
StandardShapes::MakeSphere(iTesselation, currentMesh.vertices);
|
||||||
|
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
||||||
|
|
||||||
|
// generate a name for the mesh
|
||||||
|
::sprintf(currentMesh.name,"sphere_%i",sphere++);
|
||||||
|
}
|
||||||
|
// 'dod' - dodecahedron
|
||||||
|
else if (TokenMatch(sz,"dod",3))
|
||||||
|
{
|
||||||
|
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||||
|
MeshInfo& currentMesh = meshesLocked.back();
|
||||||
|
currentMesh.shader = s;
|
||||||
|
|
||||||
|
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||||
|
|
||||||
|
// we don't need scaling or translation here - we do it in the node's transform
|
||||||
|
StandardShapes::MakeDodecahedron(currentMesh.vertices);
|
||||||
|
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
||||||
|
|
||||||
|
// generate a name for the mesh
|
||||||
|
::sprintf(currentMesh.name,"dodecahedron_%i",dodecahedron++);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentMeshWithNormals)
|
// 'oct' - octahedron
|
||||||
|
else if (TokenMatch(sz,"oct",3))
|
||||||
{
|
{
|
||||||
meshesWithNormals.push_back(MeshInfo(true));
|
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||||
currentMeshWithNormals = &meshesWithNormals.back();
|
MeshInfo& currentMesh = meshesLocked.back();
|
||||||
currentMeshWithNormals->shader = s;
|
currentMesh.shader = s;
|
||||||
|
|
||||||
|
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||||
|
|
||||||
|
// we don't need scaling or translation here - we do it in the node's transform
|
||||||
|
StandardShapes::MakeOctahedron(currentMesh.vertices);
|
||||||
|
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
||||||
|
|
||||||
|
// generate a name for the mesh
|
||||||
|
::sprintf(currentMesh.name,"octahedron_%i",octahedron++);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// 's' - sphere
|
|
||||||
else if ('s' == line[0] && IsSpace(line[1]))
|
|
||||||
{
|
|
||||||
meshesLocked.push_back(MeshInfo(false,true));
|
|
||||||
MeshInfo& currentMesh = meshesLocked.back();
|
|
||||||
currentMesh.shader = s;
|
|
||||||
|
|
||||||
sz = &line[1];
|
// 'tet' - tetrahedron
|
||||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
else if (TokenMatch(sz,"tet",3))
|
||||||
|
{
|
||||||
|
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||||
|
MeshInfo& currentMesh = meshesLocked.back();
|
||||||
|
currentMesh.shader = s;
|
||||||
|
|
||||||
// we don't need scaling or translation here - we do it in the node's transform
|
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||||
StandardShapes::MakeSphere(iTesselation, currentMesh.vertices);
|
|
||||||
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
||||||
|
|
||||||
// generate a name for the mesh
|
// we don't need scaling or translation here - we do it in the node's transform
|
||||||
::sprintf(currentMesh.name,"sphere_%i",sphere++);
|
StandardShapes::MakeTetrahedron(currentMesh.vertices);
|
||||||
}
|
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
||||||
// 'dod' - dodecahedron
|
|
||||||
else if (!strncmp(line,"dod",3) && IsSpace(line[3]))
|
|
||||||
{
|
|
||||||
meshesLocked.push_back(MeshInfo(false,true));
|
|
||||||
MeshInfo& currentMesh = meshesLocked.back();
|
|
||||||
currentMesh.shader = s;
|
|
||||||
|
|
||||||
sz = &line[4];
|
// generate a name for the mesh
|
||||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
::sprintf(currentMesh.name,"tetrahedron_%i",tetrahedron++);
|
||||||
|
}
|
||||||
|
|
||||||
// we don't need scaling or translation here - we do it in the node's transform
|
// 'hex' - hexahedron
|
||||||
StandardShapes::MakeDodecahedron(currentMesh.vertices);
|
else if (TokenMatch(sz,"hex",3))
|
||||||
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
{
|
||||||
|
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||||
|
MeshInfo& currentMesh = meshesLocked.back();
|
||||||
|
currentMesh.shader = s;
|
||||||
|
|
||||||
// generate a name for the mesh
|
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||||
::sprintf(currentMesh.name,"dodecahedron_%i",dodecahedron++);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'oct' - octahedron
|
// we don't need scaling or translation here - we do it in the node's transform
|
||||||
else if (!strncmp(line,"oct",3) && IsSpace(line[3]))
|
StandardShapes::MakeHexahedron(currentMesh.vertices);
|
||||||
{
|
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
||||||
meshesLocked.push_back(MeshInfo(false,true));
|
|
||||||
MeshInfo& currentMesh = meshesLocked.back();
|
|
||||||
currentMesh.shader = s;
|
|
||||||
|
|
||||||
sz = &line[4];
|
// generate a name for the mesh
|
||||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
::sprintf(currentMesh.name,"hexahedron_%i",hexahedron++);
|
||||||
|
}
|
||||||
|
// 'c' - cone
|
||||||
|
else if (TokenMatch(sz,"c",1))
|
||||||
|
{
|
||||||
|
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||||
|
MeshInfo& currentMesh = meshes.back();
|
||||||
|
currentMesh.shader = s;
|
||||||
|
|
||||||
// we don't need scaling or translation here - we do it in the node's transform
|
aiVector3D center1, center2; float radius1, radius2;
|
||||||
StandardShapes::MakeOctahedron(currentMesh.vertices);
|
AI_NFF_PARSE_TRIPLE(center1);
|
||||||
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
AI_NFF_PARSE_FLOAT(radius1);
|
||||||
|
AI_NFF_PARSE_TRIPLE(center2);
|
||||||
|
AI_NFF_PARSE_FLOAT(radius2);
|
||||||
|
|
||||||
// generate a name for the mesh
|
// compute the center point of the cone/cylinder
|
||||||
::sprintf(currentMesh.name,"octahedron_%i",octahedron++);
|
center2 = (center2-center1)/2.f;
|
||||||
}
|
currentMesh.center = center1+center2;
|
||||||
|
center1 = -center2;
|
||||||
|
|
||||||
// 'tet' - tetrahedron
|
// generate the cone - it consists of simple triangles
|
||||||
else if (!strncmp(line,"tet",3) && IsSpace(line[3]))
|
StandardShapes::MakeCone(center1, radius1, center2, radius2, iTesselation, currentMesh.vertices);
|
||||||
{
|
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
||||||
meshesLocked.push_back(MeshInfo(false,true));
|
|
||||||
MeshInfo& currentMesh = meshesLocked.back();
|
|
||||||
currentMesh.shader = s;
|
|
||||||
|
|
||||||
sz = &line[4];
|
// generate a name for the mesh
|
||||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
if (radius1 != radius2)
|
||||||
|
::sprintf(currentMesh.name,"cone_%i",cone++);
|
||||||
// we don't need scaling or translation here - we do it in the node's transform
|
else ::sprintf(currentMesh.name,"cylinder_%i",cylinder++);
|
||||||
StandardShapes::MakeTetrahedron(currentMesh.vertices);
|
}
|
||||||
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
// 'tess' - tesselation
|
||||||
|
else if (TokenMatch(sz,"tess",4))
|
||||||
// generate a name for the mesh
|
{
|
||||||
::sprintf(currentMesh.name,"tetrahedron_%i",tetrahedron++);
|
SkipSpaces(&sz);
|
||||||
}
|
iTesselation = strtol10(sz);
|
||||||
|
}
|
||||||
// 'hex' - hexahedron
|
// 'from' - camera position
|
||||||
else if (!strncmp(line,"hex",3) && IsSpace(line[3]))
|
else if (TokenMatch(sz,"from",4))
|
||||||
{
|
{
|
||||||
meshesLocked.push_back(MeshInfo(false,true));
|
AI_NFF_PARSE_TRIPLE(camPos);
|
||||||
MeshInfo& currentMesh = meshesLocked.back();
|
hasCam = true;
|
||||||
currentMesh.shader = s;
|
}
|
||||||
|
// 'at' - camera look-at vector
|
||||||
sz = &line[4];
|
else if (TokenMatch(sz,"at",2))
|
||||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
{
|
||||||
|
AI_NFF_PARSE_TRIPLE(camLookAt);
|
||||||
// we don't need scaling or translation here - we do it in the node's transform
|
hasCam = true;
|
||||||
StandardShapes::MakeHexahedron(currentMesh.vertices);
|
}
|
||||||
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
// 'up' - camera up vector
|
||||||
|
else if (TokenMatch(sz,"up",2))
|
||||||
// generate a name for the mesh
|
{
|
||||||
::sprintf(currentMesh.name,"hexahedron_%i",hexahedron++);
|
AI_NFF_PARSE_TRIPLE(camUp);
|
||||||
}
|
hasCam = true;
|
||||||
|
}
|
||||||
// 'tess' - tesselation
|
// 'angle' - (half?) camera field of view
|
||||||
else if (!strncmp(line,"tess",4) && IsSpace(line[4]))
|
else if (TokenMatch(sz,"angle",5))
|
||||||
{
|
{
|
||||||
sz = &line[5];SkipSpaces(&sz);
|
AI_NFF_PARSE_FLOAT(angle);
|
||||||
iTesselation = strtol10(sz);
|
hasCam = true;
|
||||||
}
|
}
|
||||||
// 'c' - cone
|
// 'resolution' - used to compute the screen aspect
|
||||||
else if ('c' == line[0] && IsSpace(line[1]))
|
else if (TokenMatch(sz,"resolution",10))
|
||||||
{
|
{
|
||||||
meshesLocked.push_back(MeshInfo(false,true));
|
AI_NFF_PARSE_FLOAT(resolution.x);
|
||||||
MeshInfo& currentMesh = meshes.back();
|
AI_NFF_PARSE_FLOAT(resolution.y);
|
||||||
currentMesh.shader = s;
|
hasCam = true;
|
||||||
|
}
|
||||||
sz = &line[1];
|
// 'pb' - bezier patch. Not supported yet
|
||||||
aiVector3D center1, center2; float radius1, radius2;
|
else if (TokenMatch(sz,"pb",2))
|
||||||
AI_NFF_PARSE_TRIPLE(center1);
|
{
|
||||||
AI_NFF_PARSE_FLOAT(radius1);
|
DefaultLogger::get()->error("NFF: Encountered unsupported ID: bezier patch");
|
||||||
AI_NFF_PARSE_TRIPLE(center2);
|
}
|
||||||
AI_NFF_PARSE_FLOAT(radius2);
|
// 'pn' - NURBS. Not supported yet
|
||||||
|
else if (TokenMatch(sz,"pn",2) || TokenMatch(sz,"pnn",3))
|
||||||
// compute the center point of the cone/cylinder
|
{
|
||||||
center2 = (center2-center1)/2.f;
|
DefaultLogger::get()->error("NFF: Encountered unsupported ID: NURBS");
|
||||||
currentMesh.center = center1+center2;
|
}
|
||||||
center1 = -center2;
|
// '' - comment
|
||||||
|
else if ('#' == line[0])
|
||||||
// generate the cone - it consists of simple triangles
|
{
|
||||||
StandardShapes::MakeCone(center1, radius1, center2, radius2, iTesselation, currentMesh.vertices);
|
const char* sz;SkipSpaces(&line[1],&sz);
|
||||||
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz);
|
||||||
|
}
|
||||||
// generate a name for the mesh
|
|
||||||
if (radius1 != radius2)
|
|
||||||
::sprintf(currentMesh.name,"cone_%i",cone++);
|
|
||||||
else ::sprintf(currentMesh.name,"cylinder_%i",cylinder++);
|
|
||||||
}
|
|
||||||
// '#' - comment
|
|
||||||
else if ('#' == line[0])
|
|
||||||
{
|
|
||||||
const char* sz;SkipSpaces(&line[1],&sz);
|
|
||||||
if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy all arrays into one large
|
// copy all arrays into one large
|
||||||
meshes.reserve(meshes.size()+meshesLocked.size()+meshesWithNormals.size());
|
meshes.reserve (meshes.size()+meshesLocked.size()+meshesWithNormals.size()+meshesWithUVCoords.size());
|
||||||
meshes.insert(meshes.end(),meshesLocked.begin(),meshesLocked.end());
|
meshes.insert (meshes.end(),meshesLocked.begin(),meshesLocked.end());
|
||||||
meshes.insert(meshes.end(),meshesWithNormals.begin(),meshesWithNormals.end());
|
meshes.insert (meshes.end(),meshesWithNormals.begin(),meshesWithNormals.end());
|
||||||
|
meshes.insert (meshes.end(),meshesWithUVCoords.begin(),meshesWithUVCoords.end());
|
||||||
|
|
||||||
// now generate output meshes. first find out how many meshes we'll need
|
// now generate output meshes. first find out how many meshes we'll need
|
||||||
std::vector<MeshInfo>::const_iterator it = meshes.begin(), end = meshes.end();
|
std::vector<MeshInfo>::const_iterator it = meshes.begin(), end = meshes.end();
|
||||||
|
@ -388,7 +649,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
// sub nodes for named objects such as spheres and cones.
|
// sub nodes for named objects such as spheres and cones.
|
||||||
aiNode* const root = new aiNode();
|
aiNode* const root = new aiNode();
|
||||||
root->mName.Set("<NFF_Root>");
|
root->mName.Set("<NFF_Root>");
|
||||||
root->mNumChildren = numNamed;
|
root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int) lights.size();
|
||||||
root->mNumMeshes = pScene->mNumMeshes-numNamed;
|
root->mNumMeshes = pScene->mNumMeshes-numNamed;
|
||||||
|
|
||||||
aiNode** ppcChildren;
|
aiNode** ppcChildren;
|
||||||
|
@ -398,6 +659,49 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
if (root->mNumChildren)
|
if (root->mNumChildren)
|
||||||
ppcChildren = root->mChildren = new aiNode*[root->mNumChildren];
|
ppcChildren = root->mChildren = new aiNode*[root->mNumChildren];
|
||||||
|
|
||||||
|
// generate the camera
|
||||||
|
if (hasCam)
|
||||||
|
{
|
||||||
|
aiNode* nd = *ppcChildren = new aiNode();
|
||||||
|
nd->mName.Set("<NFF_Camera>");
|
||||||
|
nd->mParent = root;
|
||||||
|
|
||||||
|
// allocate the camera in the scene
|
||||||
|
pScene->mNumCameras = 1;
|
||||||
|
pScene->mCameras = new aiCamera*[1];
|
||||||
|
aiCamera* c = pScene->mCameras[0] = new aiCamera;
|
||||||
|
|
||||||
|
c->mName = nd->mName; // make sure the names are identical
|
||||||
|
c->mHorizontalFOV = AI_DEG_TO_RAD( angle );
|
||||||
|
c->mLookAt = camLookAt - camPos;
|
||||||
|
c->mPosition = camPos;
|
||||||
|
c->mUp = camUp;
|
||||||
|
c->mAspect = resolution.x / resolution.y;
|
||||||
|
++ppcChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate light sources
|
||||||
|
if (!lights.empty())
|
||||||
|
{
|
||||||
|
pScene->mNumLights = (unsigned int)lights.size();
|
||||||
|
pScene->mLights = new aiLight*[pScene->mNumLights];
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren)
|
||||||
|
{
|
||||||
|
const Light& l = lights[i];
|
||||||
|
|
||||||
|
aiNode* nd = *ppcChildren = new aiNode();
|
||||||
|
nd->mParent = root;
|
||||||
|
|
||||||
|
nd->mName.length = ::sprintf(nd->mName.data,"<NFF_Light%i>",i);
|
||||||
|
|
||||||
|
// allocate the light in the scene data structure
|
||||||
|
aiLight* out = pScene->mLights[i] = new aiLight();
|
||||||
|
out->mName = nd->mName; // make sure the names are identical
|
||||||
|
out->mType = aiLightSource_POINT;
|
||||||
|
out->mColorDiffuse = out->mColorSpecular = l.color * l.intensity;
|
||||||
|
out->mPosition = l.position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!pScene->mNumMeshes)throw new ImportErrorException("NFF: No meshes loaded");
|
if (!pScene->mNumMeshes)throw new ImportErrorException("NFF: No meshes loaded");
|
||||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||||
|
@ -436,14 +740,38 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
|
|
||||||
// copy vertex positions
|
// copy vertex positions
|
||||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||||
::memcpy(mesh->mVertices,&src.vertices[0],sizeof(aiVector3D)*mesh->mNumVertices);
|
::memcpy(mesh->mVertices,&src.vertices[0],
|
||||||
if (src.bHasNormals)
|
sizeof(aiVector3D)*mesh->mNumVertices);
|
||||||
|
|
||||||
|
// NFF2: there could be vertex colors
|
||||||
|
if (!src.colors.empty())
|
||||||
|
{
|
||||||
|
ai_assert(src.colors.size() == src.vertices.size());
|
||||||
|
|
||||||
|
// copy vertex colors
|
||||||
|
mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
|
||||||
|
::memcpy(mesh->mColors[0],&src.colors[0],
|
||||||
|
sizeof(aiColor4D)*mesh->mNumVertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src.pType != PatchType_Simple)
|
||||||
{
|
{
|
||||||
ai_assert(src.normals.size() == src.vertices.size());
|
ai_assert(src.normals.size() == src.vertices.size());
|
||||||
|
|
||||||
// copy normal vectors
|
// copy normal vectors
|
||||||
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
||||||
::memcpy(mesh->mNormals,&src.normals[0],sizeof(aiVector3D)*mesh->mNumVertices);
|
::memcpy(mesh->mNormals,&src.normals[0],
|
||||||
|
sizeof(aiVector3D)*mesh->mNumVertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src.pType == PatchType_UVAndNormals)
|
||||||
|
{
|
||||||
|
ai_assert(src.uvs.size() == src.vertices.size());
|
||||||
|
|
||||||
|
// copy texture coordinates
|
||||||
|
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
||||||
|
::memcpy(mesh->mTextureCoords[0],&src.uvs[0],
|
||||||
|
sizeof(aiVector3D)*mesh->mNumVertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate faces
|
// generate faces
|
||||||
|
@ -459,8 +787,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a material for the mesh
|
// generate a material for the mesh
|
||||||
MaterialHelper* pcMat = (MaterialHelper*)(pScene->
|
MaterialHelper* pcMat = (MaterialHelper*)(pScene->mMaterials[m] = new MaterialHelper());
|
||||||
mMaterials[m] = new MaterialHelper());
|
|
||||||
|
|
||||||
mesh->mMaterialIndex = m++;
|
mesh->mMaterialIndex = m++;
|
||||||
|
|
||||||
|
@ -468,8 +795,16 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
s.Set(AI_DEFAULT_MATERIAL_NAME);
|
s.Set(AI_DEFAULT_MATERIAL_NAME);
|
||||||
pcMat->AddProperty(&s, AI_MATKEY_NAME);
|
pcMat->AddProperty(&s, AI_MATKEY_NAME);
|
||||||
|
|
||||||
pcMat->AddProperty(&src.shader.color,1,AI_MATKEY_COLOR_DIFFUSE);
|
aiColor3D c = src.shader.color * src.shader.diffuse;
|
||||||
pcMat->AddProperty(&src.shader.color,1,AI_MATKEY_COLOR_SPECULAR);
|
pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||||
|
c = src.shader.color * src.shader.specular;
|
||||||
|
pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
|
||||||
|
|
||||||
|
if (src.shader.texFile.length())
|
||||||
|
{
|
||||||
|
s.Set(src.shader.texFile);
|
||||||
|
pcMat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pScene->mRootNode = root;
|
pScene->mRootNode = root;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ protected:
|
||||||
*/
|
*/
|
||||||
void GetExtensionList(std::string& append)
|
void GetExtensionList(std::string& append)
|
||||||
{
|
{
|
||||||
append.append("*.nff");
|
append.append("*.nff;*.enff");
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
@ -95,35 +95,71 @@ private:
|
||||||
struct ShadingInfo
|
struct ShadingInfo
|
||||||
{
|
{
|
||||||
ShadingInfo()
|
ShadingInfo()
|
||||||
: color(0.6f,0.6f,0.6f,1.0f)
|
: color(0.6f,0.6f,0.6f)
|
||||||
|
, diffuse (1.f)
|
||||||
|
, specular (1.f)
|
||||||
|
, ambient (0.1f)
|
||||||
|
, refracti (1.f)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
aiColor4D color;
|
aiColor3D color;
|
||||||
//float diffuse, specular; --- not implemented yet
|
float diffuse, specular, ambient, refracti;
|
||||||
|
|
||||||
|
std::string texFile;
|
||||||
|
|
||||||
|
// shininess is ignored for the moment
|
||||||
bool operator == (const ShadingInfo& other) const
|
bool operator == (const ShadingInfo& other) const
|
||||||
{return color == other.color;}
|
{
|
||||||
|
return color == other.color &&
|
||||||
|
diffuse == other.diffuse &&
|
||||||
|
specular == other.specular &&
|
||||||
|
ambient == other.ambient &&
|
||||||
|
refracti == other.refracti &&
|
||||||
|
texFile == other.texFile;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// describes a NFF light source
|
||||||
|
struct Light
|
||||||
|
{
|
||||||
|
Light()
|
||||||
|
: color (1.f,1.f,1.f)
|
||||||
|
, intensity (1.f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
aiVector3D position;
|
||||||
|
float intensity;
|
||||||
|
aiColor3D color;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PatchType
|
||||||
|
{
|
||||||
|
PatchType_Simple = 0x0,
|
||||||
|
PatchType_Normals = 0x1,
|
||||||
|
PatchType_UVAndNormals = 0x2
|
||||||
};
|
};
|
||||||
|
|
||||||
// describes a NFF mesh
|
// describes a NFF mesh
|
||||||
struct MeshInfo
|
struct MeshInfo
|
||||||
{
|
{
|
||||||
MeshInfo(bool bHN, bool bL = false)
|
MeshInfo(PatchType _pType, bool bL = false)
|
||||||
: bHasNormals(bHN)
|
: pType(_pType)
|
||||||
, bLocked(bL)
|
, bLocked(bL)
|
||||||
{
|
{
|
||||||
name[0] = '\0'; // by default meshes are unnamed
|
name[0] = '\0'; // by default meshes are unnamed
|
||||||
}
|
}
|
||||||
|
|
||||||
ShadingInfo shader;
|
ShadingInfo shader;
|
||||||
bool bHasNormals, bLocked;
|
PatchType pType;
|
||||||
|
bool bLocked;
|
||||||
|
|
||||||
// for spheres, cones and cylinders: center point of the object
|
// for spheres, cones and cylinders: center point of the object
|
||||||
aiVector3D center, radius;
|
aiVector3D center, radius;
|
||||||
|
|
||||||
char name[128];
|
char name[128];
|
||||||
|
|
||||||
std::vector<aiVector3D> vertices, normals;
|
std::vector<aiVector3D> vertices, normals, uvs;
|
||||||
|
std::vector<aiColor4D> colors; // for NFF2
|
||||||
std::vector<unsigned int> faces;
|
std::vector<unsigned int> faces;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -109,8 +109,6 @@ void OFFImporter::InternReadFile( const std::string& pFile,
|
||||||
|
|
||||||
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = 1 ];
|
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = 1 ];
|
||||||
aiMesh* mesh = pScene->mMeshes[0] = new aiMesh();
|
aiMesh* mesh = pScene->mMeshes[0] = new aiMesh();
|
||||||
mesh->mNumVertices = numFaces*3;
|
|
||||||
aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
|
||||||
aiFace* faces = mesh->mFaces = new aiFace [mesh->mNumFaces = numFaces];
|
aiFace* faces = mesh->mFaces = new aiFace [mesh->mNumFaces = numFaces];
|
||||||
|
|
||||||
std::vector<aiVector3D> tempPositions(numVertices);
|
std::vector<aiVector3D> tempPositions(numVertices);
|
||||||
|
@ -131,21 +129,43 @@ void OFFImporter::InternReadFile( const std::string& pFile,
|
||||||
fast_atof_move(sz,(float&)v.z);
|
fast_atof_move(sz,(float&)v.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now read all faces lines
|
|
||||||
for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;++i)
|
// First find out how many vertices we'll need
|
||||||
|
const char* old = buffer;
|
||||||
|
for (unsigned int i = 0; i< mesh->mNumFaces;++i)
|
||||||
{
|
{
|
||||||
if(!GetNextLine(buffer,line))
|
if(!GetNextLine(buffer,line))
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->error("OFF: The number of faces in the header is incorrect");
|
DefaultLogger::get()->error("OFF: The number of faces in the header is incorrect");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
unsigned int idx;sz = line;SkipSpaces(&sz);
|
sz = line;SkipSpaces(&sz);
|
||||||
if(!(faces->mNumIndices = strtol10(sz,&sz)) || faces->mNumIndices > 100)
|
if(!(faces->mNumIndices = strtol10(sz,&sz)) || faces->mNumIndices > 9)
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->error("OFF: Faces with zero indices aren't allowed");
|
DefaultLogger::get()->error("OFF: Faces with zero indices aren't allowed");
|
||||||
--mesh->mNumFaces;
|
--mesh->mNumFaces;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
mesh->mNumVertices += faces->mNumIndices;
|
||||||
|
++faces;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mesh->mNumVertices)
|
||||||
|
throw new ImportErrorException("OFF: There are no valid faces");
|
||||||
|
|
||||||
|
// allocate storage for the output vertices
|
||||||
|
aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||||
|
|
||||||
|
// second: now parse all face indices
|
||||||
|
buffer = old;faces = mesh->mFaces;
|
||||||
|
for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;)
|
||||||
|
{
|
||||||
|
if(!GetNextLine(buffer,line))break;
|
||||||
|
|
||||||
|
unsigned int idx;
|
||||||
|
sz = line;SkipSpaces(&sz);
|
||||||
|
if(!(idx = strtol10(sz,&sz)) || idx > 9)
|
||||||
|
continue;
|
||||||
|
|
||||||
faces->mIndices = new unsigned int [faces->mNumIndices];
|
faces->mIndices = new unsigned int [faces->mNumIndices];
|
||||||
for (unsigned int m = 0; m < faces->mNumIndices;++m)
|
for (unsigned int m = 0; m < faces->mNumIndices;++m)
|
||||||
|
@ -156,10 +176,10 @@ void OFFImporter::InternReadFile( const std::string& pFile,
|
||||||
DefaultLogger::get()->error("OFF: Vertex index is out of range");
|
DefaultLogger::get()->error("OFF: Vertex index is out of range");
|
||||||
idx = numVertices-1;
|
idx = numVertices-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
faces->mIndices[m] = p++;
|
faces->mIndices[m] = p++;
|
||||||
*verts++ = tempPositions[idx];
|
*verts++ = tempPositions[idx];
|
||||||
}
|
}
|
||||||
|
++i;
|
||||||
++faces;
|
++faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,23 +48,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
|
// some array offsets
|
||||||
|
#define AI_PTVS_VERTEX 0x0
|
||||||
|
#define AI_PTVS_FACE 0x1
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
PretransformVertices::PretransformVertices()
|
PretransformVertices::PretransformVertices()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Destructor, private as well
|
// Destructor, private as well
|
||||||
PretransformVertices::~PretransformVertices()
|
PretransformVertices::~PretransformVertices()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Returns whether the processing step is present in the given flag field.
|
// Returns whether the processing step is present in the given flag field.
|
||||||
bool PretransformVertices::IsActive( unsigned int pFlags) const
|
bool PretransformVertices::IsActive( unsigned int pFlags) const
|
||||||
{
|
{
|
||||||
return (pFlags & aiProcess_PreTransformVertices) != 0;
|
return (pFlags & aiProcess_PreTransformVertices) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Count the number of nodes
|
// Count the number of nodes
|
||||||
unsigned int CountNodes( aiNode* pcNode )
|
unsigned int CountNodes( aiNode* pcNode )
|
||||||
|
@ -76,14 +83,20 @@ unsigned int CountNodes( aiNode* pcNode )
|
||||||
}
|
}
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Get a bitwise combination identifying the vertex format of a mesh
|
// Get a bitwise combination identifying the vertex format of a mesh
|
||||||
unsigned int GetMeshVFormat(aiMesh* pcMesh)
|
unsigned int GetMeshVFormat(aiMesh* pcMesh)
|
||||||
{
|
{
|
||||||
if (0xdeadbeef == pcMesh->mNumUVComponents[0])
|
// the vertex format is stored in aiMesh::mBones for later retrieval.
|
||||||
return pcMesh->mNumUVComponents[1];
|
// there isn't a good reason to compute it a few hundred times
|
||||||
|
// from scratch. The pointer is unused as animations are lost
|
||||||
|
// during PretransformVertices.
|
||||||
|
if (pcMesh->mBones)
|
||||||
|
return (unsigned int)pcMesh->mBones;
|
||||||
|
|
||||||
unsigned int iRet = 0;
|
unsigned int iRet = 0;
|
||||||
|
ai_assert(NULL != pcMesh->mVertices);
|
||||||
|
|
||||||
// normals
|
// normals
|
||||||
if (pcMesh->HasNormals())iRet |= 0x1;
|
if (pcMesh->HasNormals())iRet |= 0x1;
|
||||||
|
@ -92,23 +105,25 @@ unsigned int GetMeshVFormat(aiMesh* pcMesh)
|
||||||
|
|
||||||
// texture coordinates
|
// texture coordinates
|
||||||
unsigned int p = 0;
|
unsigned int p = 0;
|
||||||
ai_assert(4 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
|
ai_assert(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
|
||||||
while (pcMesh->HasTextureCoords(p))
|
while (pcMesh->HasTextureCoords(p))
|
||||||
{
|
{
|
||||||
iRet |= (0x100 << p++);
|
iRet |= (0x100 << p);
|
||||||
if (3 == pcMesh->mNumUVComponents[p])
|
if (3 == pcMesh->mNumUVComponents[p])
|
||||||
iRet |= (0x1000 << p++);
|
iRet |= (0x10000 << p);
|
||||||
|
|
||||||
|
++p;
|
||||||
}
|
}
|
||||||
// vertex colors
|
// vertex colors
|
||||||
p = 0;
|
p = 0;
|
||||||
while (pcMesh->HasVertexColors(p))iRet |= (0x10000 << p++);
|
ai_assert(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
|
||||||
|
while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++);
|
||||||
|
|
||||||
// store the value for later use
|
// store the value for later use
|
||||||
pcMesh->mNumUVComponents[0] = 0xdeadbeef;
|
pcMesh->mBones = (aiBone**)iRet;
|
||||||
pcMesh->mNumUVComponents[1] = iRet;
|
|
||||||
|
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Count the number of vertices in the whole scene and a given
|
// Count the number of vertices in the whole scene and a given
|
||||||
// material index
|
// material index
|
||||||
|
@ -132,9 +147,6 @@ void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define AI_PTVS_VERTEX 0x0
|
|
||||||
#define AI_PTVS_FACE 0x1
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Collect vertex/face data
|
// Collect vertex/face data
|
||||||
void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
||||||
|
@ -157,11 +169,14 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
||||||
aiMatrix4x4 mWorldIT = pcNode->mTransformation;
|
aiMatrix4x4 mWorldIT = pcNode->mTransformation;
|
||||||
mWorldIT.Inverse().Transpose();
|
mWorldIT.Inverse().Transpose();
|
||||||
|
|
||||||
|
// TODO: implement Inverse() for aiMatrix3x3
|
||||||
|
aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
|
||||||
|
|
||||||
// copy normals, transform them to worldspace
|
// copy normals, transform them to worldspace
|
||||||
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
|
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
|
||||||
{
|
{
|
||||||
pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] =
|
pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] =
|
||||||
mWorldIT * pcMesh->mNormals[n];
|
m * pcMesh->mNormals[n];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (iVFormat & 0x2)
|
if (iVFormat & 0x2)
|
||||||
|
@ -185,7 +200,7 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
p = 0;
|
p = 0;
|
||||||
while (iVFormat & (0x10000 << p))
|
while (iVFormat & (0x1000000 << p))
|
||||||
{
|
{
|
||||||
// copy vertex colors
|
// copy vertex colors
|
||||||
memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX],
|
memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX],
|
||||||
|
@ -213,6 +228,23 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
||||||
// just make sure the array won't be deleted by the
|
// just make sure the array won't be deleted by the
|
||||||
// aiFace destructor ...
|
// aiFace destructor ...
|
||||||
pcMesh->mFaces[planck].mIndices = NULL;
|
pcMesh->mFaces[planck].mIndices = NULL;
|
||||||
|
|
||||||
|
// FIX: update the mPrimitiveTypes member of the mesh
|
||||||
|
switch (pcMesh->mFaces[planck].mNumIndices)
|
||||||
|
{
|
||||||
|
case 0x1:
|
||||||
|
pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
||||||
|
break;
|
||||||
|
case 0x2:
|
||||||
|
pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
||||||
|
break;
|
||||||
|
case 0x3:
|
||||||
|
pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
||||||
|
break;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices;
|
aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices;
|
||||||
aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces;
|
aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces;
|
||||||
|
@ -225,11 +257,12 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Get a list of all vertex formats that occur for a given material index
|
// Get a list of all vertex formats that occur for a given material index
|
||||||
// The output list contains duplicate elements
|
// The output list contains duplicate elements
|
||||||
void GetVFormatList( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
void GetVFormatList( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
||||||
std::list<unsigned int>& aiOut)
|
std::list<unsigned int>& aiOut)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
|
for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
|
||||||
{
|
{
|
||||||
|
@ -245,13 +278,14 @@ void GetVFormatList( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Compute the absolute transformation matrices of each node
|
// Compute the absolute transformation matrices of each node
|
||||||
void ComputeAbsoluteTransform( aiNode* pcNode )
|
void ComputeAbsoluteTransform( aiNode* pcNode )
|
||||||
{
|
{
|
||||||
if (pcNode->mParent)
|
if (pcNode->mParent)
|
||||||
{
|
{
|
||||||
pcNode->mTransformation = pcNode->mTransformation*pcNode->mParent->mTransformation;
|
pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
|
for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
|
||||||
|
@ -260,18 +294,37 @@ void ComputeAbsoluteTransform( aiNode* pcNode )
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Executes the post processing step on the given imported data.
|
// Executes the post processing step on the given imported data.
|
||||||
void PretransformVertices::Execute( aiScene* pScene)
|
void PretransformVertices::Execute( aiScene* pScene)
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->debug("PretransformVerticesProcess begin");
|
DefaultLogger::get()->debug("PretransformVerticesProcess begin");
|
||||||
|
|
||||||
|
const unsigned int iOldMeshes = pScene->mNumMeshes;
|
||||||
|
const unsigned int iOldAnimationChannels = pScene->mNumAnimations;
|
||||||
|
const unsigned int iOldNodes = CountNodes(pScene->mRootNode);
|
||||||
|
|
||||||
// first compute absolute transformation matrices for all nodes
|
// first compute absolute transformation matrices for all nodes
|
||||||
ComputeAbsoluteTransform(pScene->mRootNode);
|
ComputeAbsoluteTransform(pScene->mRootNode);
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
aiMesh* mesh = pScene->mMeshes[i];
|
||||||
|
|
||||||
|
for (unsigned int a = 0; a < mesh->mNumBones;++a)
|
||||||
|
delete mesh->mBones[a];
|
||||||
|
|
||||||
|
delete[] mesh->mBones;
|
||||||
|
mesh->mBones = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// now build a list of output meshes
|
// now build a list of output meshes
|
||||||
std::vector<aiMesh*> apcOutMeshes;
|
std::vector<aiMesh*> apcOutMeshes;
|
||||||
apcOutMeshes.reserve(pScene->mNumMaterials*2);
|
apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
|
||||||
std::list<unsigned int> aiVFormats;
|
std::list<unsigned int> aiVFormats;
|
||||||
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
||||||
{
|
{
|
||||||
|
@ -306,12 +359,12 @@ void PretransformVertices::Execute( aiScene* pScene)
|
||||||
while ((*j) & (0x100 << iFaces))
|
while ((*j) & (0x100 << iFaces))
|
||||||
{
|
{
|
||||||
pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
|
pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
|
||||||
if ((*j) & (0x1000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
|
if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
|
||||||
else pcMesh->mNumUVComponents[iFaces] = 2;
|
else pcMesh->mNumUVComponents[iFaces] = 2;
|
||||||
iFaces++;
|
iFaces++;
|
||||||
}
|
}
|
||||||
iFaces = 0;
|
iFaces = 0;
|
||||||
while ((*j) & (0x10000 << iFaces))
|
while ((*j) & (0x1000000 << iFaces))
|
||||||
pcMesh->mColors[iFaces] = new aiColor4D[iVertices];
|
pcMesh->mColors[iFaces] = new aiColor4D[iVertices];
|
||||||
|
|
||||||
// fill the mesh ...
|
// fill the mesh ...
|
||||||
|
@ -324,28 +377,66 @@ void PretransformVertices::Execute( aiScene* pScene)
|
||||||
// remove all animations from the scene
|
// remove all animations from the scene
|
||||||
for (unsigned int i = 0; i < pScene->mNumAnimations;++i)
|
for (unsigned int i = 0; i < pScene->mNumAnimations;++i)
|
||||||
delete pScene->mAnimations[i];
|
delete pScene->mAnimations[i];
|
||||||
pScene->mAnimations = NULL;
|
delete[] pScene->mAnimations;
|
||||||
|
|
||||||
|
pScene->mAnimations = NULL;
|
||||||
pScene->mNumAnimations = 0;
|
pScene->mNumAnimations = 0;
|
||||||
|
|
||||||
// now delete all meshes in the scene and build a new mesh list
|
// now delete all meshes in the scene and build a new mesh list
|
||||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||||
|
{
|
||||||
delete pScene->mMeshes[i];
|
delete pScene->mMeshes[i];
|
||||||
if (apcOutMeshes.size() != pScene->mNumMeshes)
|
|
||||||
|
// 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 ...
|
||||||
|
AI_DEBUG_INVALIDATE_PTR( pScene->mMeshes[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
pScene->mNumMeshes = (unsigned int)apcOutMeshes.size();
|
||||||
|
if (apcOutMeshes.size() > pScene->mNumMeshes)
|
||||||
{
|
{
|
||||||
delete[] pScene->mMeshes;
|
delete[] pScene->mMeshes;
|
||||||
pScene->mNumMeshes = (unsigned int)apcOutMeshes.size();
|
|
||||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||||
}
|
}
|
||||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||||
pScene->mMeshes[i] = apcOutMeshes[i];
|
pScene->mMeshes[i] = apcOutMeshes[i];
|
||||||
|
|
||||||
|
// --- we need to keep all cameras and lights
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumCameras;++i)
|
||||||
|
{
|
||||||
|
aiCamera* cam = pScene->mCameras[i];
|
||||||
|
const aiNode* nd = pScene->mRootNode->FindNode(cam->mName);
|
||||||
|
ai_assert(NULL != nd);
|
||||||
|
|
||||||
|
// multiply all properties of the camera with the absolute
|
||||||
|
// transformation of the corresponding node
|
||||||
|
cam->mPosition = nd->mTransformation * cam->mPosition;
|
||||||
|
cam->mLookAt = aiMatrix3x3( nd->mTransformation ) * cam->mLookAt;
|
||||||
|
cam->mUp = aiMatrix3x3( nd->mTransformation ) * cam->mUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < pScene->mNumLights;++i)
|
||||||
|
{
|
||||||
|
aiLight* l = pScene->mLights[i];
|
||||||
|
const aiNode* nd = pScene->mRootNode->FindNode(l->mName);
|
||||||
|
ai_assert(NULL != nd);
|
||||||
|
|
||||||
|
// multiply all properties of the camera with the absolute
|
||||||
|
// transformation of the corresponding node
|
||||||
|
l->mPosition = nd->mTransformation * l->mPosition;
|
||||||
|
l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection;
|
||||||
|
}
|
||||||
|
|
||||||
// now delete all nodes in the scene and build a new
|
// now delete all nodes in the scene and build a new
|
||||||
// flat node graph with a root node and some level 1 children
|
// flat node graph with a root node and some level 1 children
|
||||||
delete pScene->mRootNode;
|
delete pScene->mRootNode;
|
||||||
pScene->mRootNode = new aiNode();
|
pScene->mRootNode = new aiNode();
|
||||||
pScene->mRootNode->mName.Set("<dummy_root>");
|
pScene->mRootNode->mName.Set("<dummy_root>");
|
||||||
|
|
||||||
if (1 == pScene->mNumMeshes)
|
if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
|
||||||
{
|
{
|
||||||
pScene->mRootNode->mNumMeshes = 1;
|
pScene->mRootNode->mNumMeshes = 1;
|
||||||
pScene->mRootNode->mMeshes = new unsigned int[1];
|
pScene->mRootNode->mMeshes = new unsigned int[1];
|
||||||
|
@ -353,22 +444,59 @@ void PretransformVertices::Execute( aiScene* pScene)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
|
pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras;
|
||||||
pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
|
aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
|
||||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
|
||||||
{
|
|
||||||
aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
|
|
||||||
pcNode->mName.length = sprintf(pcNode->mName.data,"dummy_%i",i);
|
|
||||||
|
|
||||||
|
// 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->mNumMeshes = 1;
|
||||||
pcNode->mMeshes = new unsigned int[1];
|
pcNode->mMeshes = new unsigned int[1];
|
||||||
pcNode->mMeshes[0] = i;
|
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->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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultLogger::get()->debug("PretransformVerticesProcess finished. All "
|
// print statistics
|
||||||
"vertices are in worldspace now");
|
if (!DefaultLogger::isNullLogger())
|
||||||
|
{
|
||||||
|
char buffer[4096];
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug("PretransformVerticesProcess finished");
|
||||||
|
|
||||||
|
::sprintf(buffer,"Removed %i nodes and %i animation channels (%i output nodes)",
|
||||||
|
iOldNodes,iOldAnimationChannels,CountNodes(pScene->mRootNode));
|
||||||
|
DefaultLogger::get()->info(buffer);
|
||||||
|
|
||||||
|
::sprintf(buffer,"Kept %i lights and %i cameras",
|
||||||
|
pScene->mNumLights,pScene->mNumCameras);
|
||||||
|
DefaultLogger::get()->info(buffer);
|
||||||
|
|
||||||
|
::sprintf(buffer,"Moved %i meshes to WCS (number of output meshes: %i)",
|
||||||
|
iOldMeshes,pScene->mNumMeshes);
|
||||||
|
DefaultLogger::get()->info(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "AssimpPCH.h"
|
#include "AssimpPCH.h"
|
||||||
#include "RemoveComments.h"
|
#include "RemoveComments.h"
|
||||||
|
#include "ParsingUtils.h"
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
|
@ -56,17 +57,17 @@ void CommentRemover::RemoveLineComments(const char* szComment,
|
||||||
ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
|
ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
|
||||||
|
|
||||||
const size_t len = ::strlen(szComment);
|
const size_t len = ::strlen(szComment);
|
||||||
|
|
||||||
while (*szBuffer)
|
while (*szBuffer)
|
||||||
{
|
{
|
||||||
if (0 == ::strncmp(szBuffer,szComment,len))
|
if (!::strncmp(szBuffer,szComment,len))
|
||||||
{
|
{
|
||||||
while (*szBuffer != '\r' && *szBuffer != '\n' && *szBuffer)
|
while (!IsLineEnd(*szBuffer))
|
||||||
*szBuffer++ = chReplacement;
|
*szBuffer++ = chReplacement;
|
||||||
}
|
}
|
||||||
++szBuffer;
|
++szBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
|
void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
|
||||||
const char* szCommentEnd,char* szBuffer,
|
const char* szCommentEnd,char* szBuffer,
|
||||||
|
@ -74,32 +75,30 @@ void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
|
||||||
{
|
{
|
||||||
// validate parameters
|
// validate parameters
|
||||||
ai_assert(NULL != szCommentStart && NULL != szCommentEnd &&
|
ai_assert(NULL != szCommentStart && NULL != szCommentEnd &&
|
||||||
NULL != szBuffer && '\0' != *szCommentStart && '\0' != *szCommentEnd);
|
NULL != szBuffer && *szCommentStart && *szCommentEnd);
|
||||||
|
|
||||||
const size_t len = ::strlen(szCommentEnd);
|
const size_t len = ::strlen(szCommentEnd);
|
||||||
const size_t len2 = ::strlen(szCommentStart);
|
const size_t len2 = ::strlen(szCommentStart);
|
||||||
|
|
||||||
while (*szBuffer)
|
while (*szBuffer)
|
||||||
{
|
{
|
||||||
if (0 == ::strncmp(szBuffer,szCommentStart,len2))
|
if (!::strncmp(szBuffer,szCommentStart,len2))
|
||||||
{
|
{
|
||||||
while (*szBuffer)
|
while (*szBuffer)
|
||||||
{
|
{
|
||||||
|
if (!::strncmp(szBuffer,szCommentEnd,len))
|
||||||
if (0 == ::strncmp(szBuffer,szCommentEnd,len))
|
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < len;++i)
|
for (unsigned int i = 0; i < len;++i)
|
||||||
*szBuffer++ = chReplacement;
|
*szBuffer++ = chReplacement;
|
||||||
goto __continue_outer; // WUHHHAAAAHHAA!
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
*szBuffer++ = chReplacement;
|
*szBuffer++ = chReplacement;
|
||||||
}
|
}
|
||||||
return;
|
if (!(*szBuffer))return;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
++szBuffer;
|
++szBuffer;
|
||||||
__continue_outer:
|
|
||||||
int i = 4; // NOP dummy
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,30 @@ void RemoveVCProcess::Execute( aiScene* pScene)
|
||||||
bHas = true;
|
bHas = true;
|
||||||
ArrayDelete(pScene->mTextures,pScene->mNumTextures);
|
ArrayDelete(pScene->mTextures,pScene->mNumTextures);
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
|
// handle materials
|
||||||
|
if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials)
|
||||||
|
{
|
||||||
|
bHas = true;
|
||||||
|
for (unsigned int i = 1;i < pScene->mNumMaterials;++i)
|
||||||
|
delete pScene->mMaterials[i];
|
||||||
|
|
||||||
|
MaterialHelper* helper = (MaterialHelper*) pScene->mMaterials[0];
|
||||||
|
helper->Clear();
|
||||||
|
|
||||||
|
// gray
|
||||||
|
aiColor3D clr(0.6f,0.6f,0.6f);
|
||||||
|
helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||||
|
|
||||||
|
// add a small ambient color value
|
||||||
|
clr = aiColor3D(0.05f,0.05f,0.05f);
|
||||||
|
helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
|
||||||
|
|
||||||
|
aiString s;
|
||||||
|
s.Set("Dummy_MaterialsRemoved");
|
||||||
|
helper->AddProperty(&s,AI_MATKEY_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
// handle light sources
|
// handle light sources
|
||||||
if ( configDeleteFlags & aiComponent_LIGHTS)
|
if ( configDeleteFlags & aiComponent_LIGHTS)
|
||||||
{
|
{
|
||||||
|
@ -198,7 +221,7 @@ void RemoveVCProcess::Execute( aiScene* pScene)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle camneras
|
// handle camneras
|
||||||
if ( configDeleteFlags & aiComponent_CAMERA)
|
if ( configDeleteFlags & aiComponent_CAMERAS)
|
||||||
{
|
{
|
||||||
// mask nodes for removal
|
// mask nodes for removal
|
||||||
MaskNodes(pScene->mRootNode,pScene->mLights,pScene->mNumLights,
|
MaskNodes(pScene->mRootNode,pScene->mLights,pScene->mNumLights,
|
||||||
|
@ -207,13 +230,12 @@ void RemoveVCProcess::Execute( aiScene* pScene)
|
||||||
bHas = true;
|
bHas = true;
|
||||||
ArrayDelete(pScene->mCameras,pScene->mNumCameras);
|
ArrayDelete(pScene->mCameras,pScene->mNumCameras);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
// handle meshes
|
// handle meshes
|
||||||
if (configDeleteFlags & aiComponent_MESHES)
|
if (configDeleteFlags & aiComponent_MESHES)
|
||||||
{
|
{
|
||||||
bHas = true;
|
bHas = true;
|
||||||
ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
|
ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
|
||||||
pScene->mFlags |= AI_SCENE_FLAGS_ANIM_SKELETON_ONLY;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -232,7 +254,6 @@ void RemoveVCProcess::Execute( aiScene* pScene)
|
||||||
// MSB>>1 means: NO, DON'T REMOVE ME (Veto)
|
// MSB>>1 means: NO, DON'T REMOVE ME (Veto)
|
||||||
if (bMasked)
|
if (bMasked)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
if (pScene->mNumLights)
|
if (pScene->mNumLights)
|
||||||
{
|
{
|
||||||
MaskNodes(pScene->mRootNode,pScene->mLights,pScene->mNumLights,
|
MaskNodes(pScene->mRootNode,pScene->mLights,pScene->mNumLights,
|
||||||
|
@ -243,7 +264,6 @@ void RemoveVCProcess::Execute( aiScene* pScene)
|
||||||
MaskNodes(pScene->mRootNode,pScene->mCameras,pScene->mNumCameras,
|
MaskNodes(pScene->mRootNode,pScene->mCameras,pScene->mNumCameras,
|
||||||
AI_RC_UINT_MSB_2);
|
AI_RC_UINT_MSB_2);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (!(configDeleteFlags & aiComponent_BONEWEIGHTS))
|
if (!(configDeleteFlags & aiComponent_BONEWEIGHTS))
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||||
|
@ -259,15 +279,14 @@ void RemoveVCProcess::Execute( aiScene* pScene)
|
||||||
std::list<aiNode*> dummy;
|
std::list<aiNode*> dummy;
|
||||||
UpdateNodeGraph(pScene->mRootNode,dummy, true);
|
UpdateNodeGraph(pScene->mRootNode,dummy, true);
|
||||||
|
|
||||||
// the root node will neever be deleted
|
// the root node will never be deleted
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check whether the result contains
|
// now check whether the result is still a full scene
|
||||||
// !0 animations (+ the AI_SCENE_FLAGS_ANIM_SKELETON_ONLY flag) OR
|
if (!pScene->mNumMeshes || !pScene->mNumMaterials)
|
||||||
// !0 meshes
|
|
||||||
if (!pScene->mNumAnimations && !pScene->mNumMeshes)
|
|
||||||
{
|
{
|
||||||
throw new ImportErrorException("No valid data structure remaining");
|
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||||
|
DefaultLogger::get()->debug("Setting AI_SCENE_FLAGS_INCOMPLETE flag");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done.");
|
if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done.");
|
||||||
|
@ -291,6 +310,11 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
|
// if all materials have been deleted let the material
|
||||||
|
// index of the mesh point to the created default material
|
||||||
|
if ( configDeleteFlags & aiComponent_MATERIALS)
|
||||||
|
pMesh->mMaterialIndex = 0;
|
||||||
|
|
||||||
// handle normals
|
// handle normals
|
||||||
if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
|
if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
|
||||||
{
|
{
|
||||||
|
|
|
@ -156,7 +156,7 @@ void SMDImporter::InternReadFile(
|
||||||
}
|
}
|
||||||
// set the flag in the scene structure which indicates
|
// set the flag in the scene structure which indicates
|
||||||
// that there is nothing than an animation skeleton
|
// that there is nothing than an animation skeleton
|
||||||
pScene->mFlags |= AI_SCENE_FLAGS_ANIM_SKELETON_ONLY;
|
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asBones.empty())
|
if (!asBones.empty())
|
||||||
|
@ -179,7 +179,7 @@ void SMDImporter::InternReadFile(
|
||||||
// compute absolute bone transformation matrices
|
// compute absolute bone transformation matrices
|
||||||
ComputeAbsoluteBoneTransformations();
|
ComputeAbsoluteBoneTransformations();
|
||||||
}
|
}
|
||||||
if (!(pScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY))
|
if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
|
||||||
{
|
{
|
||||||
// create output meshes
|
// create output meshes
|
||||||
CreateOutputMeshes();
|
CreateOutputMeshes();
|
||||||
|
@ -462,7 +462,7 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent)
|
||||||
void SMDImporter::CreateOutputNodes()
|
void SMDImporter::CreateOutputNodes()
|
||||||
{
|
{
|
||||||
pScene->mRootNode = new aiNode();
|
pScene->mRootNode = new aiNode();
|
||||||
if (!(pScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY))
|
if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
|
||||||
{
|
{
|
||||||
// create one root node that renders all meshes
|
// create one root node that renders all meshes
|
||||||
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
|
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
|
||||||
|
@ -475,7 +475,7 @@ void SMDImporter::CreateOutputNodes()
|
||||||
AddBoneChildren(pScene->mRootNode,(uint32_t)-1);
|
AddBoneChildren(pScene->mRootNode,(uint32_t)-1);
|
||||||
|
|
||||||
// if we have only one bone we can even remove the root node
|
// if we have only one bone we can even remove the root node
|
||||||
if (pScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY &&
|
if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE &&
|
||||||
1 == pScene->mRootNode->mNumChildren)
|
1 == pScene->mRootNode->mNumChildren)
|
||||||
{
|
{
|
||||||
aiNode* pcOldRoot = pScene->mRootNode;
|
aiNode* pcOldRoot = pScene->mRootNode;
|
||||||
|
|
|
@ -55,7 +55,7 @@ using namespace Assimp;
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
DeterminePTypeHelperProcess ::DeterminePTypeHelperProcess()
|
DeterminePTypeHelperProcess ::DeterminePTypeHelperProcess()
|
||||||
{
|
{
|
||||||
// nothing to do here
|
bSpeedFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -73,84 +73,97 @@ bool DeterminePTypeHelperProcess::IsActive( unsigned int pFlags) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// called as a request to the step to update its configuration
|
||||||
|
void DeterminePTypeHelperProcess::SetupProperties(const Importer* pImp)
|
||||||
|
{
|
||||||
|
bSpeedFlag = (pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0) ? true : false);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Executes the post processing step on the given imported data.
|
// Executes the post processing step on the given imported data.
|
||||||
void DeterminePTypeHelperProcess::Execute( aiScene* pScene)
|
void DeterminePTypeHelperProcess::Execute( aiScene* pScene)
|
||||||
{
|
{
|
||||||
|
DefaultLogger::get()->debug("DeterminePTypeHelper begin");
|
||||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||||
{
|
{
|
||||||
aiMesh* mesh = pScene->mMeshes[i];
|
aiMesh* mesh = pScene->mMeshes[i];
|
||||||
|
|
||||||
|
// if the speed flag is not set search whether there are any degenerated
|
||||||
|
// primitives in the mesh
|
||||||
|
if (false && !bSpeedFlag)
|
||||||
|
{
|
||||||
|
unsigned int deg = 0;
|
||||||
|
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
||||||
|
{
|
||||||
|
aiFace& face = mesh->mFaces[a];
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
// check whether the face contains degenerated entries
|
||||||
|
for (register unsigned int i = 0; i < face.mNumIndices; ++i)
|
||||||
|
{
|
||||||
|
for (register unsigned int a = i+1; a < face.mNumIndices; ++a)
|
||||||
|
{
|
||||||
|
if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[a]])
|
||||||
|
{
|
||||||
|
// we have found a matching vertex position
|
||||||
|
// remove the corresponding index from the array
|
||||||
|
for (unsigned int m = a; m < face.mNumIndices-1; ++m)
|
||||||
|
{
|
||||||
|
face.mIndices[m] = face.mIndices[m+1];
|
||||||
|
}
|
||||||
|
--a;
|
||||||
|
--face.mNumIndices;
|
||||||
|
|
||||||
|
// NOTE: we set the removed vertex index to an unique value
|
||||||
|
// to make sure the developer gets notified when his
|
||||||
|
// application attemps to access this data.
|
||||||
|
face.mIndices[face.mNumIndices] = 0xdeadbeef;
|
||||||
|
|
||||||
|
if(first)
|
||||||
|
{
|
||||||
|
++deg;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deg)
|
||||||
|
{
|
||||||
|
char s[64];
|
||||||
|
::_itoa(deg,s,10);
|
||||||
|
DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mesh->mPrimitiveTypes)
|
if (!mesh->mPrimitiveTypes)
|
||||||
{
|
{
|
||||||
bool bDeg = false;
|
|
||||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
||||||
{
|
{
|
||||||
aiFace& face = mesh->mFaces[a];
|
aiFace& face = mesh->mFaces[a];
|
||||||
switch (face.mNumIndices)
|
switch (face.mNumIndices)
|
||||||
{
|
{
|
||||||
case 3u:
|
case 3u:
|
||||||
|
mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||||
|
break;
|
||||||
|
|
||||||
// check whether the triangle is degenerated
|
|
||||||
if (mesh->mVertices[face.mIndices[0]] == mesh->mVertices[face.mIndices[1]] ||
|
|
||||||
mesh->mVertices[face.mIndices[1]] == mesh->mVertices[face.mIndices[2]])
|
|
||||||
{
|
|
||||||
face.mNumIndices = 2;
|
|
||||||
unsigned int* pi = new unsigned int[2];
|
|
||||||
pi[0] = face.mIndices[0];
|
|
||||||
pi[1] = face.mIndices[2];
|
|
||||||
delete[] face.mIndices;
|
|
||||||
face.mIndices = pi;
|
|
||||||
|
|
||||||
bDeg = true;
|
|
||||||
}
|
|
||||||
else if (mesh->mVertices[face.mIndices[2]] == mesh->mVertices[face.mIndices[0]])
|
|
||||||
{
|
|
||||||
face.mNumIndices = 2;
|
|
||||||
unsigned int* pi = new unsigned int[2];
|
|
||||||
pi[0] = face.mIndices[0];
|
|
||||||
pi[1] = face.mIndices[1];
|
|
||||||
delete[] face.mIndices;
|
|
||||||
face.mIndices = pi;
|
|
||||||
|
|
||||||
bDeg = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2u:
|
case 2u:
|
||||||
|
mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
||||||
|
break;
|
||||||
|
|
||||||
// check whether the line is degenerated
|
|
||||||
if (mesh->mVertices[face.mIndices[0]] == mesh->mVertices[face.mIndices[1]])
|
|
||||||
{
|
|
||||||
face.mNumIndices = 1;
|
|
||||||
unsigned int* pi = new unsigned int[1];
|
|
||||||
pi[0] = face.mIndices[0];
|
|
||||||
delete[] face.mIndices;
|
|
||||||
face.mIndices = pi;
|
|
||||||
|
|
||||||
bDeg = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1u:
|
case 1u:
|
||||||
mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bDeg)
|
|
||||||
{
|
|
||||||
DefaultLogger::get()->warn("Found degenerated primitives");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DefaultLogger::get()->debug("DeterminePTypeHelper finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,7 +231,15 @@ void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node
|
||||||
// Executes the post processing step on the given imported data.
|
// Executes the post processing step on the given imported data.
|
||||||
void SortByPTypeProcess::Execute( aiScene* pScene)
|
void SortByPTypeProcess::Execute( aiScene* pScene)
|
||||||
{
|
{
|
||||||
if (!pScene->mNumMeshes)return;
|
if (!pScene->mNumMeshes)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->debug("SortByPTypeProcess skipped, there are no meshes");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug("SortByPTypeProcess begin");
|
||||||
|
|
||||||
|
unsigned int aiNumMeshesPerPType[4] = {0,0,0,0};
|
||||||
|
|
||||||
std::vector<aiMesh*> outMeshes;
|
std::vector<aiMesh*> outMeshes;
|
||||||
outMeshes.reserve(pScene->mNumMeshes<<1u);
|
outMeshes.reserve(pScene->mNumMeshes<<1u);
|
||||||
|
@ -232,10 +253,26 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
||||||
|
|
||||||
// if there's just one primitive type in the mesh there's nothing to do for us
|
// if there's just one primitive type in the mesh there's nothing to do for us
|
||||||
unsigned int num = 0;
|
unsigned int num = 0;
|
||||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) ++num;
|
if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT)
|
||||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) ++num;
|
{
|
||||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) ++num;
|
++aiNumMeshesPerPType[0];
|
||||||
if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) ++num;
|
++num;
|
||||||
|
}
|
||||||
|
if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE)
|
||||||
|
{
|
||||||
|
++aiNumMeshesPerPType[1];
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)
|
||||||
|
{
|
||||||
|
++aiNumMeshesPerPType[2];
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)
|
||||||
|
{
|
||||||
|
++aiNumMeshesPerPType[3];
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
|
||||||
if (1 == num)
|
if (1 == num)
|
||||||
{
|
{
|
||||||
|
@ -436,5 +473,17 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
||||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||||
::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
|
::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DefaultLogger::isNullLogger())
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
::sprintf(buffer,"Points: %i, Lines: %i, Triangles: %i, Polygons: %i (Meshes)",
|
||||||
|
aiNumMeshesPerPType[0],
|
||||||
|
aiNumMeshesPerPType[1],
|
||||||
|
aiNumMeshesPerPType[2],
|
||||||
|
aiNumMeshesPerPType[3]);
|
||||||
|
DefaultLogger::get()->info(buffer);
|
||||||
|
DefaultLogger::get()->debug("SortByPTypeProcess finished");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,13 @@ public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
void Execute( aiScene* pScene);
|
void Execute( aiScene* pScene);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
void SetupProperties(const Importer* pImp);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool bSpeedFlag;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if (!defined AI_BUILD_NO_SORTBYPTYPE_PROCESS)
|
#if (!defined AI_BUILD_NO_SORTBYPTYPE_PROCESS)
|
||||||
|
|
|
@ -70,11 +70,9 @@ public:
|
||||||
inline StreamReader(IOStream* stream)
|
inline StreamReader(IOStream* stream)
|
||||||
{
|
{
|
||||||
ai_assert(NULL != stream);
|
ai_assert(NULL != stream);
|
||||||
|
|
||||||
this->input = input;
|
|
||||||
this->stream = stream;
|
this->stream = stream;
|
||||||
|
|
||||||
size_t s = stream->GetFileSize();
|
size_t s = stream->FileSize();
|
||||||
if (!s)throw new ImportErrorException("File is empty");
|
if (!s)throw new ImportErrorException("File is empty");
|
||||||
|
|
||||||
current = buffer = new int8_t[s];
|
current = buffer = new int8_t[s];
|
||||||
|
@ -188,4 +186,4 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !! AI_STREAMREADER_H_INCLUDED
|
#endif // !! AI_STREAMREADER_H_INCLUDED
|
||||||
|
|
|
@ -56,11 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
#if _MSC_VER >= 1400
|
|
||||||
# define vsprintf vsprintf_s
|
|
||||||
# define sprintf sprintf_s
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
ValidateDSProcess::ValidateDSProcess()
|
ValidateDSProcess::ValidateDSProcess()
|
||||||
|
@ -126,114 +121,200 @@ void ValidateDSProcess::ReportWarning(const char* msg,...)
|
||||||
va_end(args);
|
va_end(args);
|
||||||
DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
|
DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
inline int HasNameMatch(const aiString& in, aiNode* node)
|
||||||
|
{
|
||||||
|
int result = (node->mName == in ? 1 : 0 );
|
||||||
|
for (unsigned int i = 0; i < node->mNumChildren;++i)
|
||||||
|
{
|
||||||
|
result += HasNameMatch(in,node->mChildren[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
|
inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size,
|
||||||
|
const char* firstName, const char* secondName)
|
||||||
|
{
|
||||||
|
// validate all entries
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
if (!parray)
|
||||||
|
{
|
||||||
|
ReportError("aiScene::%s is NULL (aiScene::%s is %i)",
|
||||||
|
firstName, secondName, size);
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < size;++i)
|
||||||
|
{
|
||||||
|
if (!parray[i])
|
||||||
|
{
|
||||||
|
ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)",
|
||||||
|
firstName,i,secondName,size);
|
||||||
|
}
|
||||||
|
Validate(parray[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
|
inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
|
||||||
|
const char* firstName, const char* secondName)
|
||||||
|
{
|
||||||
|
// validate all entries
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
if (!parray)
|
||||||
|
{
|
||||||
|
ReportError("aiScene::%s is NULL (aiScene::%s is %i)",
|
||||||
|
firstName, secondName, size);
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < size;++i)
|
||||||
|
{
|
||||||
|
if (!parray[i])
|
||||||
|
{
|
||||||
|
ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)",
|
||||||
|
firstName,i,secondName,size);
|
||||||
|
}
|
||||||
|
Validate(parray[i]);
|
||||||
|
|
||||||
|
// check whether there are duplicate names
|
||||||
|
for (unsigned int a = i+1; a < size;++a)
|
||||||
|
{
|
||||||
|
if (parray[i]->mName == parray[a]->mName)
|
||||||
|
{
|
||||||
|
this->ReportError("aiScene::%s[%i] has the same name as "
|
||||||
|
"aiScene::%s[%i]",firstName, i,secondName, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
|
inline void ValidateDSProcess::DoValidationWithNameCheck(T** array,
|
||||||
|
unsigned int size, const char* firstName,
|
||||||
|
const char* secondName)
|
||||||
|
{
|
||||||
|
// validate all entries
|
||||||
|
DoValidationEx(array,size,firstName,secondName);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < size;++i)
|
||||||
|
{
|
||||||
|
int res = HasNameMatch(array[i]->mName,mScene->mRootNode);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
ReportError("aiScene::%s[%i] has no corresponding node in the scene graph (%s)",
|
||||||
|
firstName,i,array[i]->mName.data);
|
||||||
|
}
|
||||||
|
else if (1 != res)
|
||||||
|
{
|
||||||
|
ReportError("aiScene::%s[%i]: there are more than one nodes with %s as name",
|
||||||
|
firstName,i,array[i]->mName.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Executes the post processing step on the given imported data.
|
// Executes the post processing step on the given imported data.
|
||||||
void ValidateDSProcess::Execute( aiScene* pScene)
|
void ValidateDSProcess::Execute( aiScene* pScene)
|
||||||
{
|
{
|
||||||
this->mScene = pScene;
|
this->mScene = pScene;
|
||||||
DefaultLogger::get()->debug("ValidateDataStructureProcess begin");
|
DefaultLogger::get()->debug("ValidateDataStructureProcess begin");
|
||||||
|
|
||||||
|
// validate the node graph of the scene
|
||||||
|
Validate(pScene->mRootNode);
|
||||||
|
|
||||||
|
// at least one of the mXXX arrays must be non-empty or we'll flag
|
||||||
|
// the sebe as invalid
|
||||||
|
bool has = false;
|
||||||
|
|
||||||
// validate all meshes
|
// validate all meshes
|
||||||
if (pScene->mNumMeshes)
|
if (pScene->mNumMeshes)
|
||||||
{
|
{
|
||||||
if (!pScene->mMeshes)
|
has = true;
|
||||||
{
|
DoValidation(pScene->mMeshes,pScene->mNumMeshes,"mMeshes","mNumMeshes");
|
||||||
this->ReportError("aiScene::mMeshes is NULL (aiScene::mNumMeshes is %i)",
|
|
||||||
pScene->mNumMeshes);
|
|
||||||
}
|
|
||||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
|
||||||
{
|
|
||||||
if (!pScene->mMeshes[i])
|
|
||||||
{
|
|
||||||
this->ReportError("aiScene::mMeshes[%i] is NULL (aiScene::mNumMeshes is %i)",
|
|
||||||
i,pScene->mNumMeshes);
|
|
||||||
}
|
|
||||||
this->Validate(pScene->mMeshes[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!(this->mScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY))
|
else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
|
||||||
{
|
{
|
||||||
this->ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
|
ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate all animations
|
// validate all animations
|
||||||
if (pScene->mNumAnimations)
|
if (pScene->mNumAnimations)
|
||||||
{
|
{
|
||||||
if (!pScene->mAnimations)
|
has = true;
|
||||||
{
|
DoValidation(pScene->mAnimations,pScene->mNumAnimations,
|
||||||
this->ReportError("aiScene::mAnimations is NULL (aiScene::mNumAnimations is %i)",
|
"mAnimations","mNumAnimations");
|
||||||
pScene->mNumAnimations);
|
|
||||||
}
|
|
||||||
for (unsigned int i = 0; i < pScene->mNumAnimations;++i)
|
|
||||||
{
|
|
||||||
if (!pScene->mAnimations[i])
|
|
||||||
{
|
|
||||||
this->ReportError("aiScene::mAnimations[%i] is NULL (aiScene::mNumAnimations is %i)",
|
|
||||||
i,pScene->mNumAnimations);
|
|
||||||
}
|
|
||||||
this->Validate(pScene->mAnimations[i]);
|
|
||||||
|
|
||||||
// check whether there are duplicate animation names
|
|
||||||
for (unsigned int a = i+1; a < pScene->mNumAnimations;++a)
|
|
||||||
{
|
|
||||||
if (pScene->mAnimations[i]->mName == pScene->mAnimations[a]->mName)
|
|
||||||
{
|
|
||||||
this->ReportError("aiScene::mAnimations[%i] has the same name as "
|
|
||||||
"aiScene::mAnimations[%i]",i,a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (this->mScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY)
|
|
||||||
|
// validate all cameras
|
||||||
|
if (pScene->mNumCameras)
|
||||||
{
|
{
|
||||||
this->ReportError("aiScene::mNumAnimations is 0 and the "
|
has = true;
|
||||||
"AI_SCENE_FLAGS_ANIM_SKELETON_ONLY flag is set.");
|
DoValidationWithNameCheck(pScene->mCameras,pScene->mNumCameras,
|
||||||
|
"mCameras","mNumCameras");
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate all textures
|
// validate all lights
|
||||||
if (pScene->mNumTextures)
|
if (pScene->mNumLights)
|
||||||
{
|
{
|
||||||
if (!pScene->mTextures)
|
has = true;
|
||||||
{
|
DoValidationWithNameCheck(pScene->mLights,pScene->mNumLights,
|
||||||
this->ReportError("aiScene::mTextures is NULL (aiScene::mNumTextures is %i)",
|
"mLights","mNumLights");
|
||||||
pScene->mNumTextures);
|
|
||||||
}
|
|
||||||
for (unsigned int i = 0; i < pScene->mNumTextures;++i)
|
|
||||||
{
|
|
||||||
if (!pScene->mTextures[i])
|
|
||||||
{
|
|
||||||
this->ReportError("aiScene::mTextures[%i] is NULL (aiScene::mNumTextures is %i)",
|
|
||||||
i,pScene->mNumTextures);
|
|
||||||
}
|
|
||||||
this->Validate(pScene->mTextures[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate all materials
|
// validate all materials
|
||||||
if (pScene->mNumMaterials)
|
if (pScene->mNumMaterials)
|
||||||
{
|
{
|
||||||
if (!pScene->mMaterials)
|
has = true;
|
||||||
{
|
DoValidation(pScene->mCameras,pScene->mNumCameras,"mMaterials","mNumMaterials");
|
||||||
this->ReportError("aiScene::mMaterials is NULL (aiScene::mNumMaterials is %i)",
|
}
|
||||||
pScene->mNumMaterials);
|
else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
|
||||||
}
|
{
|
||||||
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
ReportError("aiScene::mNumMaterials is 0. At least one material must be there");
|
||||||
{
|
|
||||||
if (!pScene->mMaterials[i])
|
|
||||||
{
|
|
||||||
this->ReportError("aiScene::mMaterials[%i] is NULL (aiScene::mNumMaterials is %i)",
|
|
||||||
i,pScene->mNumMaterials);
|
|
||||||
}
|
|
||||||
this->Validate(pScene->mMaterials[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else this->ReportError("aiScene::mNumMaterials is 0. At least one material must be there.");
|
|
||||||
|
|
||||||
// validate the node graph of the scene
|
|
||||||
this->Validate(pScene->mRootNode);
|
|
||||||
|
|
||||||
|
if (!has)ReportError("The aiScene data structure is empty");
|
||||||
DefaultLogger::get()->debug("ValidateDataStructureProcess end");
|
DefaultLogger::get()->debug("ValidateDataStructureProcess end");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void ValidateDSProcess::Validate( const aiLight* pLight)
|
||||||
|
{
|
||||||
|
if (pLight->mType == aiLightSource_UNDEFINED)
|
||||||
|
ReportError("aiLight::mType is aiLightSource_UNDEFINED");
|
||||||
|
|
||||||
|
if (!pLight->mAttenuationConstant &&
|
||||||
|
!pLight->mAttenuationLinear &&
|
||||||
|
!pLight->mAttenuationQuadratic)
|
||||||
|
{
|
||||||
|
ReportError("aiLight::mAttenuationXXX - all are zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pLight->mAngleInnerCone > pLight->mAngleOuterCone)
|
||||||
|
ReportError("aiLight::mAngleInnerCone is larger than aiLight::mAngleOuterCone");
|
||||||
|
|
||||||
|
if (pLight->mColorDiffuse.IsBlack() && pLight->mColorAmbient.IsBlack()
|
||||||
|
&& pLight->mColorSpecular.IsBlack())
|
||||||
|
{
|
||||||
|
ReportError("aiLight::mColorXXX - all are black and won't have any influence");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void ValidateDSProcess::Validate( const aiCamera* pCamera)
|
||||||
|
{
|
||||||
|
if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear)
|
||||||
|
ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear");
|
||||||
|
|
||||||
|
if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI)
|
||||||
|
ReportError("%f is not a valid value for aiCamera::mHorizontalFOV",pCamera->mHorizontalFOV);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||||
{
|
{
|
||||||
|
@ -288,96 +369,91 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||||
if (!face.mIndices)this->ReportError("aiMesh::mFaces[%i].mIndices is NULL",i);
|
if (!face.mIndices)this->ReportError("aiMesh::mFaces[%i].mIndices is NULL",i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->mScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY)
|
// positions must always be there ...
|
||||||
|
if (!pMesh->mNumVertices || !pMesh->mVertices && !mScene->mFlags)
|
||||||
{
|
{
|
||||||
if (pMesh->mNumVertices || pMesh->mVertices ||
|
this->ReportError("The mesh contains no vertices");
|
||||||
pMesh->mNumFaces || pMesh->mFaces)
|
}
|
||||||
|
|
||||||
|
// if tangents are there there must also be bitangent vectors ...
|
||||||
|
if ((pMesh->mTangents != NULL) != (pMesh->mBitangents != NULL))
|
||||||
|
{
|
||||||
|
this->ReportError("If there are tangents there must also be bitangent vectors");
|
||||||
|
}
|
||||||
|
|
||||||
|
// faces, too
|
||||||
|
if (!pMesh->mNumFaces || !pMesh->mFaces && !mScene->mFlags)
|
||||||
|
{
|
||||||
|
this->ReportError("The mesh contains no faces");
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check whether the face indexing layout is correct:
|
||||||
|
// unique vertices, pseudo-indexed.
|
||||||
|
std::vector<bool> abRefList;
|
||||||
|
abRefList.resize(pMesh->mNumVertices,false);
|
||||||
|
for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
|
||||||
|
{
|
||||||
|
aiFace& face = pMesh->mFaces[i];
|
||||||
|
for (unsigned int a = 0; a < face.mNumIndices;++a)
|
||||||
{
|
{
|
||||||
this->ReportWarning("The mesh contains vertices and faces although "
|
if (face.mIndices[a] >= pMesh->mNumVertices)
|
||||||
"the AI_SCENE_FLAGS_ANIM_SKELETON_ONLY flag is set");
|
{
|
||||||
|
this->ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a);
|
||||||
|
}
|
||||||
|
// the MSB flag is temporarily used by the extra verbose
|
||||||
|
// mode to tell us that the JoinVerticesProcess might have
|
||||||
|
// been executed already.
|
||||||
|
if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && abRefList[face.mIndices[a]])
|
||||||
|
{
|
||||||
|
ReportError("aiMesh::mVertices[%i] is referenced twice - second "
|
||||||
|
"time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
|
||||||
|
}
|
||||||
|
abRefList[face.mIndices[a]] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
// check whether there are vertices that aren't referenced by a face
|
||||||
|
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
||||||
{
|
{
|
||||||
// positions must always be there ...
|
if (!abRefList[i])this->ReportError("aiMesh::mVertices[%i] is not referenced",i);
|
||||||
if (!pMesh->mNumVertices || !pMesh->mVertices)
|
|
||||||
{
|
|
||||||
this->ReportError("The mesh contains no vertices");
|
|
||||||
}
|
|
||||||
|
|
||||||
// faces, too
|
|
||||||
if (!pMesh->mNumFaces || !pMesh->mFaces)
|
|
||||||
{
|
|
||||||
this->ReportError("The mesh contains no faces");
|
|
||||||
}
|
|
||||||
|
|
||||||
// now check whether the face indexing layout is correct:
|
|
||||||
// unique vertices, pseudo-indexed.
|
|
||||||
std::vector<bool> abRefList;
|
|
||||||
abRefList.resize(pMesh->mNumVertices,false);
|
|
||||||
for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
|
|
||||||
{
|
|
||||||
aiFace& face = pMesh->mFaces[i];
|
|
||||||
for (unsigned int a = 0; a < face.mNumIndices;++a)
|
|
||||||
{
|
|
||||||
if (face.mIndices[a] >= pMesh->mNumVertices)
|
|
||||||
{
|
|
||||||
this->ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a);
|
|
||||||
}
|
|
||||||
// the MSB flag is temporarily used by the extra verbose
|
|
||||||
// mode to tell us that the JoinVerticesProcess might have
|
|
||||||
// been executed already.
|
|
||||||
if ( !(this->mScene->mFlags & 0x80000000 ) && abRefList[face.mIndices[a]])
|
|
||||||
{
|
|
||||||
this->ReportError("aiMesh::mVertices[%i] is referenced twice - second "
|
|
||||||
"time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
|
|
||||||
}
|
|
||||||
abRefList[face.mIndices[a]] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// check whether there are vertices that aren't referenced by a face
|
|
||||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
|
||||||
{
|
|
||||||
if (!abRefList[i])this->ReportError("aiMesh::mVertices[%i] is not referenced",i);
|
|
||||||
}
|
|
||||||
abRefList.clear();
|
|
||||||
|
|
||||||
// texture channel 2 may not be set if channel 1 is zero ...
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
|
||||||
{
|
|
||||||
if (!pMesh->HasTextureCoords(i))break;
|
|
||||||
}
|
|
||||||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
|
||||||
if (pMesh->HasTextureCoords(i))
|
|
||||||
{
|
|
||||||
this->ReportError("Texture coordinate channel %i is existing, "
|
|
||||||
"although the previous channel was NULL.",i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// the same for the vertex colors
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
|
||||||
{
|
|
||||||
if (!pMesh->HasVertexColors(i))break;
|
|
||||||
}
|
|
||||||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
|
||||||
if (pMesh->HasVertexColors(i))
|
|
||||||
{
|
|
||||||
this->ReportError("Vertex color channel %i is existing, "
|
|
||||||
"although the previous channel was NULL.",i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
abRefList.clear();
|
||||||
|
|
||||||
|
// texture channel 2 may not be set if channel 1 is zero ...
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||||
|
{
|
||||||
|
if (!pMesh->HasTextureCoords(i))break;
|
||||||
|
}
|
||||||
|
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||||
|
if (pMesh->HasTextureCoords(i))
|
||||||
|
{
|
||||||
|
ReportError("Texture coordinate channel %i is existing, "
|
||||||
|
"although the previous channel was NULL.",i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// the same for the vertex colors
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||||
|
{
|
||||||
|
if (!pMesh->HasVertexColors(i))break;
|
||||||
|
}
|
||||||
|
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||||
|
if (pMesh->HasVertexColors(i))
|
||||||
|
{
|
||||||
|
ReportError("Vertex color channel %i is existing, "
|
||||||
|
"although the previous channel was NULL.",i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// now validate all bones
|
// now validate all bones
|
||||||
if (pMesh->HasBones())
|
if (pMesh->HasBones())
|
||||||
{
|
{
|
||||||
if (!pMesh->mBones)
|
if (!pMesh->mBones)
|
||||||
{
|
{
|
||||||
this->ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)",
|
ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)",
|
||||||
pMesh->mNumBones);
|
pMesh->mNumBones);
|
||||||
}
|
}
|
||||||
float* afSum = NULL;
|
float* afSum = NULL;
|
||||||
|
@ -397,7 +473,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||||
this->ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)",
|
this->ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)",
|
||||||
i,pMesh->mNumBones);
|
i,pMesh->mNumBones);
|
||||||
}
|
}
|
||||||
this->Validate(pMesh,pMesh->mBones[i],afSum);
|
Validate(pMesh,pMesh->mBones[i],afSum);
|
||||||
|
|
||||||
for (unsigned int a = i+1; a < pMesh->mNumBones;++a)
|
for (unsigned int a = i+1; a < pMesh->mNumBones;++a)
|
||||||
{
|
{
|
||||||
|
@ -414,7 +490,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||||
{
|
{
|
||||||
if (afSum[i] && (afSum[i] <= 0.995 || afSum[i] >= 1.005))
|
if (afSum[i] && (afSum[i] <= 0.995 || afSum[i] >= 1.005))
|
||||||
{
|
{
|
||||||
this->ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)",i,afSum[i]);
|
ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)",i,afSum[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] afSum;
|
delete[] afSum;
|
||||||
|
|
|
@ -145,10 +145,22 @@ protected:
|
||||||
* @param pTexture Input texture
|
* @param pTexture Input texture
|
||||||
*/
|
*/
|
||||||
void Validate( const aiTexture* pTexture);
|
void Validate( const aiTexture* pTexture);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Validates a light source
|
||||||
|
* @param pLight Input light
|
||||||
|
*/
|
||||||
|
void Validate( const aiLight* pLight);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Validates a camera
|
||||||
|
* @param pCamera Input camera
|
||||||
|
*/
|
||||||
|
void Validate( const aiCamera* pCamera);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Validates a bone animation channel
|
/** Validates a bone animation channel
|
||||||
* @param pAnimation Input animation
|
* @param pAnimation Animation channel.
|
||||||
* @param pBoneAnim Input bone animation
|
* @param pBoneAnim Input bone animation
|
||||||
*/
|
*/
|
||||||
void Validate( const aiAnimation* pAnimation,
|
void Validate( const aiAnimation* pAnimation,
|
||||||
|
@ -168,9 +180,28 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// template to validate one of the aiScene::mXXX arrays
|
||||||
|
template <typename T>
|
||||||
|
inline void DoValidation(T** array, unsigned int size,
|
||||||
|
const char* firstName, const char* secondName);
|
||||||
|
|
||||||
|
// extended version: checks whethr T::mName occurs twice
|
||||||
|
template <typename T>
|
||||||
|
inline void DoValidationEx(T** array, unsigned int size,
|
||||||
|
const char* firstName, const char* secondName);
|
||||||
|
|
||||||
|
// extension to the first template which does also search
|
||||||
|
// the nodegraph for an item with the same name
|
||||||
|
template <typename T>
|
||||||
|
inline void DoValidationWithNameCheck(T** array, unsigned int size,
|
||||||
|
const char* firstName, const char* secondName);
|
||||||
|
|
||||||
aiScene* mScene;
|
aiScene* mScene;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
||||||
#endif // AI_VALIDATEPROCESS_H_INC
|
#endif // AI_VALIDATEPROCESS_H_INC
|
||||||
|
|
|
@ -139,7 +139,7 @@ inline unsigned int strtol_cppstyle( const char* in, const char** out=0)
|
||||||
{
|
{
|
||||||
if ('0' == in[0])
|
if ('0' == in[0])
|
||||||
{
|
{
|
||||||
return 'x' == in[1] ? strtol10(in+2,out) : strtol8(in+1,out);
|
return 'x' == in[1] ? strtol16(in+2,out) : strtol8(in+1,out);
|
||||||
}
|
}
|
||||||
return strtol10(in, out);
|
return strtol10(in, out);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ all: $(TARGET)
|
||||||
$(TARGET): $(OBJECTS)
|
$(TARGET): $(OBJECTS)
|
||||||
gcc -o $@ $(OBJECTS) -shared -lstdc++
|
gcc -o $@ $(OBJECTS) -shared -lstdc++
|
||||||
%.o:%.cpp
|
%.o:%.cpp
|
||||||
$(CXX) -g -Wall -c $? -o $@ -I../include -I"C:\Program Files\boost\boost_1_35_0" -I"%BOOST_DIR%"
|
$(CXX) -g -Wall -c $? -o $@ -I../include -I"C:\Program Files\boost\boost_1_35_0"
|
||||||
clean:
|
clean:
|
||||||
del *.o
|
del *.o
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,35 @@ struct aiCamera
|
||||||
*/
|
*/
|
||||||
aiString mName;
|
aiString mName;
|
||||||
|
|
||||||
|
/** Position of the camera relative to the coordinate space
|
||||||
|
* defined by the corresponding node.
|
||||||
|
*
|
||||||
|
* The default value is 0|0|0.
|
||||||
|
*/
|
||||||
|
aiVector3D mPosition;
|
||||||
|
|
||||||
|
|
||||||
|
/** 'Up' - vector of the camera coordinate system relative to
|
||||||
|
* the coordinate space defined by the corresponding node.
|
||||||
|
*
|
||||||
|
* The 'right' vector of the camera coordinate system is
|
||||||
|
* the cross product of the up and lookAt vectors.
|
||||||
|
* The default value is 0|1|0. The vector
|
||||||
|
* may be normalized, but it needn't.
|
||||||
|
*/
|
||||||
|
aiVector3D mUp;
|
||||||
|
|
||||||
|
|
||||||
|
/** 'LookAt' - vector of the camera coordinate system relative to
|
||||||
|
* the coordinate space defined by the corresponding node.
|
||||||
|
*
|
||||||
|
* This is the viewing direction of the user.
|
||||||
|
* The default value is 0|0|1. The vector
|
||||||
|
* may be normalized, but it needn't.
|
||||||
|
*/
|
||||||
|
aiVector3D mLookAt;
|
||||||
|
|
||||||
|
|
||||||
/** Half horizontal field of view angle, in radians.
|
/** Half horizontal field of view angle, in radians.
|
||||||
*
|
*
|
||||||
* The field of view angle is the angle between the center
|
* The field of view angle is the angle between the center
|
||||||
|
@ -105,7 +134,9 @@ struct aiCamera
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
aiCamera()
|
aiCamera()
|
||||||
: mHorizontalFOV (0.25f * (float)AI_MATH_PI)
|
: mUp (0.f,1.f,0.f)
|
||||||
|
, mLookAt (0.f,0.f,1.f)
|
||||||
|
, mHorizontalFOV (0.25f * (float)AI_MATH_PI)
|
||||||
, mClipPlaneNear (0.1f)
|
, mClipPlaneNear (0.1f)
|
||||||
, mClipPlaneFar (1000.f)
|
, mClipPlaneFar (1000.f)
|
||||||
, mAspect (0.f)
|
, mAspect (0.f)
|
||||||
|
@ -120,4 +151,4 @@ struct aiCamera
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // AI_CAMERA_H_INC
|
#endif // AI_CAMERA_H_INC
|
||||||
|
|
|
@ -40,8 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file Defines constants for configurable properties */
|
/** @file Defines constants for configurable properties */
|
||||||
#ifndef AI_CONFIG_H_INC
|
#ifndef __AI_CONFIG_H_INC__
|
||||||
#define AI_CONFIG_H_INC
|
#define __AI_CONFIG_H_INC__
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** \brief Set the maximum number of vertices in a mesh.
|
/** \brief Set the maximum number of vertices in a mesh.
|
||||||
|
@ -138,7 +138,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
* This applies to the GenSmoothNormals-Step. The angle is specified
|
* This applies to the GenSmoothNormals-Step. The angle is specified
|
||||||
* in degrees, so 180 is PI. The default value is
|
* in degrees, so 180 is PI. The default value is
|
||||||
* 175 degrees (all vertex normals are smoothed). The maximum value is 175
|
* 175 degrees (all vertex normals are smoothed). The maximum value is 175
|
||||||
* Property type: float.
|
* Property type: float. Warning: seting this option may cause a severe
|
||||||
|
* loss of performance.
|
||||||
*/
|
*/
|
||||||
#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE "pp.gsn.max_smoothing"
|
#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE "pp.gsn.max_smoothing"
|
||||||
|
|
||||||
|
@ -169,20 +170,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** \brief Sets the colormap (= palette) to be used to decode embedded
|
/** \brief Sets the colormap (= palette) to be used to decode embedded
|
||||||
* textures in MDL files.
|
* textures in MDL (Quake or 3DGS) files.
|
||||||
*
|
*
|
||||||
* This must be a valid path to a file. The file is 768 (256*3) bytes
|
* This must be a valid path to a file. The file is 768 (256*3) bytes
|
||||||
* large and contains RGB tripels for each of the 256 palette entries.
|
* large and contains RGB triplets for each of the 256 palette entries.
|
||||||
* The default value is colormap.lmp. If the file is nto found,
|
* The default value is colormap.lmp. If the file is not found,
|
||||||
* a default palette is used.
|
* a default palette (from Quake 1) is used.
|
||||||
* Property type: string.
|
* Property type: string.
|
||||||
*/
|
*/
|
||||||
#define AI_CONFIG_IMPORT_MDL_COLORMAP "imp.mdl.color_map"
|
#define AI_CONFIG_IMPORT_MDL_COLORMAP "imp.mdl.color_map"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
/** \brief Enumerates components of the aiScene and aiMesh data structures
|
||||||
|
* that can be excluded from the import with the RemoveComponent step.
|
||||||
|
*
|
||||||
|
* See the documentation to #aiProcess_RemoveComment for more details.
|
||||||
|
*/
|
||||||
enum aiComponent
|
enum aiComponent
|
||||||
{
|
{
|
||||||
//! Normal vectors
|
//! Normal vectors
|
||||||
|
@ -220,9 +224,13 @@ enum aiComponent
|
||||||
//! cameras are removed.
|
//! cameras are removed.
|
||||||
aiComponent_CAMERAS = 0x200,
|
aiComponent_CAMERAS = 0x200,
|
||||||
|
|
||||||
//! Removes all meshes (aiScene::mMeshes). The
|
//! Removes all meshes (aiScene::mMeshes).
|
||||||
//! #AI_SCENE_FLAGS_ANIM_SKELETON_ONLY flag is set in aiScene::mFlags.
|
|
||||||
aiComponent_MESHES = 0x400,
|
aiComponent_MESHES = 0x400,
|
||||||
|
|
||||||
|
//! Removes all materials. One default material will
|
||||||
|
//! be generated, so aiScene::mNumMaterials will be 1.
|
||||||
|
//! This makes no real sense without the aiComponent_TEXTURES flag.
|
||||||
|
aiComponent_MATERIALS = 0x800
|
||||||
};
|
};
|
||||||
|
|
||||||
#define aiComponent_COLORSn(n) (1u << (n+20u))
|
#define aiComponent_COLORSn(n) (1u << (n+20u))
|
||||||
|
|
|
@ -120,6 +120,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
# define AI_FORCE_INLINE __forceinline
|
# define AI_FORCE_INLINE __forceinline
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define ASSIMP_API
|
# define ASSIMP_API
|
||||||
# define AI_FORCE_INLINE inline
|
# define AI_FORCE_INLINE inline
|
||||||
|
|
|
@ -70,6 +70,8 @@ enum aiLightSourceType
|
||||||
|
|
||||||
//! A spot light source emmits light in a specific
|
//! A spot light source emmits light in a specific
|
||||||
//! angle. It has a position and a direction it is pointing to.
|
//! angle. It has a position and a direction it is pointing to.
|
||||||
|
//! A good example for a spot light is a light spot in
|
||||||
|
//! sport arenas.
|
||||||
aiLightSource_SPOT = 0x3
|
aiLightSource_SPOT = 0x3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,7 +84,7 @@ enum aiLightSourceType
|
||||||
*/
|
*/
|
||||||
struct aiLight
|
struct aiLight
|
||||||
{
|
{
|
||||||
/** The name of the light sources.
|
/** The name of the light source.
|
||||||
*
|
*
|
||||||
* There must be a node in the scenegraph with the same name.
|
* There must be a node in the scenegraph with the same name.
|
||||||
* This node specifies the position of the light in the scene
|
* This node specifies the position of the light in the scene
|
||||||
|
@ -91,20 +93,23 @@ struct aiLight
|
||||||
aiString mName;
|
aiString mName;
|
||||||
|
|
||||||
/** The type of the light source.
|
/** The type of the light source.
|
||||||
|
*
|
||||||
|
* aiLightSource_UNDEFINED is nto a valid value for this member.
|
||||||
*/
|
*/
|
||||||
aiLightSourceType mType;
|
aiLightSourceType mType;
|
||||||
|
|
||||||
/** Position of the light source in space. Relative to the
|
/** Position of the light source in space. Relative to the
|
||||||
* node corresponding to the light.
|
* transformation of the node corresponding to the light.
|
||||||
*
|
*
|
||||||
* The position is undefined for directional lights.
|
* The position is undefined for directional lights.
|
||||||
*/
|
*/
|
||||||
aiVector3D mPosition;
|
aiVector3D mPosition;
|
||||||
|
|
||||||
/** Direction of the light source in space. Relative to the
|
/** Direction of the light source in space. Relative to the
|
||||||
* node corresponding to the light.
|
* transformation of the node corresponding to the light.
|
||||||
*
|
*
|
||||||
* The direction is undefined for point lights.
|
* The direction is undefined for point lights. The vector
|
||||||
|
* may be normalized, but it needn't.
|
||||||
*/
|
*/
|
||||||
aiVector3D mDirection;
|
aiVector3D mDirection;
|
||||||
|
|
||||||
|
@ -115,7 +120,7 @@ struct aiLight
|
||||||
* @code
|
* @code
|
||||||
* Atten = 1/( att0 + att1 * d + att2 * d*d)
|
* Atten = 1/( att0 + att1 * d + att2 * d*d)
|
||||||
* @endcode
|
* @endcode
|
||||||
* This member corresponds to the att01 variable in the equation.
|
* This member corresponds to the att0 variable in the equation.
|
||||||
*/
|
*/
|
||||||
float mAttenuationConstant;
|
float mAttenuationConstant;
|
||||||
|
|
||||||
|
@ -126,7 +131,7 @@ struct aiLight
|
||||||
* @code
|
* @code
|
||||||
* Atten = 1/( att0 + att1 * d + att2 * d*d)
|
* Atten = 1/( att0 + att1 * d + att2 * d*d)
|
||||||
* @endcode
|
* @endcode
|
||||||
* This member corresponds to the att02 variable in the equation.
|
* This member corresponds to the att1 variable in the equation.
|
||||||
*/
|
*/
|
||||||
float mAttenuationLinear;
|
float mAttenuationLinear;
|
||||||
|
|
||||||
|
@ -137,28 +142,33 @@ struct aiLight
|
||||||
* @code
|
* @code
|
||||||
* Atten = 1/( att0 + att1 * d + att2 * d*d)
|
* Atten = 1/( att0 + att1 * d + att2 * d*d)
|
||||||
* @endcode
|
* @endcode
|
||||||
* This member corresponds to the att03 variable in the equation.
|
* This member corresponds to the att2 variable in the equation.
|
||||||
*/
|
*/
|
||||||
float mAttenuationQuadratic;
|
float mAttenuationQuadratic;
|
||||||
|
|
||||||
/** Diffuse color of the light source
|
/** Diffuse color of the light source
|
||||||
*
|
*
|
||||||
* The color has no alpha component which wouldn't make
|
* The diffuse light color is multiplied with the diffuse
|
||||||
* sense for light sources.
|
* material color to obtain the final color that contributes
|
||||||
|
* to the diffuse shading term.
|
||||||
*/
|
*/
|
||||||
aiColor3D mColorDiffuse;
|
aiColor3D mColorDiffuse;
|
||||||
|
|
||||||
/** Specular color of the light source
|
/** Specular color of the light source
|
||||||
*
|
*
|
||||||
* The color has no alpha component which wouldn't make
|
* The specular light color is multiplied with the specular
|
||||||
* sense for light sources.
|
* material color to obtain the final color that contributes
|
||||||
|
* to the specular shading term.
|
||||||
*/
|
*/
|
||||||
aiColor3D mColorSpecular;
|
aiColor3D mColorSpecular;
|
||||||
|
|
||||||
/** Ambient color of the light source
|
/** Ambient color of the light source
|
||||||
*
|
*
|
||||||
* The color has no alpha component which wouldn't make
|
* The ambient light color is multiplied with the ambient
|
||||||
* sense for light sources.
|
* material color to obtain the final color that contributes
|
||||||
|
* to the ambient shading term. Most renderers will ignore
|
||||||
|
* this value it, is just a remaining of the fixed-function pipeline
|
||||||
|
* that is still supported by quite many file formats.
|
||||||
*/
|
*/
|
||||||
aiColor3D mColorAmbient;
|
aiColor3D mColorAmbient;
|
||||||
|
|
||||||
|
@ -168,18 +178,19 @@ struct aiLight
|
||||||
* angle. The angle is given in radians. It is 2PI for point
|
* angle. The angle is given in radians. It is 2PI for point
|
||||||
* lights and undefined for directional lights.
|
* lights and undefined for directional lights.
|
||||||
*/
|
*/
|
||||||
float mAngleOuterCone;
|
float mAngleInnerCone;
|
||||||
|
|
||||||
/** Outer angle of a spot light's light cone.
|
/** Outer angle of a spot light's light cone.
|
||||||
*
|
*
|
||||||
* The spot light does not affect objects outside this angle.
|
* The spot light does not affect objects outside this angle.
|
||||||
* The angle is given in radians. It is 2PI for point lights and
|
* The angle is given in radians. It is 2PI for point lights and
|
||||||
* undefined for directional lights.
|
* undefined for directional lights. The outer angle must be
|
||||||
|
* greater than or equal to the inner angle.
|
||||||
* It is assumed that the application uses a smooth
|
* It is assumed that the application uses a smooth
|
||||||
* interpolation between the inner and the outer cone of the
|
* interpolation between the inner and the outer cone of the
|
||||||
* spot light.
|
* spot light.
|
||||||
*/
|
*/
|
||||||
float mAngleInnerCone;
|
float mAngleOuterCone;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
@ -188,8 +199,8 @@ struct aiLight
|
||||||
, mAttenuationConstant (0.f)
|
, mAttenuationConstant (0.f)
|
||||||
, mAttenuationLinear (1.f)
|
, mAttenuationLinear (1.f)
|
||||||
, mAttenuationQuadratic (0.f)
|
, mAttenuationQuadratic (0.f)
|
||||||
, mAngleOuterCone ((float)AI_MATH_TWO_PI)
|
|
||||||
, mAngleInnerCone ((float)AI_MATH_TWO_PI)
|
, mAngleInnerCone ((float)AI_MATH_TWO_PI)
|
||||||
|
, mAngleOuterCone ((float)AI_MATH_TWO_PI)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,4 +212,4 @@ struct aiLight
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif // !! __AI_LIGHT_H_INC__
|
#endif // !! __AI_LIGHT_H_INC__
|
||||||
|
|
|
@ -240,6 +240,20 @@ struct aiMaterialProperty
|
||||||
* is never 0
|
* is never 0
|
||||||
*/
|
*/
|
||||||
char* mData;
|
char* mData;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
aiMaterialProperty()
|
||||||
|
{
|
||||||
|
mData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
~aiMaterialProperty()
|
||||||
|
{
|
||||||
|
delete[] mData;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -173,21 +173,15 @@ inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
|
||||||
// and remove all scaling from the matrix
|
// and remove all scaling from the matrix
|
||||||
if(scaling.x)
|
if(scaling.x)
|
||||||
{
|
{
|
||||||
vRows[0].x /= scaling.x;
|
vRows[0] /= scaling.x;
|
||||||
vRows[0].y /= scaling.x;
|
|
||||||
vRows[0].z /= scaling.x;
|
|
||||||
}
|
}
|
||||||
if(scaling.y)
|
if(scaling.y)
|
||||||
{
|
{
|
||||||
vRows[1].x /= scaling.y;
|
vRows[1] /= scaling.y;
|
||||||
vRows[1].y /= scaling.y;
|
|
||||||
vRows[1].z /= scaling.y;
|
|
||||||
}
|
}
|
||||||
if(scaling.z)
|
if(scaling.z)
|
||||||
{
|
{
|
||||||
vRows[2].x /= scaling.z;
|
vRows[2] /= scaling.z;
|
||||||
vRows[2].y /= scaling.z;
|
|
||||||
vRows[2].z /= scaling.z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a 3x3 rotation matrix
|
// build a 3x3 rotation matrix
|
||||||
|
@ -217,7 +211,7 @@ inline void aiMatrix4x4::FromEulerAngles(float x, float y, float z)
|
||||||
{
|
{
|
||||||
aiMatrix4x4& _this = *this;
|
aiMatrix4x4& _this = *this;
|
||||||
|
|
||||||
const float A = ::cos(x);
|
const float A = ::cos(x);
|
||||||
const float B = ::sin(x);
|
const float B = ::sin(x);
|
||||||
const float C = ::cos(y);
|
const float C = ::cos(y);
|
||||||
const float D = ::sin(y);
|
const float D = ::sin(y);
|
||||||
|
|
|
@ -41,8 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
/** @file Declares the data structures in which the imported geometry is
|
/** @file Declares the data structures in which the imported geometry is
|
||||||
returned by ASSIMP: aiMesh, aiFace and aiBone data structures. */
|
returned by ASSIMP: aiMesh, aiFace and aiBone data structures. */
|
||||||
#ifndef AI_MESH_H_INC
|
#ifndef __AI_MESH_H_INC__
|
||||||
#define AI_MESH_H_INC
|
#define __AI_MESH_H_INC__
|
||||||
|
|
||||||
#include "aiTypes.h"
|
#include "aiTypes.h"
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ extern "C" {
|
||||||
* Point and line primitives are rarely used and are NOT supported. However,
|
* Point and line primitives are rarely used and are NOT supported. However,
|
||||||
* a load could pass them as degenerated triangles.
|
* a load could pass them as degenerated triangles.
|
||||||
*/
|
*/
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
struct aiFace
|
struct aiFace
|
||||||
{
|
{
|
||||||
//! Number of indices defining this face. 3 for a triangle, >3 for polygon
|
//! Number of indices defining this face. 3 for a triangle, >3 for polygon
|
||||||
|
@ -130,7 +129,6 @@ struct aiFace
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** A single influence of a bone on a vertex.
|
/** A single influence of a bone on a vertex.
|
||||||
*/
|
*/
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
struct aiVertexWeight
|
struct aiVertexWeight
|
||||||
{
|
{
|
||||||
//! Index of the vertex which is influenced by the bone.
|
//! Index of the vertex which is influenced by the bone.
|
||||||
|
@ -161,7 +159,6 @@ struct aiVertexWeight
|
||||||
* in the frame hierarchy and by which it can be addressed by animations.
|
* in the frame hierarchy and by which it can be addressed by animations.
|
||||||
* In addition it has a number of influences on vertices.
|
* In addition it has a number of influences on vertices.
|
||||||
*/
|
*/
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
struct aiBone
|
struct aiBone
|
||||||
{
|
{
|
||||||
//! The name of the bone.
|
//! The name of the bone.
|
||||||
|
@ -218,7 +215,6 @@ struct aiBone
|
||||||
* \note Some internal structures expect (and assert) this value
|
* \note Some internal structures expect (and assert) this value
|
||||||
* to be at least 4
|
* to be at least 4
|
||||||
*/
|
*/
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
# define AI_MAX_NUMBER_OF_COLOR_SETS 0x4
|
# define AI_MAX_NUMBER_OF_COLOR_SETS 0x4
|
||||||
|
|
||||||
#endif // !! AI_MAX_NUMBER_OF_COLOR_SETS
|
#endif // !! AI_MAX_NUMBER_OF_COLOR_SETS
|
||||||
|
@ -234,7 +230,6 @@ struct aiBone
|
||||||
* \note Some internal structures expect (and assert) this value
|
* \note Some internal structures expect (and assert) this value
|
||||||
* to be at least 4
|
* to be at least 4
|
||||||
*/
|
*/
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
# define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x4
|
# define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x4
|
||||||
|
|
||||||
// NOTE (Aramis): If you change these values, make sure that you also
|
// NOTE (Aramis): If you change these values, make sure that you also
|
||||||
|
@ -248,33 +243,34 @@ struct aiBone
|
||||||
|
|
||||||
#endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
|
#endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
|
||||||
|
|
||||||
#define AI_MESH_SMOOTHING_ANGLE_NOT_SET (10e10f)
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Enumerates the types of geometric primitives supported by Assimp.
|
/** Enumerates the types of geometric primitives supported by Assimp.
|
||||||
*/
|
*/
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
enum aiPrimitiveType
|
enum aiPrimitiveType
|
||||||
{
|
{
|
||||||
/** A point primitive.
|
/** A point primitive.
|
||||||
|
*
|
||||||
* This is just a single vertex in the virtual world,
|
* This is just a single vertex in the virtual world,
|
||||||
* #aiFace contains just one index for such a primitive.
|
* #aiFace contains just one index for such a primitive.
|
||||||
*/
|
*/
|
||||||
aiPrimitiveType_POINT = 0x1,
|
aiPrimitiveType_POINT = 0x1,
|
||||||
|
|
||||||
/** A line primitive.
|
/** A line primitive.
|
||||||
|
*
|
||||||
* This is a line defined through a start and an end position.
|
* This is a line defined through a start and an end position.
|
||||||
* #aiFace contains exactly two indices for such a primitive.
|
* #aiFace contains exactly two indices for such a primitive.
|
||||||
*/
|
*/
|
||||||
aiPrimitiveType_LINE = 0x2,
|
aiPrimitiveType_LINE = 0x2,
|
||||||
|
|
||||||
/** A triangular primitive.
|
/** A triangular primitive.
|
||||||
|
*
|
||||||
* A triangle consists of three indices.
|
* A triangle consists of three indices.
|
||||||
*/
|
*/
|
||||||
aiPrimitiveType_TRIANGLE = 0x4,
|
aiPrimitiveType_TRIANGLE = 0x4,
|
||||||
|
|
||||||
/** A higher-level polygon with more than 3 edges.
|
/** A higher-level polygon with more than 3 edges.
|
||||||
|
*
|
||||||
* A triangle is a polygon, but polygon in this context means
|
* A triangle is a polygon, but polygon in this context means
|
||||||
* "all polygons that are not triangles". The "Triangulate"-Step
|
* "all polygons that are not triangles". The "Triangulate"-Step
|
||||||
* is provided for your convinience, it splits all polygons in
|
* is provided for your convinience, it splits all polygons in
|
||||||
|
@ -298,9 +294,9 @@ enum aiPrimitiveType
|
||||||
*
|
*
|
||||||
* A Mesh uses only a single material which is referenced by a material ID.
|
* A Mesh uses only a single material which is referenced by a material ID.
|
||||||
* \note The mPositions member is not optional, although a Has()-Method is
|
* \note The mPositions member is not optional, although a Has()-Method is
|
||||||
* provided for it.
|
* provided for it. However, positions *could* be missing if the
|
||||||
|
* AI_SCENE_FLAGS_INCOMPLETE flag is set in aiScene::mFlags.
|
||||||
*/
|
*/
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
struct aiMesh
|
struct aiMesh
|
||||||
{
|
{
|
||||||
/** Bitwise combination of the members of the #aiPrimitiveType enum.
|
/** Bitwise combination of the members of the #aiPrimitiveType enum.
|
||||||
|
@ -328,14 +324,23 @@ struct aiMesh
|
||||||
|
|
||||||
/** Vertex normals.
|
/** Vertex normals.
|
||||||
* The array contains normalized vectors, NULL if not present.
|
* The array contains normalized vectors, NULL if not present.
|
||||||
* The array is mNumVertices in size.
|
* The array is mNumVertices in size. Normals are undefined for
|
||||||
|
* point and line primitives. A mesh consisting of points and
|
||||||
|
* lines only may not have normal vectors. Meshes with mixed
|
||||||
|
* primitive types (i.e. lines and triangles) may have normals,
|
||||||
|
* but the normals for vertices that are only referenced by
|
||||||
|
* point or line primitives are undefined and set to QNaN.
|
||||||
*/
|
*/
|
||||||
C_STRUCT aiVector3D* mNormals;
|
C_STRUCT aiVector3D* mNormals;
|
||||||
|
|
||||||
/** Vertex tangents.
|
/** Vertex tangents.
|
||||||
* The tangent of a vertex points in the direction of the positive
|
* The tangent of a vertex points in the direction of the positive
|
||||||
* X texture axis. The array contains normalized vectors, NULL if
|
* X texture axis. The array contains normalized vectors, NULL if
|
||||||
* not present. The array is mNumVertices in size.
|
* not present. The array is mNumVertices in size. A mesh consisting
|
||||||
|
* of points and lines only may not have normal vectors. Meshes with
|
||||||
|
* mixed primitive types (i.e. lines and triangles) may have
|
||||||
|
* normals, but the normals for vertices that are only referenced by
|
||||||
|
* point or line primitives are undefined and set to QNaN.
|
||||||
* @note If the mesh contains tangents, it automatically also
|
* @note If the mesh contains tangents, it automatically also
|
||||||
* contains bitangents.
|
* contains bitangents.
|
||||||
*/
|
*/
|
||||||
|
@ -368,6 +373,7 @@ struct aiMesh
|
||||||
* or cube maps). If the value is 2 for a given channel n, the
|
* or cube maps). If the value is 2 for a given channel n, the
|
||||||
* component p.z of mTextureCoords[n][p] is set to 0.0f.
|
* component p.z of mTextureCoords[n][p] is set to 0.0f.
|
||||||
* If the value is 1 for a given channel, p.y is set to 0.0f, too.
|
* If the value is 1 for a given channel, p.y is set to 0.0f, too.
|
||||||
|
* If this value is 0, 2 should be assumed.
|
||||||
* @note 4D coords are not supported
|
* @note 4D coords are not supported
|
||||||
*/
|
*/
|
||||||
unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||||
|
@ -375,7 +381,8 @@ struct aiMesh
|
||||||
/** The faces the mesh is contstructed from.
|
/** The faces the mesh is contstructed from.
|
||||||
* Each face referres to a number of vertices by their indices.
|
* Each face referres to a number of vertices by their indices.
|
||||||
* This array is always present in a mesh, its size is given
|
* This array is always present in a mesh, its size is given
|
||||||
* in mNumFaces.
|
* in mNumFaces. If the AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
|
||||||
|
* is NOT set each face references an unique set of vertices.
|
||||||
*/
|
*/
|
||||||
C_STRUCT aiFace* mFaces;
|
C_STRUCT aiFace* mFaces;
|
||||||
|
|
||||||
|
@ -422,7 +429,7 @@ struct aiMesh
|
||||||
//! Deletes all storage allocated for the mesh
|
//! Deletes all storage allocated for the mesh
|
||||||
~aiMesh()
|
~aiMesh()
|
||||||
{
|
{
|
||||||
if ( mNumVertices) // fix to make this work for invalid scenes, too
|
if ( mNumVertices ) // fix to make this work for invalid scenes, too
|
||||||
{
|
{
|
||||||
delete [] mVertices;
|
delete [] mVertices;
|
||||||
delete [] mNormals;
|
delete [] mNormals;
|
||||||
|
@ -433,7 +440,7 @@ struct aiMesh
|
||||||
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
|
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
|
||||||
delete [] mColors[a];
|
delete [] mColors[a];
|
||||||
}
|
}
|
||||||
if ( mNumBones) // fix to make this work for invalid scenes, too
|
if ( mNumBones && mBones) // fix to make this work for invalid scenes, too
|
||||||
{
|
{
|
||||||
for( unsigned int a = 0; a < mNumBones; a++)
|
for( unsigned int a = 0; a < mNumBones; a++)
|
||||||
delete mBones[a];
|
delete mBones[a];
|
||||||
|
@ -461,6 +468,9 @@ struct aiMesh
|
||||||
{ return mNormals != NULL; }
|
{ return mNormals != NULL; }
|
||||||
|
|
||||||
//! Check whether the mesh contains tangent and bitangent vectors
|
//! Check whether the mesh contains tangent and bitangent vectors
|
||||||
|
//! It is not possible that it contains tangents and no bitangents
|
||||||
|
//! (or the other way round). The existence of one of them
|
||||||
|
//! implies that the second is there, too.
|
||||||
inline bool HasTangentsAndBitangents() const
|
inline bool HasTangentsAndBitangents() const
|
||||||
{ return mTangents != NULL && mBitangents != NULL; }
|
{ return mTangents != NULL && mBitangents != NULL; }
|
||||||
|
|
||||||
|
@ -478,7 +488,7 @@ struct aiMesh
|
||||||
//! \param pIndex Index of the texture coordinates set
|
//! \param pIndex Index of the texture coordinates set
|
||||||
inline bool HasTextureCoords( unsigned int pIndex) const
|
inline bool HasTextureCoords( unsigned int pIndex) const
|
||||||
{
|
{
|
||||||
if( pIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
|
if( pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS)
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return mTextureCoords[pIndex] != NULL;
|
return mTextureCoords[pIndex] != NULL;
|
||||||
|
@ -494,5 +504,5 @@ struct aiMesh
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // AI_MESH_H_INC
|
#endif // __AI_MESH_H_INC
|
||||||
|
|
||||||
|
|
|
@ -40,13 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file Defines the data structures in which the imported scene is returned. */
|
/** @file Defines the data structures in which the imported scene is returned. */
|
||||||
#ifndef AI_SCENE_H_INC
|
#ifndef __AI_SCENE_H_INC__
|
||||||
#define AI_SCENE_H_INC
|
#define __AI_SCENE_H_INC__
|
||||||
|
|
||||||
#include "aiTypes.h"
|
#include "aiTypes.h"
|
||||||
#include "aiMesh.h"
|
|
||||||
#include "aiMaterial.h"
|
|
||||||
#include "aiTexture.h"
|
#include "aiTexture.h"
|
||||||
|
#include "aiMesh.h"
|
||||||
|
#include "aiLight.h"
|
||||||
|
#include "aiCamera.h"
|
||||||
|
#include "aiMaterial.h"
|
||||||
#include "aiAnim.h"
|
#include "aiAnim.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -80,8 +82,8 @@ struct aiNode
|
||||||
|
|
||||||
/** The number of child nodes of this node. */
|
/** The number of child nodes of this node. */
|
||||||
unsigned int mNumChildren;
|
unsigned int mNumChildren;
|
||||||
/** The child nodes of this node. NULL if mNumChildren is 0. */
|
|
||||||
|
|
||||||
|
/** The child nodes of this node. NULL if mNumChildren is 0. */
|
||||||
C_STRUCT aiNode** mChildren;
|
C_STRUCT aiNode** mChildren;
|
||||||
|
|
||||||
/** The number of meshes of this node. */
|
/** The number of meshes of this node. */
|
||||||
|
@ -113,8 +115,9 @@ struct aiNode
|
||||||
/** Destructor */
|
/** Destructor */
|
||||||
~aiNode()
|
~aiNode()
|
||||||
{
|
{
|
||||||
// delete al children recursively
|
// delete all children recursively
|
||||||
if (mChildren) // fix to make the d'tor work for invalid scenes, too
|
// to make sure we won't crash if the data is invalid ...
|
||||||
|
if (mChildren && mNumChildren)
|
||||||
{
|
{
|
||||||
for( unsigned int a = 0; a < mNumChildren; a++)
|
for( unsigned int a = 0; a < mNumChildren; a++)
|
||||||
delete mChildren[a];
|
delete mChildren[a];
|
||||||
|
@ -122,17 +125,66 @@ struct aiNode
|
||||||
}
|
}
|
||||||
delete [] mMeshes;
|
delete [] mMeshes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Searches for a node with a specific name, beginning at this
|
||||||
|
* nodes. Normally you will call this method on the root node
|
||||||
|
* of the scene.
|
||||||
|
*
|
||||||
|
* @param name Name to seach for
|
||||||
|
* @return NULL or a valid Node if the search was successful.
|
||||||
|
*/
|
||||||
|
inline aiNode* FindNode(const aiString& name)
|
||||||
|
{
|
||||||
|
if (mName == name)return this;
|
||||||
|
for (unsigned int i = 0; i < mNumChildren;++i)
|
||||||
|
{
|
||||||
|
aiNode* p = mChildren[i]->FindNode(name);
|
||||||
|
if (p)return p;
|
||||||
|
}
|
||||||
|
// there is definitely no sub node with this name
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
};
|
};
|
||||||
|
|
||||||
//! @def AI_SCENE_FLAGS_ANIM_SKELETON_ONLY
|
|
||||||
//! Specifies that no full model but only an animation skeleton has been
|
|
||||||
//! imported. There are no materials in this case. There are no
|
|
||||||
//! textures in this case. But there is a node graph, animation channels
|
|
||||||
//! and propably meshes with bones. Validation of meshes is less strict
|
|
||||||
//! with this flag, so be careful.
|
|
||||||
#define AI_SCENE_FLAGS_ANIM_SKELETON_ONLY 0x1
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** @def AI_SCENE_FLAGS_INCOMPLETE
|
||||||
|
* Specifies that the scene data structure that was imported is not complete.
|
||||||
|
* This flag bypasses some internal validations and allows the import
|
||||||
|
* of animation skeletons, material libraries or camera animation paths
|
||||||
|
* using Assimp. Most applications won't support such data.
|
||||||
|
*/
|
||||||
|
#define AI_SCENE_FLAGS_INCOMPLETE 0x1
|
||||||
|
|
||||||
|
|
||||||
|
/** @def AI_SCENE_FLAGS_VALIDATED
|
||||||
|
* This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
|
||||||
|
* if the validation is successful. In a validated scene you can be sure that
|
||||||
|
* any cross references in the data structure (e.g. vertex indices) are valid.
|
||||||
|
*/
|
||||||
|
#define AI_SCENE_FLAGS_VALIDATED 0x2
|
||||||
|
|
||||||
|
|
||||||
|
/** @def AI_SCENE_FLAGS_VALIDATION_WARNING
|
||||||
|
* This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
|
||||||
|
* if the validation is successful but some issues have been found.
|
||||||
|
* This can for example mean that a texture that does not exist is referenced
|
||||||
|
* by a material or that the bone weights for a vertex don't sum to 1.0 ... .
|
||||||
|
* In most cases you should still be able to use the import. This flag could
|
||||||
|
* be useful for applications which don't capture Assimp's log output.
|
||||||
|
*/
|
||||||
|
#define AI_SCENE_FLAGS_VALIDATION_WARNING 0x4
|
||||||
|
|
||||||
|
|
||||||
|
/** @def AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
|
||||||
|
* This flag is currently only set by the aiProcess_JoinIdenticalVertices step.
|
||||||
|
* It indicates that the vertices of the output meshes aren't in the internal
|
||||||
|
* verbose format anymore. In the verbose format all vertices are unique,
|
||||||
|
* no vertex is ever referenced by more than one face.
|
||||||
|
*/
|
||||||
|
#define AI_SCENE_FLAGS_NON_VERBOSE_FORMAT 0x8
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** The root structure of the imported data.
|
/** The root structure of the imported data.
|
||||||
|
@ -143,15 +195,20 @@ struct aiNode
|
||||||
struct aiScene
|
struct aiScene
|
||||||
{
|
{
|
||||||
|
|
||||||
/** Any combination of the AI_SCENE_FLAGS_XXX flags */
|
/** Any combination of the AI_SCENE_FLAGS_XXX flags. By default
|
||||||
|
* this value is 0, no flags are set. Most applications will
|
||||||
|
* want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE
|
||||||
|
* bit set.
|
||||||
|
*/
|
||||||
unsigned int mFlags;
|
unsigned int mFlags;
|
||||||
|
|
||||||
|
|
||||||
/** The root node of the hierarchy.
|
/** The root node of the hierarchy.
|
||||||
*
|
*
|
||||||
* There will always be at least the root node if the import
|
* There will always be at least the root node if the import
|
||||||
* was successful. Presence of further nodes depends on the
|
* was successful (and no special flags have been set).
|
||||||
* format and content of the imported file.
|
* Presence of further nodes depends on the format and content
|
||||||
|
* of the imported file.
|
||||||
*/
|
*/
|
||||||
C_STRUCT aiNode* mRootNode;
|
C_STRUCT aiNode* mRootNode;
|
||||||
|
|
||||||
|
@ -163,7 +220,9 @@ struct aiScene
|
||||||
/** The array of meshes.
|
/** The array of meshes.
|
||||||
*
|
*
|
||||||
* Use the indices given in the aiNode structure to access
|
* Use the indices given in the aiNode structure to access
|
||||||
* this array. The array is mNumMeshes in size.
|
* this array. The array is mNumMeshes in size. If the
|
||||||
|
* AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
|
||||||
|
* be at least ONE material.
|
||||||
*/
|
*/
|
||||||
C_STRUCT aiMesh** mMeshes;
|
C_STRUCT aiMesh** mMeshes;
|
||||||
|
|
||||||
|
@ -175,7 +234,9 @@ struct aiScene
|
||||||
/** The array of materials.
|
/** The array of materials.
|
||||||
*
|
*
|
||||||
* Use the index given in each aiMesh structure to access this
|
* Use the index given in each aiMesh structure to access this
|
||||||
* array. The array is mNumMaterials in size.
|
* array. The array is mNumMaterials in size. If the
|
||||||
|
* AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
|
||||||
|
* be at least ONE material.
|
||||||
*/
|
*/
|
||||||
C_STRUCT aiMaterial** mMaterials;
|
C_STRUCT aiMaterial** mMaterials;
|
||||||
|
|
||||||
|
@ -200,10 +261,36 @@ struct aiScene
|
||||||
*
|
*
|
||||||
* Not many file formats embedd their textures into the file.
|
* Not many file formats embedd their textures into the file.
|
||||||
* An example is Quake's MDL format (which is also used by
|
* An example is Quake's MDL format (which is also used by
|
||||||
* some GameStudio™ versions)
|
* some GameStudio versions)
|
||||||
*/
|
*/
|
||||||
C_STRUCT aiTexture** mTextures;
|
C_STRUCT aiTexture** mTextures;
|
||||||
|
|
||||||
|
|
||||||
|
/** The number of light sources in the scene. Light sources
|
||||||
|
are fully optional, in most cases this attribute will be 0 */
|
||||||
|
unsigned int mNumLights;
|
||||||
|
|
||||||
|
/** The array of light sources.
|
||||||
|
*
|
||||||
|
* All light sources imported from the given file are
|
||||||
|
* listed here. The array is mNumLights in size.
|
||||||
|
*/
|
||||||
|
C_STRUCT aiLight** mLights;
|
||||||
|
|
||||||
|
|
||||||
|
/** The number of cameras in the scene. Cameras
|
||||||
|
are fully optional, in most cases this attribute will be 0 */
|
||||||
|
unsigned int mNumCameras;
|
||||||
|
|
||||||
|
/** The array of cameras.
|
||||||
|
*
|
||||||
|
* All cameras imported from the given file are listed here.
|
||||||
|
* The array is mNumCameras in size. The first camera in the
|
||||||
|
* array (if existing) is the default camera view into
|
||||||
|
* the scene.
|
||||||
|
*/
|
||||||
|
C_STRUCT aiCamera** mCameras;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
//! Default constructor
|
//! Default constructor
|
||||||
|
@ -215,6 +302,8 @@ struct aiScene
|
||||||
mNumMaterials = 0; mMaterials = NULL;
|
mNumMaterials = 0; mMaterials = NULL;
|
||||||
mNumAnimations = 0; mAnimations = NULL;
|
mNumAnimations = 0; mAnimations = NULL;
|
||||||
mNumTextures = 0; mTextures = NULL;
|
mNumTextures = 0; mTextures = NULL;
|
||||||
|
mNumCameras = 0; mCameras = NULL;
|
||||||
|
mNumLights = 0; mLights = NULL;
|
||||||
mFlags = 0;
|
mFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,31 +312,74 @@ struct aiScene
|
||||||
{
|
{
|
||||||
// delete all subobjects recursively
|
// delete all subobjects recursively
|
||||||
delete mRootNode;
|
delete mRootNode;
|
||||||
if (mNumMeshes) // fix to make the d'tor work for invalid scenes, too
|
|
||||||
|
// To make sure we won't crash if the data is invalid it's
|
||||||
|
// mich better to check whether both mNumXXX and mXXX are
|
||||||
|
// valid instead of relying on just one of them.
|
||||||
|
if (mNumMeshes && mMeshes)
|
||||||
{
|
{
|
||||||
for( unsigned int a = 0; a < mNumMeshes; a++)
|
for( unsigned int a = 0; a < mNumMeshes; a++)
|
||||||
delete mMeshes[a];
|
delete mMeshes[a];
|
||||||
delete [] mMeshes;
|
delete [] mMeshes;
|
||||||
}
|
}
|
||||||
if (mNumMaterials) // fix to make the d'tor work for invalid scenes, too
|
if (mNumMaterials && mMaterials)
|
||||||
{
|
{
|
||||||
for( unsigned int a = 0; a < mNumMaterials; a++)
|
for( unsigned int a = 0; a < mNumMaterials; a++)
|
||||||
delete mMaterials[a];
|
delete mMaterials[a];
|
||||||
delete [] mMaterials;
|
delete [] mMaterials;
|
||||||
}
|
}
|
||||||
if (mNumAnimations) // fix to make the d'tor work for invalid scenes, too
|
if (mNumAnimations && mAnimations)
|
||||||
{
|
{
|
||||||
for( unsigned int a = 0; a < mNumAnimations; a++)
|
for( unsigned int a = 0; a < mNumAnimations; a++)
|
||||||
delete mAnimations[a];
|
delete mAnimations[a];
|
||||||
delete [] mAnimations;
|
delete [] mAnimations;
|
||||||
}
|
}
|
||||||
if (mNumTextures) // fix to make the d'tor work for invalid scenes, too
|
if (mNumTextures && mTextures)
|
||||||
{
|
{
|
||||||
for( unsigned int a = 0; a < mNumTextures; a++)
|
for( unsigned int a = 0; a < mNumTextures; a++)
|
||||||
delete mTextures[a];
|
delete mTextures[a];
|
||||||
delete [] mTextures;
|
delete [] mTextures;
|
||||||
}
|
}
|
||||||
|
if (mNumLights && mLights)
|
||||||
|
{
|
||||||
|
for( unsigned int a = 0; a < mNumLights; a++)
|
||||||
|
delete mLights[a];
|
||||||
|
delete [] mLights;
|
||||||
|
}
|
||||||
|
if (mNumCameras && mCameras)
|
||||||
|
{
|
||||||
|
for( unsigned int a = 0; a < mNumCameras; a++)
|
||||||
|
delete mCameras[a];
|
||||||
|
delete [] mCameras;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Check whether the scene contains meshes
|
||||||
|
//! Unless no special scene flags are set this will always be true.
|
||||||
|
inline bool HasMeshes() const
|
||||||
|
{ return mMeshes != NULL; }
|
||||||
|
|
||||||
|
//! Check whether the scene contains materials
|
||||||
|
//! Unless no special scene flags are set this will always be true.
|
||||||
|
inline bool HasMaterials() const
|
||||||
|
{ return mMaterials != NULL; }
|
||||||
|
|
||||||
|
//! Check whether the scene contains lights
|
||||||
|
inline bool HasLights() const
|
||||||
|
{ return mLights != NULL; }
|
||||||
|
|
||||||
|
//! Check whether the scene contains textures
|
||||||
|
inline bool HasTextures() const
|
||||||
|
{ return mTextures != NULL; }
|
||||||
|
|
||||||
|
//! Check whether the scene contains cameras
|
||||||
|
inline bool HasCameras() const
|
||||||
|
{ return mCameras != NULL; }
|
||||||
|
|
||||||
|
//! Check whether the scene contains animations
|
||||||
|
inline bool HasAnimations() const
|
||||||
|
{ return mAnimations != NULL; }
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,4 +387,4 @@ struct aiScene
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // AI_SCENE_H_INC
|
#endif // __AI_SCENE_H_INC__
|
||||||
|
|
|
@ -69,15 +69,8 @@ extern "C" {
|
||||||
# define AI_MAKE_EMBEDDED_TEXNAME(_n_) "*" # _n_
|
# define AI_MAKE_EMBEDDED_TEXNAME(_n_) "*" # _n_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ugly compiler dependent packing stuff
|
|
||||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
#include "./Compiler/pushpack1.h"
|
||||||
# pragma pack(push,1)
|
|
||||||
# define PACK_STRUCT
|
|
||||||
#elif defined( __GNUC__ )
|
|
||||||
# define PACK_STRUCT __attribute__((packed))
|
|
||||||
#else
|
|
||||||
# error Compiler not supported. Never do this again.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Helper structure to represent a texel in ARGB8888 format
|
/** Helper structure to represent a texel in ARGB8888 format
|
||||||
|
@ -87,11 +80,9 @@ extern "C" {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
struct aiTexel
|
struct aiTexel
|
||||||
{
|
{
|
||||||
unsigned char b;
|
uint8_t b,g,r,a;
|
||||||
unsigned char g;
|
|
||||||
unsigned char r;
|
|
||||||
unsigned char a;
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
//! Comparison operator
|
//! Comparison operator
|
||||||
bool operator== (const aiTexel& other) const
|
bool operator== (const aiTexel& other) const
|
||||||
{
|
{
|
||||||
|
@ -105,14 +96,11 @@ struct aiTexel
|
||||||
return b != other.b || r != other.r ||
|
return b != other.b || r != other.r ||
|
||||||
g != other.g || a != other.a;
|
g != other.g || a != other.a;
|
||||||
}
|
}
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
} PACK_STRUCT;
|
} PACK_STRUCT;
|
||||||
|
|
||||||
// reset packing to the original value
|
#include "./Compiler/poppack1.h"
|
||||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
|
||||||
# pragma pack( pop )
|
|
||||||
#endif
|
|
||||||
#undef PACK_STRUCT
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Helper structure to describe an embedded texture
|
/** Helper structure to describe an embedded texture
|
||||||
|
@ -164,12 +152,14 @@ struct aiTexture
|
||||||
|
|
||||||
// Construction
|
// Construction
|
||||||
aiTexture ()
|
aiTexture ()
|
||||||
: mWidth(0), mHeight(0), pcData(NULL)
|
: mWidth (0)
|
||||||
|
, mHeight (0)
|
||||||
|
, pcData (NULL)
|
||||||
{
|
{
|
||||||
achFormatHint[0] = '\0';
|
achFormatHint[0] = 0;
|
||||||
achFormatHint[1] = '\0';
|
achFormatHint[1] = 0;
|
||||||
achFormatHint[2] = '\0';
|
achFormatHint[2] = 0;
|
||||||
achFormatHint[3] = '\0';
|
achFormatHint[3] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destruction
|
// Destruction
|
||||||
|
|
|
@ -114,19 +114,15 @@ struct aiColor3D
|
||||||
aiColor3D operator*(const aiColor3D& c) const
|
aiColor3D operator*(const aiColor3D& c) const
|
||||||
{return aiColor3D(r*c.r,g*c.g,b*c.b);}
|
{return aiColor3D(r*c.r,g*c.g,b*c.b);}
|
||||||
|
|
||||||
aiColor3D operator*(float f)
|
aiColor3D operator*(float f) const
|
||||||
{return aiColor3D(r*f,g*f,b*f);}
|
{return aiColor3D(r*f,g*f,b*f);}
|
||||||
|
|
||||||
// ugly subscript operator ... should better use an union, but
|
inline float operator[](unsigned int i) const {return *(&r + i);}
|
||||||
// hopefully the compiler will optimize the switch away.
|
inline float& operator[](unsigned int i) {return *(&r + i);}
|
||||||
inline float& operator[] (unsigned int sub)
|
|
||||||
|
inline bool IsBlack() const
|
||||||
{
|
{
|
||||||
switch (sub)
|
return !r && !g && !b;
|
||||||
{
|
|
||||||
case 0: return (float&)r;
|
|
||||||
case 1: return (float&)g;
|
|
||||||
default: return (float&)b;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__cplusplus
|
#endif // !__cplusplus
|
||||||
|
@ -156,17 +152,13 @@ struct aiColor4D
|
||||||
bool operator != (const aiColor4D& other) const
|
bool operator != (const aiColor4D& other) const
|
||||||
{return r != other.r || g != other.g || b != other.b || a != other.a;}
|
{return r != other.r || g != other.g || b != other.b || a != other.a;}
|
||||||
|
|
||||||
// ugly subscript operator ... should better use an union, but
|
inline float operator[](unsigned int i) const {return *(&r + i);}
|
||||||
// hopefully the compiler will optimize the switch away.
|
inline float& operator[](unsigned int i) {return *(&r + i);}
|
||||||
inline float& operator[] (unsigned int sub)
|
|
||||||
|
inline bool IsBlack() const
|
||||||
{
|
{
|
||||||
switch (sub)
|
// the alpha component doesn't care here. black is black.
|
||||||
{
|
return !r && !g && !b;
|
||||||
case 0: return (float&)r;
|
|
||||||
case 1: return (float&)g;
|
|
||||||
case 2: return (float&)b;
|
|
||||||
default: return (float&)a;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__cplusplus
|
#endif // !__cplusplus
|
||||||
|
|
|
@ -433,8 +433,7 @@ int CreateAssetData()
|
||||||
g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
|
g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_pcAsset->pcScene->mMeshes[i]->mPrimitiveTypes == aiPrimitiveType_LINE ||
|
if (g_pcAsset->pcScene->mMeshes[i]->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
|
||||||
g_pcAsset->pcScene->mMeshes[i]->mPrimitiveTypes == aiPrimitiveType_POINT)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -675,6 +675,14 @@
|
||||||
RelativePath="..\..\test\unit\Main.cpp"
|
RelativePath="..\..\test\unit\Main.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\test\unit\RemoveComponent.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\test\unit\RemoveComponent.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\test\unit\utFindInvalidData.cpp"
|
RelativePath="..\..\test\unit\utFindInvalidData.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -726,6 +726,10 @@
|
||||||
RelativePath="..\..\include\BoostWorkaround\boost\format.hpp"
|
RelativePath="..\..\include\BoostWorkaround\boost\format.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\BoostWorkaround\boost\multi_array.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
|
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
|
||||||
>
|
>
|
||||||
|
@ -867,6 +871,10 @@
|
||||||
RelativePath="..\..\code\StandardShapes.h"
|
RelativePath="..\..\code\StandardShapes.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\StreamReader.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\code\StringComparison.h"
|
RelativePath="..\..\code\StringComparison.h"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue