- changing Assimp's coordinate system from RH z-up to RH y-up
 - fixing coordinate system for LWO, 3DS, ASE, MD5, MDL, B3D, IRR, IRRMESH 
 - converttolh moved to three separate steps -> flipuv, flipwinding, makelh

LWO 
 - fixing texture coordinate generation -> mapping axis is correct now 
 - fixing z-fighting bug

ASE 
 - fixing crash due to invalid normal setup 
 - fixing parenting bug 
 - code cleanup

IRR 
 - code cleanup
 - fixing placement of externally loaded meshes 

MDL 
 - fixing texture coordinate space

PLY 
 - cleanup 
 - two-sided maat property is now set 

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@366 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2009-03-15 00:40:30 +00:00
parent 68d7e43056
commit c2d8881549
48 changed files with 1518 additions and 1802 deletions

View File

@ -774,20 +774,13 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode,m);
}
// We used the first vertex color set to store some
// temporary values so we need to cleanup here
// We used the first vertex color set to store some emporary values so we need to cleanup here
for (unsigned int a = 0; a < pcOut->mNumMeshes;++a)
pcOut->mMeshes[a]->mColors[0] = NULL;
// if the root node has only one child ... set the child as root node
if (1 == pcOut->mRootNode->mNumChildren)
{
aiNode* pcOld = pcOut->mRootNode;
pcOut->mRootNode = pcOut->mRootNode->mChildren[0];
pcOut->mRootNode->mParent = NULL;
pcOld->mChildren[0] = NULL;
delete pcOld;
}
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pcOut->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f) * pcOut->mRootNode->mTransformation;
// If the root node is unnamed name it "<3DSRoot>"
if (::strstr( pcOut->mRootNode->mName.data, "UNNAMED" ) ||

File diff suppressed because it is too large Load Diff

View File

@ -1889,17 +1889,19 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
unsigned int index, faceIdx = 0xffffffff;
// FIXME: rewrite this and find out how to interpret the normals
// correctly. This is crap.
// Smooth the vertex and face normals together. The result
// will be edgy then, but otherwise everything would be soft ...
while (true)
{
if ('*' == *filePtr)
{
while (true) {
if ('*' == *filePtr) {
++filePtr;
if (faceIdx != 0xffffffff && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17))
{
if (faceIdx != 0xffffffff && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) {
aiVector3D vNormal;
ParseLV4MeshFloatTriple(&vNormal.x,index);
if (faceIdx >= sMesh.mFaces.size())
continue;
// Make sure we assign it to the correct face
const ASE::Face& face = sMesh.mFaces[faceIdx];
@ -1909,29 +1911,27 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
index = 1;
else if (index == face.mIndices[2])
index = 2;
else
{
else {
DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
continue;
}
// We'll renormalize later
sMesh.mNormals[faceIdx*3+index] += vNormal;
continue;
}
if (TokenMatch(filePtr,"MESH_FACENORMAL",15))
{
if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) {
aiVector3D vNormal;
ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
if (faceIdx >= sMesh.mFaces.size())
{
if (faceIdx >= sMesh.mFaces.size()) {
DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
continue;
}
// We'll renormalize later
sMesh.mNormals[faceIdx*3] += vNormal;
sMesh.mNormals[faceIdx*3+1] += vNormal;
sMesh.mNormals[faceIdx*3+2] += vNormal;
continue;
}
}

View File

@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// internal headers
#include "B3DImporter.h"
#include "TextureTransform.h"
#include "ConvertToLHProcess.h"
using namespace Assimp;
using namespace std;
@ -119,11 +120,6 @@ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
//create root node
aiNode *node=new aiNode( "root" );
node->mTransformation=aiMatrix4x4(
1,0,0,0,
0,0,1,0,
0,1,0,0,
0,0,0,1 );
node->mNumMeshes=_meshes.size();
node->mMeshes=new unsigned[_meshes.size()];
@ -131,6 +127,10 @@ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
node->mMeshes[i]=i;
}
pScene->mRootNode=node;
// convert to RH
MakeLeftHandedProcess monster_maker;
monster_maker.Execute(pScene);
}
// ------------------------------------------------------------------------------------------------
@ -348,8 +348,8 @@ void B3DImporter::ReadTRIS(){
unsigned *ip=face->mIndices=new unsigned[3];
int v[3];
v[0]=ReadInt();
v[2]=ReadInt();
v[1]=ReadInt();
v[2]=ReadInt();
for( unsigned j=0;j<3;++j ){
int k=v[j];
const Vertex &v=_vertices[k];

View File

@ -39,136 +39,220 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the post processing step to convert all imported data
* to a left-handed coordinate system.
/** @file MakeLeftHandedProcess.cpp
* @brief Implementation of the post processing step to convert all
* imported data to a left-handed coordinate system.
*
* Face order & UV flip are also implemented here, for the sake of a
* better location.
*/
#include "AssimpPCH.h"
#include "ConvertToLHProcess.h"
using namespace Assimp;
// The transformation matrix to convert from DirectX coordinates to OpenGL coordinates.
const aiMatrix3x3 Assimp::ConvertToLHProcess::sToOGLTransform(
1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f
);
// The transformation matrix to convert from OpenGL coordinates to DirectX coordinates.
const aiMatrix3x3 Assimp::ConvertToLHProcess::sToDXTransform(
1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f
);
#ifndef ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ConvertToLHProcess::ConvertToLHProcess()
{
bTransformVertices = false;
}
MakeLeftHandedProcess::MakeLeftHandedProcess()
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
ConvertToLHProcess::~ConvertToLHProcess()
{
// nothing to do here
}
MakeLeftHandedProcess::~MakeLeftHandedProcess()
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool ConvertToLHProcess::IsActive( unsigned int pFlags) const
bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const
{
if (pFlags & aiProcess_ConvertToLeftHanded)
{
bTransformVertices = (0 != (pFlags & aiProcess_PreTransformVertices) ? true : false);
return true;
}
return false;
return 0 != (pFlags & aiProcess_MakeLeftHanded);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void ConvertToLHProcess::Execute( aiScene* pScene)
void MakeLeftHandedProcess::Execute( aiScene* pScene)
{
// Check for an existent root node to proceed
if (NULL == pScene->mRootNode)
{
DefaultLogger::get()->error("ConvertToLHProcess fails, there is no root node");
return;
}
ai_assert(pScene->mRootNode != NULL);
DefaultLogger::get()->debug("MakeLeftHandedProcess begin");
DefaultLogger::get()->debug("ConvertToLHProcess begin");
// recursively convert all the nodes
ProcessNode( pScene->mRootNode, aiMatrix4x4());
// transform vertex by vertex or change the root transform?
// We can't do the coordinate system transformation earlier
// in the pipeline - most steps assume that we're in OGL
// space. So we need to transform all vertices a second time
// here.
if (bTransformVertices)
{
aiMatrix4x4 mTransform;
ConvertToDX(mTransform);
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{
aiMesh* pcMesh = pScene->mMeshes[i];
// transform all vertices
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
pcMesh->mVertices[n] = mTransform * pcMesh->mVertices[n];
// transform all normals
if (pcMesh->HasNormals())
{
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
pcMesh->mNormals[n] = mTransform * pcMesh->mNormals[n];
}
// transform all tangents and all bitangents
if (pcMesh->HasTangentsAndBitangents())
{
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
{
pcMesh->mTangents[n] = mTransform * pcMesh->mTangents[n];
pcMesh->mBitangents[n] = mTransform * pcMesh->mBitangents[n];
}
}
}
}
else
{
// transform the root node of the scene, the other nodes will follow then
ConvertToDX( pScene->mRootNode->mTransformation);
}
// transform all meshes accordingly
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
// process the meshes accordingly
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
ProcessMesh( pScene->mMeshes[a]);
// process all materials - we need to adjust UV transformations
for( unsigned int a = 0; a < pScene->mNumMaterials; a++)
// process the materials accordingly
for( unsigned int a = 0; a < pScene->mNumMaterials; ++a)
ProcessMaterial( pScene->mMaterials[a]);
// transform all animation channels affecting the root node as well
// transform all animation channels as well
for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
{
aiAnimation* anim = pScene->mAnimations[a];
for( unsigned int b = 0; b < anim->mNumChannels; b++)
{
aiNodeAnim* nodeAnim = anim->mChannels[b];
if( strcmp( nodeAnim->mNodeName.data, pScene->mRootNode->mName.data) == 0)
ProcessAnimation( nodeAnim);
}
}
DefaultLogger::get()->debug("ConvertToLHProcess finished");
// flipping a single vector component means inverting face order ...
FlipWindingOrderProcess flipper;
flipper.Execute(pScene);
DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
}
// ------------------------------------------------------------------------------------------------
// Recursively converts a node, all of its children and all of its meshes
void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation)
{
// mirror all base vectors at the local Z axis
pNode->mTransformation.c1 = -pNode->mTransformation.c1;
pNode->mTransformation.c2 = -pNode->mTransformation.c2;
pNode->mTransformation.c3 = -pNode->mTransformation.c3;
pNode->mTransformation.c4 = -pNode->mTransformation.c4;
// now invert the Z axis again to keep the matrix determinant positive.
// The local meshes will be inverted accordingly so that the result should look just fine again.
pNode->mTransformation.a3 = -pNode->mTransformation.a3;
pNode->mTransformation.b3 = -pNode->mTransformation.b3;
pNode->mTransformation.c3 = -pNode->mTransformation.c3;
pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
// continue for all children
for( size_t a = 0; a < pNode->mNumChildren; ++a)
ProcessNode( pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation);
}
// ------------------------------------------------------------------------------------------------
// Converts a single mesh to left handed coordinates.
void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
{
// mirror positions, normals and stuff along the Z axis
for( size_t a = 0; a < pMesh->mNumVertices; ++a)
{
pMesh->mVertices[a].z *= -1.0f;
if( pMesh->HasNormals())
pMesh->mNormals[a].z *= -1.0f;
if( pMesh->HasTangentsAndBitangents())
{
pMesh->mTangents[a].z *= -1.0f;
pMesh->mBitangents[a].z *= -1.0f;
}
}
// mirror offset matrices of all bones
for( size_t a = 0; a < pMesh->mNumBones; ++a)
{
aiBone* bone = pMesh->mBones[a];
bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1;
bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2;
bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4;
}
// mirror bitangents as well as they're derived from the texture coords
if( pMesh->HasTangentsAndBitangents())
{
for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
pMesh->mBitangents[a] *= -1.0f;
}
}
// ------------------------------------------------------------------------------------------------
// Converts a single material to left handed coordinates.
void ConvertToLHProcess::ProcessMaterial (aiMaterial* mat)
{
for (unsigned int a = 0; a < mat->mNumProperties;++a)
void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
{
MaterialHelper* mat = (MaterialHelper*)_mat;
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
aiMaterialProperty* prop = mat->mProperties[a];
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo"))
// Mapping axis for UV mappings?
if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) {
ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
aiVector3D* pff = (aiVector3D*)prop->mData;
pff->z *= -1.f;
}
}
}
// ------------------------------------------------------------------------------------------------
// Converts the given animation to LH coordinates.
void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
{
ai_assert( prop->mDataLength >= sizeof(aiUVTransform));
// position keys
for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
pAnim->mPositionKeys[a].mValue.z *= -1.0f;
// rotation keys
for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
{
/* That's the safe version, but the float errors add up. So we try the short version instead
aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2;
aiQuaternion rotquat( rotmat);
pAnim->mRotationKeys[a].mValue = rotquat;
*/
pAnim->mRotationKeys[a].mValue.x *= -1.0f;
pAnim->mRotationKeys[a].mValue.y *= -1.0f;
}
}
#endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS
// # FlipUVsProcess
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FlipUVsProcess::FlipUVsProcess()
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
FlipUVsProcess::~FlipUVsProcess()
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool FlipUVsProcess::IsActive( unsigned int pFlags) const
{
return 0 != (pFlags & aiProcess_FlipUVs);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FlipUVsProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("FlipUVsProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
ProcessMesh(pScene->mMeshes[i]);
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
ProcessMaterial(pScene->mMaterials[i]);
DefaultLogger::get()->debug("FlipUVsProcess finished");
}
// ------------------------------------------------------------------------------------------------
// Converts a single material
void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
{
MaterialHelper* mat = (MaterialHelper*)_mat;
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
aiMaterialProperty* prop = mat->mProperties[a];
// UV transformation key?
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */
aiUVTransform* uv = (aiUVTransform*)prop->mData;
// just flip it, that's everything
@ -179,8 +263,53 @@ void ConvertToLHProcess::ProcessMaterial (aiMaterial* mat)
}
// ------------------------------------------------------------------------------------------------
// Converts a single mesh to left handed coordinates.
void ConvertToLHProcess::ProcessMesh( aiMesh* pMesh)
// Converts a single mesh
void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
{
// mirror texture y coordinate
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
if( !pMesh->HasTextureCoords( a))
break;
for( unsigned int b = 0; b < pMesh->mNumVertices; b++)
pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y;
}
}
#endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
// # FlipWindingOrderProcess
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FlipWindingOrderProcess::FlipWindingOrderProcess()
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
FlipWindingOrderProcess::~FlipWindingOrderProcess()
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
{
return 0 != (pFlags & aiProcess_FlipWindingOrder);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FlipWindingOrderProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
ProcessMesh(pScene->mMeshes[i]);
DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
}
// ------------------------------------------------------------------------------------------------
// Converts a single mesh
void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
{
// invert the order of all faces in this mesh
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
@ -189,77 +318,6 @@ void ConvertToLHProcess::ProcessMesh( aiMesh* pMesh)
for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
}
// mirror texture y coordinate
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
{
if( pMesh->HasTextureCoords( a))
{
for( unsigned int b = 0; b < pMesh->mNumVertices; b++)
pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y;
}
}
// mirror bitangents as well as they're derived from the texture coords
if( pMesh->HasTangentsAndBitangents())
{
for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
pMesh->mBitangents[a] = -pMesh->mBitangents[a];
}
}
// ------------------------------------------------------------------------------------------------
// Converts the given animation to LH coordinates.
void ConvertToLHProcess::ProcessAnimation( aiNodeAnim* pAnim)
{
// position keys
for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
ConvertToDX( pAnim->mPositionKeys[a].mValue);
return;
// rotation keys
for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
{
aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
ConvertToDX( rotmat);
pAnim->mRotationKeys[a].mValue = aiQuaternion( rotmat);
}
}
// ------------------------------------------------------------------------------------------------
// Static helper function to convert a vector/matrix from DX to OGL coords
void ConvertToLHProcess::ConvertToOGL( aiVector3D& poVector)
{
poVector = sToOGLTransform * poVector;
}
// ------------------------------------------------------------------------------------------------
void ConvertToLHProcess::ConvertToOGL( aiMatrix3x3& poMatrix)
{
poMatrix = sToOGLTransform * poMatrix;
}
// ------------------------------------------------------------------------------------------------
void ConvertToLHProcess::ConvertToOGL( aiMatrix4x4& poMatrix)
{
poMatrix = aiMatrix4x4( sToOGLTransform) * poMatrix;
}
// ------------------------------------------------------------------------------------------------
// Static helper function to convert a vector/matrix from OGL back to DX coords
void ConvertToLHProcess::ConvertToDX( aiVector3D& poVector)
{
poVector = sToDXTransform * poVector;
}
// ------------------------------------------------------------------------------------------------
void ConvertToLHProcess::ConvertToDX( aiMatrix3x3& poMatrix)
{
poMatrix = sToDXTransform * poMatrix;
}
// ------------------------------------------------------------------------------------------------
void ConvertToLHProcess::ConvertToDX( aiMatrix4x4& poMatrix)
{
poMatrix = aiMatrix4x4(sToDXTransform) * poMatrix;
}
#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS

View File

@ -38,7 +38,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file Defines a post processing step to convert all data to a left-handed coordinate system.*/
/** @file MakeLeftHandedProcess.h
* @brief Defines a bunch of post-processing steps to handle
* coordinate system conversions.
*
* - LH to RH
* - UV origin upper-left to lower-left
* - face order cw to ccw
*/
#ifndef AI_CONVERTTOLHPROCESS_H_INC
#define AI_CONVERTTOLHPROCESS_H_INC
@ -48,72 +55,55 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiMesh;
struct aiNodeAnim;
namespace Assimp
{
namespace Assimp {
// ---------------------------------------------------------------------------
/** The ConvertToLHProcess converts all imported data to a left-handed coordinate
* system. This implies inverting the Z axis for all transformation matrices
* invert the orientation of all faces, and adapting skinning and animation
* data in a similar way.
// -----------------------------------------------------------------------------------
/** @brief The MakeLeftHandedProcess converts all imported data to a left-handed
* coordinate system.
*
* This implies a mirroring of the Z axis of the coordinate system. But to keep
* transformation matrices free from reflections we shift the reflection to other
* places. We mirror the meshes and adapt the rotations.
*
* @note RH-LH and LH-RH is the same, so this class can be used for both
*/
class ASSIMP_API ConvertToLHProcess : public BaseProcess
class ASSIMP_API MakeLeftHandedProcess : public BaseProcess
{
friend class Importer;
protected:
public:
/** Constructor to be privately used by Importer */
ConvertToLHProcess();
MakeLeftHandedProcess();
/** Destructor, private as well */
~ConvertToLHProcess();
~MakeLeftHandedProcess();
public:
// -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag field.
* @param pFlags The processing flags the importer was called with. A bitwise
* combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields, false if not.
*/
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute( aiScene* pScene);
// -------------------------------------------------------------------
/** Static helper function to convert a vector/matrix from DX coords to OGL coords.
* @param poMatrix The matrix to convert.
*/
static void ConvertToOGL( aiVector3D& poVector);
static void ConvertToOGL( aiMatrix3x3& poMatrix);
static void ConvertToOGL( aiMatrix4x4& poMatrix);
// -------------------------------------------------------------------
/** Static helper function to convert a vector/matrix from OGL coords back to DX coords.
* @param poMatrix The matrix to convert.
*/
static void ConvertToDX( aiVector3D& poVector);
static void ConvertToDX( aiMatrix3x3& poMatrix);
static void ConvertToDX( aiMatrix4x4& poMatrix);
protected:
// -------------------------------------------------------------------
/** Recursively converts a node and all of its children
*/
void ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation);
// -------------------------------------------------------------------
/** Converts a single mesh to left handed coordinates.
* This simply means the order of all faces is inverted.
* This means that positions, normals and tangents are mirrored at
* the local Z axis and the order of all faces are inverted.
* @param pMesh The mesh to convert.
*/
void ProcessMesh( aiMesh* pMesh);
// -------------------------------------------------------------------
/** Converts a single material to left handed coordinates.
* This simply means all UV offsets are inverted.
* @param mat The material to convert.
/** Converts a single material to left-handed coordinates
* @param pMat Material to convert
*/
void ProcessMaterial (aiMaterial* mat);
void ProcessMaterial( aiMaterial* pMat);
// -------------------------------------------------------------------
/** Converts the given animation to LH coordinates.
@ -122,16 +112,56 @@ protected:
* @param pAnim The bone animation to transform
*/
void ProcessAnimation( aiNodeAnim* pAnim);
};
//! true if the transformation matrix for the OGL-to-DX is
//! directly used to transform all vertices.
mutable bool bTransformVertices;
// ---------------------------------------------------------------------------
/** Postprocessing step to flip the face order of the imported data
*/
class ASSIMP_API FlipWindingOrderProcess : public BaseProcess
{
friend class Importer;
public:
/** The transformation matrix to convert from DirectX coordinates to OpenGL coordinates. */
static const aiMatrix3x3 sToOGLTransform;
/** The transformation matrix to convert from OpenGL coordinates to DirectX coordinates. */
static const aiMatrix3x3 sToDXTransform;
/** Constructor to be privately used by Importer */
FlipWindingOrderProcess();
/** Destructor, private as well */
~FlipWindingOrderProcess();
// -------------------------------------------------------------------
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
void Execute( aiScene* pScene);
protected:
void ProcessMesh( aiMesh* pMesh);
};
// ---------------------------------------------------------------------------
/** Postprocessing step to flip the UV coordinate system of the import data
*/
class ASSIMP_API FlipUVsProcess : public BaseProcess
{
friend class Importer;
public:
/** Constructor to be privately used by Importer */
FlipUVsProcess();
/** Destructor, private as well */
~FlipUVsProcess();
// -------------------------------------------------------------------
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
void Execute( aiScene* pScene);
protected:
void ProcessMesh( aiMesh* pMesh);
void ProcessMaterial( aiMaterial* mat);
};
} // end of namespace Assimp

View File

@ -84,16 +84,12 @@ aiColor4D g_clrInvalid = aiColor4D(get_qnan(),0.f,0.f,1.f);
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
DXFImporter::DXFImporter()
{
// nothing to do here
}
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
DXFImporter::~DXFImporter()
{
// nothing to do here
}
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
@ -103,6 +99,7 @@ bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
}
// ------------------------------------------------------------------------------------------------
// Get a list of all supported file extensions
void DXFImporter::GetExtensionList(std::string& append)
{
append.append("*.dxf");
@ -115,8 +112,7 @@ bool DXFImporter::GetNextLine()
if(!SkipLine(&buffer))
return false;
if(!SkipSpaces(&buffer))return GetNextLine();
else if (*buffer == '{')
{
else if (*buffer == '{') {
// some strange meta data ...
while (true)
{
@ -135,8 +131,7 @@ bool DXFImporter::GetNextLine()
// Get the next token in the file
bool DXFImporter::GetNextToken()
{
if (bRepeat)
{
if (bRepeat) {
bRepeat = false;
return true;
}
@ -181,26 +176,23 @@ void DXFImporter::InternReadFile( const std::string& pFile,
throw new ImportErrorException("DXF: Binary files are not supported at the moment");
// now get all lines of the file
while (GetNextToken())
{
if (2 == groupCode)
{
while (GetNextToken()) {
if (2 == groupCode) {
// ENTITIES and BLOCKS sections - skip the whole rest, no need to waste our time with them
if (!::strcmp(cursor,"ENTITIES") || !::strcmp(cursor,"BLOCKS"))
if (!ParseEntities())break; else bRepeat = true;
// other sections - skip them to make sure there will be no name conflicts
else
{
while (GetNextToken())
{
else {
while (GetNextToken()) {
if (!groupCode && !::strcmp(cursor,"ENDSEC"))break;
}
}
}
// print comment strings
else if (999 == groupCode)
{
else if (999 == groupCode) {
DefaultLogger::get()->info(std::string( cursor ));
}
else if (!groupCode && !::strcmp(cursor,"EOF"))
@ -208,9 +200,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
}
// find out how many valud layers we have
for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end();
it != end;++it)
{
for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end(); it != end;++it) {
if (!(*it).vPositions.empty())++pScene->mNumMeshes;
}
@ -219,11 +209,10 @@ void DXFImporter::InternReadFile( const std::string& pFile,
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
m = 0;
for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end();
it != end;++it)
{
if ((*it).vPositions.empty())continue;
for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end();it != end;++it) {
if ((*it).vPositions.empty()) {
continue;
}
// generate the output mesh
aiMesh* pMesh = pScene->mMeshes[m++] = new aiMesh();
const std::vector<aiVector3D>& vPositions = (*it).vPositions;
@ -232,11 +221,9 @@ void DXFImporter::InternReadFile( const std::string& pFile,
// check whether we need vertex colors here
aiColor4D* clrOut = NULL;
const aiColor4D* clr = NULL;
for (std::vector<aiColor4D>::const_iterator it2 = (*it).vColors.begin(), end2 = (*it).vColors.end();
it2 != end2; ++it2)
{
if ((*it2).r == (*it2).r) // check against qnan
{
for (std::vector<aiColor4D>::const_iterator it2 = (*it).vColors.begin(), end2 = (*it).vColors.end();it2 != end2; ++it2) {
if ((*it2).r == (*it2).r) /* qnan? */ {
clrOut = pMesh->mColors[0] = new aiColor4D[vPositions.size()];
for (unsigned int i = 0; i < vPositions.size();++i)
clrOut[i] = aiColor4D(0.6f,0.6f,0.6f,1.0f);
@ -252,30 +239,25 @@ void DXFImporter::InternReadFile( const std::string& pFile,
aiVector3D* vpOut = pMesh->mVertices = new aiVector3D[vPositions.size()];
const aiVector3D* vp = &vPositions[0];
for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
{
for (unsigned int i = 0; i < pMesh->mNumFaces;++i) {
aiFace& face = pMesh->mFaces[i];
// check whether we need four, three or two indices here
if (vp[1] == vp[2])
{
if (vp[1] == vp[2]) {
face.mNumIndices = 2;
}
else if (vp[3] == vp[2])
{
else if (vp[3] == vp[2]) {
face.mNumIndices = 3;
}
else face.mNumIndices = 4;
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) {
*vpOut++ = vp[a];
if (clr)
{
if (is_not_qnan( clr[a].r ))
if (clr) {
if (is_not_qnan( clr[a].r )) {
*clrOut = clr[a];
}
++clrOut;
}
face.mIndices[a] = pMesh->mNumVertices++;
@ -288,16 +270,14 @@ void DXFImporter::InternReadFile( const std::string& pFile,
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<DXF_ROOT>");
if (1 == pScene->mNumMeshes)
{
if (1 == pScene->mNumMeshes) {
pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
pScene->mRootNode->mMeshes[0] = 0;
}
else
{
pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
for (m = 0; m < pScene->mRootNode->mNumChildren;++m)
{
for (m = 0; m < pScene->mRootNode->mNumChildren;++m) {
aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
p->mName.length = ::strlen( mLayers[m].name );
::strcpy(p->mName.data, mLayers[m].name);
@ -333,10 +313,8 @@ void DXFImporter::InternReadFile( const std::string& pFile,
// ------------------------------------------------------------------------------------------------
bool DXFImporter::ParseEntities()
{
while (GetNextToken())
{
if (!groupCode)
{
while (GetNextToken()) {
if (!groupCode) {
if (!::strcmp(cursor,"3DFACE") || !::strcmp(cursor,"LINE") || !::strcmp(cursor,"3DLINE"))
if (!Parse3DFace()) return false; else bRepeat = true;
@ -353,17 +331,13 @@ bool DXFImporter::ParseEntities()
// ------------------------------------------------------------------------------------------------
void DXFImporter::SetLayer(LayerInfo*& out)
{
for (std::vector<LayerInfo>::iterator it = mLayers.begin(),end = mLayers.end();
it != end;++it)
{
if (!::strcmp( (*it).name, cursor ))
{
for (std::vector<LayerInfo>::iterator it = mLayers.begin(),end = mLayers.end();it != end;++it) {
if (!::strcmp( (*it).name, cursor )) {
out = &(*it);
break;
}
}
if (!out)
{
if (!out) {
// we don't have this layer yet
mLayers.push_back(LayerInfo());
out = &mLayers.back();
@ -374,8 +348,7 @@ void DXFImporter::SetLayer(LayerInfo*& out)
// ------------------------------------------------------------------------------------------------
void DXFImporter::SetDefaultLayer(LayerInfo*& out)
{
if (!mDefaultLayer)
{
if (!mDefaultLayer) {
mLayers.push_back(LayerInfo());
mDefaultLayer = &mLayers.back();
}
@ -393,27 +366,22 @@ bool DXFImporter::ParsePolyLine()
std::vector<unsigned int> indices;
unsigned int flags = 0;
while (GetNextToken())
{
while (GetNextToken()) {
switch (groupCode)
{
case 0:
{
if (!::strcmp(cursor,"VERTEX"))
{
if (!::strcmp(cursor,"VERTEX")) {
aiVector3D v;aiColor4D clr(g_clrInvalid);
unsigned int idx[4] = {0xffffffff,0xffffffff,0xffffffff,0xffffffff};
ParsePolyLineVertex(v, clr, idx);
if (0xffffffff == idx[0])
{
if (0xffffffff == idx[0]) {
positions.push_back(v);
colors.push_back(clr);
}
else
{
else {
// check whether we have a fourth coordinate
if (0xffffffff == idx[3])
{
if (0xffffffff == idx[3]) {
idx[3] = idx[2];
}
@ -423,8 +391,7 @@ bool DXFImporter::ParsePolyLine()
}
bRepeat = true;
}
else if (!::strcmp(cursor,"ENDSEQ"))
{
else if (!::strcmp(cursor,"ENDSEQ")) {
ret = true;
}
break;
@ -433,8 +400,7 @@ bool DXFImporter::ParsePolyLine()
// flags --- important that we know whether it is a polyface mesh
case 70:
{
if (!flags)
{
if (!flags) {
flags = strtol10(cursor);
}
break;
@ -462,32 +428,29 @@ bool DXFImporter::ParsePolyLine()
}
}
}
if (!(flags & 64))
{
if (!(flags & 64)) {
DefaultLogger::get()->warn("DXF: Only polyface meshes are currently supported");
return ret;
}
if (positions.size() < 3 || indices.size() < 3)
{
if (positions.size() < 3 || indices.size() < 3) {
DefaultLogger::get()->warn("DXF: Unable to parse POLYLINE element - not enough vertices");
return ret;
}
// use a default layer if necessary
if (!out)SetDefaultLayer(out);
if (!out) {
SetDefaultLayer(out);
}
flags = (unsigned int)(out->vPositions.size()+indices.size());
out->vPositions.reserve(flags);
out->vColors.reserve(flags);
// generate unique vertices
for (std::vector<unsigned int>::const_iterator it = indices.begin(), end = indices.end();
it != end; ++it)
{
for (std::vector<unsigned int>::const_iterator it = indices.begin(), end = indices.end();it != end; ++it) {
unsigned int idx = *it;
if (idx > positions.size() || !idx)
{
if (idx > positions.size() || !idx) {
DefaultLogger::get()->error("DXF: Polyface mesh index os out of range");
idx = (unsigned int) positions.size();
}
@ -502,11 +465,11 @@ bool DXFImporter::ParsePolyLine()
bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,aiColor4D& clr, unsigned int* outIdx)
{
bool ret = false;
while (GetNextToken())
{
while (GetNextToken()) {
switch (groupCode)
{
case 0: ret = true;break;
case 0: ret = true;
break;
// todo - handle the correct layer for the vertex
// At the moment it is assumed that all vertices of
@ -530,7 +493,9 @@ bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,aiColor4D& clr, unsigned i
// color
case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break;
};
if (ret)break;
if (ret) {
break;
}
}
return ret;
}
@ -547,15 +512,12 @@ bool DXFImporter::Parse3DFace()
// this is also used for for parsing line entities
bool bThird = false;
while (GetNextToken())
{
switch (groupCode)
{
while (GetNextToken()) {
switch (groupCode) {
case 0: ret = true;break;
// 8 specifies the layer
case 8:
{
case 8: {
SetLayer(out);
break;
}
@ -611,8 +573,9 @@ bool DXFImporter::Parse3DFace()
if (!bThird)vip[2] = vip[1];
// use a default layer if necessary
if (!out)SetDefaultLayer(out);
if (!out) {
SetDefaultLayer(out);
}
// add the faces to the face list for this layer
out->vPositions.push_back(vip[0]);
out->vPositions.push_back(vip[1]);

View File

@ -70,16 +70,12 @@ using namespace boost::math;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
IRRImporter::IRRImporter()
{
// nothing to do here
}
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
IRRImporter::~IRRImporter()
{
// nothing to do here
}
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
@ -174,17 +170,14 @@ aiMesh* IRRImporter::BuildSingleQuadMesh(const SkyboxVertex& v1,
*vec++ = v2.uv;
*vec++ = v3.uv;
*vec = v4.uv;
return out;
}
// ------------------------------------------------------------------------------------------------
void IRRImporter::BuildSkybox(std::vector<aiMesh*>& meshes, std::vector<aiMaterial*> materials)
{
// Update the material of the skybox - replace the name
// and disable shading for skyboxes.
for (unsigned int i = 0; i < 6;++i)
{
// Update the material of the skybox - replace the name and disable shading for skyboxes.
for (unsigned int i = 0; i < 6;++i) {
MaterialHelper* out = ( MaterialHelper* ) (*(materials.end()-(6-i)));
aiString s;
@ -256,8 +249,7 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
unsigned int& defMatIdx,
aiMesh* mesh)
{
if (inmaterials.empty())
{
if (inmaterials.empty()) {
// Do we have a default material? If not we need to create one
if (0xffffffff == defMatIdx)
{
@ -274,8 +266,7 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
mesh->mMaterialIndex = defMatIdx;
return;
}
else if (inmaterials.size() > 1)
{
else if (inmaterials.size() > 1) {
DefaultLogger::get()->info("IRR: Skipping additional materials");
}
@ -307,24 +298,20 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
{
ai_assert(NULL != root && NULL != real);
if (root->animators.empty())return;
// const aiMatrix4x4& transform = real->mTransformation;
if (root->animators.empty()) {
return;
}
unsigned int total = 0;
for (std::list<Animator>::iterator it = root->animators.begin();
it != root->animators.end(); ++it)
{
if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER)
{
for (std::list<Animator>::iterator it = root->animators.begin();it != root->animators.end(); ++it) {
if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) {
DefaultLogger::get()->warn("IRR: Skipping unknown or unsupported animator");
continue;
}
++total;
}
if (!total)return;
else if (1 == total)
{
DefaultLogger::get()->warn("IRR: Generating dummy nodes to simulate multiple animators");
else if (1 == total) {
DefaultLogger::get()->warn("IRR: Adding dummy nodes to simulate multiple animators");
}
// NOTE: 1 tick == i millisecond
@ -338,8 +325,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
Animator& in = *it ;
aiNodeAnim* anim = new aiNodeAnim();
if (cur != total-1)
{
if (cur != total-1) {
// Build a new name - a prefix instead of a suffix because it is
// easier to check against
anim->mNodeName.length = ::sprintf(anim->mNodeName.data,
@ -367,8 +353,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
else anim->mNodeName.Set(root->name);
++cur;
switch (in.type)
{
switch (in.type) {
case Animator::ROTATION:
{
// -----------------------------------------------------
@ -463,8 +448,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
// from Irrlicht, what else should we do than copying it?
aiVector3D vecU,vecV;
if (in.direction.y)
{
if (in.direction.y) {
vecV = aiVector3D(50,0,0) ^ in.direction;
}
else vecV = aiVector3D(0,50,00) ^ in.direction;
@ -472,8 +456,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
vecU = (vecV ^ in.direction).Normalize();
// build the output keys
for (unsigned int i = 0; i < anim->mNumPositionKeys;++i)
{
for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) {
aiVectorKey& key = anim->mPositionKeys[i];
key.mTime = i * tdelta;
@ -502,8 +485,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
const double timeFactor = lengthOfWay / in.timeForWay;
// build the output keys
for (unsigned int i = 0; i < anim->mNumPositionKeys;++i)
{
for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) {
aiVectorKey& key = anim->mPositionKeys[i];
key.mTime = i * tdelta;
key.mValue = in.circleCenter + diff * float(timeFactor * key.mTime);
@ -516,16 +498,14 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
// repeat outside the defined time range
anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
const int size = (int)in.splineKeys.size();
if (!size)
{
if (!size) {
// We have no point in the spline. That's bad. Really bad.
DefaultLogger::get()->warn("IRR: Spline animators with no points defined");
delete anim;anim = NULL;
break;
}
else if (size == 1)
{
else if (size == 1) {
// We have just one point in the spline so we don't need the full calculation
anim->mNumPositionKeys = 1;
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
@ -576,8 +556,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
}
break;
};
if (anim)
{
if (anim) {
anims.push_back(anim);
++total;
}
@ -598,8 +577,7 @@ void SetupMapping (MaterialHelper* mat, aiTextureMapping mode, const aiVector3D&
for (unsigned int i = 0; i < mat->mNumProperties;++i)
{
aiMaterialProperty* prop = mat->mProperties[i];
if (!::strcmp( prop->mKey.data, "$tex.file"))
{
if (!::strcmp( prop->mKey.data, "$tex.file")) {
// Setup the mapping key
aiMaterialProperty* m = new aiMaterialProperty();
m->mKey.Set("$tex.mapping");
@ -615,9 +593,7 @@ void SetupMapping (MaterialHelper* mat, aiTextureMapping mode, const aiVector3D&
p.push_back(m);
// Setup the mapping axis
if (mode == aiTextureMapping_CYLINDER || mode == aiTextureMapping_PLANE ||
mode == aiTextureMapping_SPHERE)
{
if (mode == aiTextureMapping_CYLINDER || mode == aiTextureMapping_PLANE || mode == aiTextureMapping_SPHERE) {
m = new aiMaterialProperty();
m->mKey.Set("$tex.mapaxis");
m->mIndex = prop->mIndex;
@ -674,63 +650,24 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// the list of all scenes to be attached to the
// graph we're currently building
aiScene* scene = batch.GetImport(root->id);
if (!scene)
{
DefaultLogger::get()->error("IRR: Unable to load external file: "
+ root->meshPath);
if (!scene) {
DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath);
break;
}
attach.push_back(AttachmentInfo(scene,rootOut));
#if 0 /* currently unused */
meshTrafoAssign = 1;
// If the root node of the scene is animated - and *this* node
// is animated, too, we need to insert a dummy node into the
// hierarchy in order to avoid interferences with animations
for (unsigned int i = 0; i < scene->mNumAnimations;++i)
{
aiAnimation* anim = scene->mAnimations[i];
for (unsigned int a = 0; a < anim->mNumChannels;++a) {
if (scene->mRootNode->mName == anim->mChannels[a]->mNodeName) {
if (root->animators.empty()) {
meshTrafoAssign = 2;
}
else {
meshTrafoAssign = 3;
aiNode* dummy = new aiNode();
dummy->mName.Set("$CSpaceSeam$");
dummy->mNumChildren = 1;
dummy->mChildren = new aiNode*[1];
dummy->mChildren[0] = scene->mRootNode;
scene->mRootNode->mParent = dummy;
scene->mRootNode = dummy;
scene->mRootNode->mTransformation = AI_TO_IRR_MATRIX;
}
break;
}
}
}
#endif
// if (1 == meshTrafoAssign)
// scene->mRootNode->mTransformation = AI_TO_IRR_MATRIX * scene->mRootNode->mTransformation;
// Now combine the material we've loaded for this mesh
// with the real materials we got from the file. As we
// don't execute any pp-steps on the file, the numbers
// should be equal. If they are not, we can impossibly
// do this ...
if (root->materials.size() != (unsigned int)scene->mNumMaterials)
{
if (root->materials.size() != (unsigned int)scene->mNumMaterials) {
DefaultLogger::get()->warn("IRR: Failed to match imported materials "
"with the materials found in the IRR scene file");
break;
}
for (unsigned int i = 0; i < scene->mNumMaterials;++i)
{
for (unsigned int i = 0; i < scene->mNumMaterials;++i) {
// Delete the old material, we don't need it anymore
delete scene->mMaterials[i];
@ -741,8 +678,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// NOTE: Each mesh should have exactly one material assigned,
// but we do it in a separate loop if this behaviour changes
// in future.
for (unsigned int i = 0; i < scene->mNumMeshes;++i)
{
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
// Process material flags
aiMesh* mesh = scene->mMeshes[i];
@ -751,25 +687,21 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// and check whether they have a common alpha value. This is quite
// often the case so we can simply extract it to a shared oacity
// value.
std::pair<aiMaterial*, unsigned int>& src = root->materials[
mesh->mMaterialIndex];
std::pair<aiMaterial*, unsigned int>& src = root->materials[mesh->mMaterialIndex];
MaterialHelper* mat = (MaterialHelper*)src.first;
if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha)
{
bool bdo = true;
for (unsigned int a = 1; a < mesh->mNumVertices;++a)
{
if (mesh->mColors[0][a].a != mesh->mColors[0][a-1].a)
{
for (unsigned int a = 1; a < mesh->mNumVertices;++a) {
if (mesh->mColors[0][a].a != mesh->mColors[0][a-1].a) {
bdo = false;
break;
}
}
if (bdo)
{
DefaultLogger::get()->info("IRR: Replacing mesh vertex "
"alpha with common opacity");
if (bdo) {
DefaultLogger::get()->info("IRR: Replacing mesh vertex alpha with common opacity");
for (unsigned int a = 0; a < mesh->mNumVertices;++a)
mesh->mColors[0][a].a = 1.f;
@ -782,8 +714,8 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// (either lightmap, normalmap, 2layered material) we need to
// setup the correct UV index for it. The texture can either
// be diffuse (lightmap & 2layer) or a normal map (normal & parallax)
if (mesh->HasTextureCoords(1))
{
if (mesh->HasTextureCoords(1)) {
int idx = 1;
if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap)) {
mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
@ -852,11 +784,8 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
case Node::SKYBOX:
{
// A skybox is defined by six materials
if (root->materials.size() < 6)
{
DefaultLogger::get()->error("IRR: There should be six materials "
"for a skybox");
if (root->materials.size() < 6) {
DefaultLogger::get()->error("IRR: There should be six materials for a skybox");
break;
}
@ -888,8 +817,8 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// Check whether we added a mesh (or more than one ...). In this case
// we'll also need to attach it to the node
if (oldMeshSize != (unsigned int) meshes.size())
{
if (oldMeshSize != (unsigned int) meshes.size()) {
rootOut->mNumMeshes = (unsigned int)meshes.size() - oldMeshSize;
rootOut->mMeshes = new unsigned int[rootOut->mNumMeshes];
@ -904,7 +833,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// Now compute the final local transformation matrix of the
// node from the given translation, rotation and scaling values.
// (the rotation is given in Euler angles, XYZ order)
std::swap((float&)root->rotation.z,(float&)root->rotation.y);
//std::swap((float&)root->rotation.z,(float&)root->rotation.y);
rootOut->mTransformation.FromEulerAnglesXYZ(AI_DEG_TO_RAD(root->rotation) );
// apply scaling
@ -912,20 +841,17 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
mat.a1 *= root->scaling.x;
mat.b1 *= root->scaling.x;
mat.c1 *= root->scaling.x;
mat.a2 *= root->scaling.z;
mat.b2 *= root->scaling.z;
mat.c2 *= root->scaling.z;
mat.a3 *= root->scaling.y;
mat.b3 *= root->scaling.y;
mat.c3 *= root->scaling.y;
mat.a2 *= root->scaling.y;
mat.b2 *= root->scaling.y;
mat.c2 *= root->scaling.y;
mat.a3 *= root->scaling.z;
mat.b3 *= root->scaling.z;
mat.c3 *= root->scaling.z;
// apply translation
mat.a4 += root->position.x;
mat.b4 += root->position.z;
mat.c4 += root->position.y;
//if (meshTrafoAssign == 2)
// mat *= AI_TO_IRR_MATRIX;
mat.b4 += root->position.y;
mat.c4 += root->position.z;
// now compute animations for the node
ComputeAnimations(root,rootOut, anims);
@ -933,11 +859,11 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// Add all children recursively. First allocate enough storage
// for them, then call us again
rootOut->mNumChildren = (unsigned int)root->children.size();
if (rootOut->mNumChildren)
{
if (rootOut->mNumChildren) {
rootOut->mChildren = new aiNode*[rootOut->mNumChildren];
for (unsigned int i = 0; i < rootOut->mNumChildren;++i)
{
for (unsigned int i = 0; i < rootOut->mNumChildren;++i) {
aiNode* node = rootOut->mChildren[i] = new aiNode();
node->mParent = rootOut;
GenerateGraph(root->children[i],node,scene,batch,meshes,
@ -989,14 +915,11 @@ void IRRImporter::InternReadFile( const std::string& pFile,
unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0;
// Parse the XML file
while (reader->read())
{
switch (reader->getNodeType())
{
while (reader->read()) {
switch (reader->getNodeType()) {
case EXN_ELEMENT:
if (!ASSIMP_stricmp(reader->getNodeName(),"node"))
{
if (!ASSIMP_stricmp(reader->getNodeName(),"node")) {
// ***********************************************************************
/* What we're going to do with the node depends
* on its type:
@ -1019,24 +942,20 @@ void IRRImporter::InternReadFile( const std::string& pFile,
// ***********************************************************************
const char* sz = reader->getAttributeValueSafe("type");
Node* nd;
if (!ASSIMP_stricmp(sz,"mesh") || !ASSIMP_stricmp(sz,"octTree"))
{
if (!ASSIMP_stricmp(sz,"mesh") || !ASSIMP_stricmp(sz,"octTree")) {
// OctTree's and meshes are treated equally
nd = new Node(Node::MESH);
}
else if (!ASSIMP_stricmp(sz,"cube"))
{
else if (!ASSIMP_stricmp(sz,"cube")) {
nd = new Node(Node::CUBE);
++guessedMeshCnt;
// meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
}
else if (!ASSIMP_stricmp(sz,"skybox"))
{
else if (!ASSIMP_stricmp(sz,"skybox")) {
nd = new Node(Node::SKYBOX);
guessedMeshCnt += 6;
}
else if (!ASSIMP_stricmp(sz,"camera"))
{
else if (!ASSIMP_stricmp(sz,"camera")) {
nd = new Node(Node::CAMERA);
// Setup a temporary name for the camera
@ -1044,8 +963,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
cam->mName.Set( nd->name );
cameras.push_back(cam);
}
else if (!ASSIMP_stricmp(sz,"light"))
{
else if (!ASSIMP_stricmp(sz,"light")) {
nd = new Node(Node::LIGHT);
// Setup a temporary name for the light
@ -1053,31 +971,25 @@ void IRRImporter::InternReadFile( const std::string& pFile,
cam->mName.Set( nd->name );
lights.push_back(cam);
}
else if (!ASSIMP_stricmp(sz,"sphere"))
{
else if (!ASSIMP_stricmp(sz,"sphere")) {
nd = new Node(Node::SPHERE);
++guessedMeshCnt;
}
else if (!ASSIMP_stricmp(sz,"animatedMesh"))
{
else if (!ASSIMP_stricmp(sz,"animatedMesh")) {
nd = new Node(Node::ANIMMESH);
}
else if (!ASSIMP_stricmp(sz,"empty"))
{
else if (!ASSIMP_stricmp(sz,"empty")) {
nd = new Node(Node::DUMMY);
}
else if (!ASSIMP_stricmp(sz,"terrain"))
{
else if (!ASSIMP_stricmp(sz,"terrain")) {
nd = new Node(Node::TERRAIN);
}
else if (!ASSIMP_stricmp(sz,"billBoard"))
{
else if (!ASSIMP_stricmp(sz,"billBoard")) {
// We don't support billboards, so ignore them
DefaultLogger::get()->error("IRR: Billboards are not supported by Assimp");
nd = new Node(Node::DUMMY);
}
else
{
else {
DefaultLogger::get()->warn("IRR: Found unknown node: " + std::string(sz));
/* We skip the contents of nodes we don't know.
@ -1093,21 +1005,17 @@ void IRRImporter::InternReadFile( const std::string& pFile,
nd->parent = curParent;
curParent->children.push_back(nd);
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"materials"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) {
inMaterials = true;
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"animators"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) {
inAnimator = true;
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes")) {
/* We should have a valid node here
* FIX: no ... the scene root node is also contained in an attributes block
*/
if (!curNode)
{
if (!curNode) {
#if 0
DefaultLogger::get()->error("IRR: Encountered <attributes> element, but "
"there is no node active");
@ -1118,8 +1026,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
Animator* curAnim = NULL;
// Materials can occur for nearly any type of node
if (inMaterials && curNode->type != Node::DUMMY)
{
if (inMaterials && curNode->type != Node::DUMMY) {
/* This is a material description - parse it!
*/
curNode->materials.push_back(std::pair< aiMaterial*, unsigned int > () );
@ -1130,8 +1037,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
++guessedMatCnt;
continue;
}
else if (inAnimator)
{
else if (inAnimator) {
/* This is an animation path - add a new animator
* to the list.
*/
@ -1144,28 +1050,21 @@ void IRRImporter::InternReadFile( const std::string& pFile,
/* Parse all elements in the attributes block
* and process them.
*/
while (reader->read())
{
if (reader->getNodeType() == EXN_ELEMENT)
{
if (!ASSIMP_stricmp(reader->getNodeName(),"vector3d"))
{
while (reader->read()) {
if (reader->getNodeType() == EXN_ELEMENT) {
if (!ASSIMP_stricmp(reader->getNodeName(),"vector3d")) {
VectorProperty prop;
ReadVectorProperty(prop);
if (inAnimator)
{
if (curAnim->type == Animator::ROTATION && prop.name == "Rotation")
{
if (inAnimator) {
if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") {
// We store the rotation euler angles in 'direction'
curAnim->direction = prop.value;
}
else if (curAnim->type == Animator::FOLLOW_SPLINE)
{
else if (curAnim->type == Animator::FOLLOW_SPLINE) {
// Check whether the vector follows the PointN naming scheme,
// here N is the ONE-based index of the point
if (prop.name.length() >= 6 && prop.name.substr(0,5) == "Point")
{
if (prop.name.length() >= 6 && prop.name.substr(0,5) == "Point") {
// Add a new key to the list
curAnim->splineKeys.push_back(aiVectorKey());
aiVectorKey& key = curAnim->splineKeys.back();
@ -1175,203 +1074,158 @@ void IRRImporter::InternReadFile( const std::string& pFile,
key.mTime = strtol10(&prop.name[5]);
}
}
else if (curAnim->type == Animator::FLY_CIRCLE)
{
if (prop.name == "Center")
{
else if (curAnim->type == Animator::FLY_CIRCLE) {
if (prop.name == "Center") {
curAnim->circleCenter = prop.value;
}
else if (prop.name == "Direction")
{
else if (prop.name == "Direction") {
curAnim->direction = prop.value;
// From Irrlicht source - a workaround for backward
// compatibility with Irrlicht 1.1
if (curAnim->direction == aiVector3D())
{
// From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1
if (curAnim->direction == aiVector3D()) {
curAnim->direction = aiVector3D(0.f,1.f,0.f);
}
else curAnim->direction.Normalize();
}
}
else if (curAnim->type == Animator::FLY_STRAIGHT)
{
if (prop.name == "Start")
{
else if (curAnim->type == Animator::FLY_STRAIGHT) {
if (prop.name == "Start") {
// We reuse the field here
curAnim->circleCenter = prop.value;
}
else if (prop.name == "End")
{
else if (prop.name == "End") {
// We reuse the field here
curAnim->direction = prop.value;
}
}
}
else
{
if (prop.name == "Position")
{
else {
if (prop.name == "Position") {
curNode->position = prop.value;
}
else if (prop.name == "Rotation")
{
else if (prop.name == "Rotation") {
curNode->rotation = prop.value;
}
else if (prop.name == "Scale")
{
else if (prop.name == "Scale") {
curNode->scaling = prop.value;
}
else if (Node::CAMERA == curNode->type)
{
aiCamera* cam = cameras.back();
if (prop.name == "Target")
{
if (prop.name == "Target") {
cam->mLookAt = prop.value;
}
else if (prop.name == "UpVector")
{
else if (prop.name == "UpVector") {
cam->mUp = prop.value;
}
}
}
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"bool"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"bool")) {
BoolProperty prop;
ReadBoolProperty(prop);
if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop")
{
if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") {
curAnim->loop = prop.value;
}
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"float"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"float")) {
FloatProperty prop;
ReadFloatProperty(prop);
if (inAnimator)
{
if (inAnimator) {
// The speed property exists for several animators
if (prop.name == "Speed")
{
if (prop.name == "Speed") {
curAnim->speed = prop.value;
}
else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius")
{
else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius") {
curAnim->circleRadius = prop.value;
}
else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness")
{
else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness") {
curAnim->tightness = prop.value;
}
}
else
{
if (prop.name == "FramesPerSecond" &&
Node::ANIMMESH == curNode->type)
{
else {
if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) {
curNode->framesPerSecond = prop.value;
}
else if (Node::CAMERA == curNode->type)
{
else if (Node::CAMERA == curNode->type) {
/* This is the vertical, not the horizontal FOV.
* We need to compute the right FOV from the
* screen aspect which we don't know yet.
*/
if (prop.name == "Fovy")
{
if (prop.name == "Fovy") {
cameras.back()->mHorizontalFOV = prop.value;
}
else if (prop.name == "Aspect")
{
else if (prop.name == "Aspect") {
cameras.back()->mAspect = prop.value;
}
else if (prop.name == "ZNear")
{
else if (prop.name == "ZNear") {
cameras.back()->mClipPlaneNear = prop.value;
}
else if (prop.name == "ZFar")
{
else if (prop.name == "ZFar") {
cameras.back()->mClipPlaneFar = prop.value;
}
}
else if (Node::LIGHT == curNode->type)
{
else if (Node::LIGHT == curNode->type) {
/* Additional light information
*/
if (prop.name == "Attenuation")
{
if (prop.name == "Attenuation") {
lights.back()->mAttenuationLinear = prop.value;
}
else if (prop.name == "OuterCone")
{
else if (prop.name == "OuterCone") {
lights.back()->mAngleOuterCone = AI_DEG_TO_RAD( prop.value );
}
else if (prop.name == "InnerCone")
{
else if (prop.name == "InnerCone") {
lights.back()->mAngleInnerCone = AI_DEG_TO_RAD( prop.value );
}
}
// radius of the sphere to be generated -
// or alternatively, size of the cube
else if (Node::SPHERE == curNode->type && prop.name == "Radius" ||
Node::CUBE == curNode->type && prop.name == "Size" )
{
else if (Node::SPHERE == curNode->type && prop.name == "Radius"
|| Node::CUBE == curNode->type && prop.name == "Size" ) {
curNode->sphereRadius = prop.value;
}
}
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"int"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"int")) {
IntProperty prop;
ReadIntProperty(prop);
if (inAnimator)
{
if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay")
{
if (inAnimator) {
if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay") {
curAnim->timeForWay = prop.value;
}
}
else
{
else {
// sphere polgon numbers in each direction
if (Node::SPHERE == curNode->type)
{
if (prop.name == "PolyCountX")
{
if (Node::SPHERE == curNode->type) {
if (prop.name == "PolyCountX") {
curNode->spherePolyCountX = prop.value;
}
else if (prop.name == "PolyCountY")
{
else if (prop.name == "PolyCountY") {
curNode->spherePolyCountY = prop.value;
}
}
}
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"string") ||
!ASSIMP_stricmp(reader->getNodeName(),"enum"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"string") ||!ASSIMP_stricmp(reader->getNodeName(),"enum")) {
StringProperty prop;
ReadStringProperty(prop);
if (prop.value.length())
{
if (prop.name == "Name")
{
if (prop.value.length()) {
if (prop.name == "Name") {
curNode->name = prop.value;
/* If we're either a camera or a light source
* we need to update the name in the aiLight/
* aiCamera structure, too.
*/
if (Node::CAMERA == curNode->type)
{
if (Node::CAMERA == curNode->type) {
cameras.back()->mName.Set(prop.value);
}
else if (Node::LIGHT == curNode->type)
{
else if (Node::LIGHT == curNode->type) {
lights.back()->mName.Set(prop.value);
}
}
@ -1404,10 +1258,9 @@ void IRRImporter::InternReadFile( const std::string& pFile,
unsigned int pp = 0;
BatchLoader::PropertyMap map;
/* If the mesh is a static one remove all animations
/* If the mesh is a static one remove all animations from the impor data
*/
if (Node::ANIMMESH != curNode->type)
{
if (Node::ANIMMESH != curNode->type) {
pp |= aiProcess_RemoveComponent;
SetGenericProperty<int>(map.ints,AI_CONFIG_PP_RVC_FLAGS,
aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS);
@ -1419,21 +1272,9 @@ void IRRImporter::InternReadFile( const std::string& pFile,
* file referencing each other *could* cause the system to
* recurse forever.
*/
std::string::size_type pos = prop.value.find_last_of('.');
// no file extension - can't read, so we don't need to try it
if( pos == std::string::npos)
{
DefaultLogger::get()->error("IRR: Can't load files without a file extension");
}
else
{
std::string extension = prop.value.substr( pos);
for (std::string::iterator i = extension.begin(); i != extension.end();++i)
*i = ::tolower(*i);
if (".irr" == prop.value)
{
const std::string extension = GetExtension(prop.value);
if ("irr" == extension) {
DefaultLogger::get()->error("IRR: Can't load another IRR file recursively");
}
else
@ -1442,28 +1283,22 @@ void IRRImporter::InternReadFile( const std::string& pFile,
curNode->meshPath = prop.value;
}
}
}
else if (inAnimator && prop.name == "Type")
{
// type of the animator
if (prop.value == "rotation")
{
if (prop.value == "rotation") {
curAnim->type = Animator::ROTATION;
}
else if (prop.value == "flyCircle")
{
else if (prop.value == "flyCircle") {
curAnim->type = Animator::FLY_CIRCLE;
}
else if (prop.value == "flyStraight")
{
else if (prop.value == "flyStraight") {
curAnim->type = Animator::FLY_CIRCLE;
}
else if (prop.value == "followSpline")
{
else if (prop.value == "followSpline") {
curAnim->type = Animator::FOLLOW_SPLINE;
}
else
{
else {
DefaultLogger::get()->warn("IRR: Ignoring unknown animator: "
+ prop.value);
@ -1473,9 +1308,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
}
}
}
else if (reader->getNodeType() == EXN_ELEMENT_END &&
!ASSIMP_stricmp(reader->getNodeName(),"attributes"))
{
else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),"attributes")) {
break;
}
}
@ -1485,14 +1318,11 @@ void IRRImporter::InternReadFile( const std::string& pFile,
case EXN_ELEMENT_END:
// If we reached the end of a node, we need to continue processing its parent
if (!ASSIMP_stricmp(reader->getNodeName(),"node"))
{
if (!curNode)
{
if (!ASSIMP_stricmp(reader->getNodeName(),"node")) {
if (!curNode) {
// currently is no node set. We need to go
// back in the node hierarchy
if (!curParent)
{
if (!curParent) {
curParent = root;
DefaultLogger::get()->error("IRR: Too many closing <node> elements");
}
@ -1501,12 +1331,10 @@ void IRRImporter::InternReadFile( const std::string& pFile,
else curNode = NULL;
}
// clear all flags
else if (!ASSIMP_stricmp(reader->getNodeName(),"materials"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) {
inMaterials = false;
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"animators"))
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) {
inAnimator = false;
}
break;
@ -1519,11 +1347,11 @@ void IRRImporter::InternReadFile( const std::string& pFile,
/* Now iterate through all cameras and compute their final (horizontal) FOV
*/
for (std::vector<aiCamera*>::iterator it = cameras.begin(), end = cameras.end();
it != end; ++it) {
for (std::vector<aiCamera*>::iterator it = cameras.begin(), end = cameras.end();it != end; ++it) {
aiCamera* cam = *it;
if (cam->mAspect) // screen aspect could be missing
{
// screen aspect could be missing
if (cam->mAspect) {
cam->mHorizontalFOV *= cam->mAspect;
}
else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV");
@ -1539,8 +1367,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
/* Copy the cameras to the output array
*/
if (!cameras.empty())
{
if (!cameras.empty()) {
tempScene->mNumCameras = (unsigned int)cameras.size();
tempScene->mCameras = new aiCamera*[tempScene->mNumCameras];
::memcpy(tempScene->mCameras,&cameras[0],sizeof(void*)*tempScene->mNumCameras);
@ -1548,8 +1375,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
/* Copy the light sources to the output array
*/
if (!lights.empty())
{
if (!lights.empty()) {
tempScene->mNumLights = (unsigned int)lights.size();
tempScene->mLights = new aiLight*[tempScene->mNumLights];
::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights);
@ -1593,8 +1419,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
an->mChannels = new aiNodeAnim*[an->mNumChannels];
::memcpy(an->mChannels, & anims [0], sizeof(void*)*an->mNumChannels);
}
if (!meshes.empty())
{
if (!meshes.empty()) {
// copy all meshes to the temporary scene
tempScene->mNumMeshes = (unsigned int)meshes.size();
tempScene->mMeshes = new aiMesh*[tempScene->mNumMeshes];
@ -1604,8 +1429,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
/* Copy all materials to the output array
*/
if (!materials.empty())
{
if (!materials.empty()) {
tempScene->mNumMaterials = (unsigned int)materials.size();
tempScene->mMaterials = new aiMaterial*[tempScene->mNumMaterials];
::memcpy(tempScene->mMaterials,&materials[0],sizeof(void*)*
@ -1624,8 +1448,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
* scene flag. This is necessary if we failed to load all
* models from external files
*/
if (!pScene->mNumMeshes || !pScene->mNumMaterials)
{
if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
DefaultLogger::get()->warn("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
}

View File

@ -54,16 +54,12 @@ using namespace irr::io;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
IRRMeshImporter::IRRMeshImporter()
{
// nothing to do here
}
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
IRRMeshImporter::~IRRMeshImporter()
{
// nothing to do here
}
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
@ -134,23 +130,18 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
bool useColors = false;
// Parse the XML file
while (reader->read())
{
switch (reader->getNodeType())
{
while (reader->read()) {
switch (reader->getNodeType()) {
case EXN_ELEMENT:
if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh))
{
if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) {
// end of previous buffer. A material and a mesh should be there
if ( !curMat || !curMesh)
{
if ( !curMat || !curMesh) {
DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
delete curMat;
delete curMesh;
}
else
{
else {
materials.push_back(curMat);
meshes.push_back(curMesh);
}
@ -167,10 +158,8 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
}
if (!ASSIMP_stricmp(reader->getNodeName(),"material"))
{
if (curMat)
{
if (!ASSIMP_stricmp(reader->getNodeName(),"material")) {
if (curMat) {
DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
delete curMat;curMat = NULL;
}
@ -180,11 +169,8 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
{
int num = reader->getAttributeValueAsInt("vertexCount");
if (!num)
{
// This is possible ... remove the mesh from the list
// and skip further reading
if (!num) {
// This is possible ... remove the mesh from the list and skip further reading
DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
delete curMat;curMat = NULL;
@ -201,13 +187,11 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
// Determine the file format
const char* t = reader->getAttributeValueSafe("type");
if (!ASSIMP_stricmp("2tcoords", t))
{
if (!ASSIMP_stricmp("2tcoords", t)) {
curUV2s.reserve (num);
vertexFormat = 1;
if (curMatFlags & AI_IRRMESH_EXTRA_2ND_TEXTURE)
{
if (curMatFlags & AI_IRRMESH_EXTRA_2ND_TEXTURE) {
// *********************************************************
// We have a second texture! So use this UV channel
// for it. The 2nd texture can be either a normal
@ -228,24 +212,20 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
}
}
}
else if (!ASSIMP_stricmp("tangents", t))
{
else if (!ASSIMP_stricmp("tangents", t)) {
curTangents.reserve (num);
curBitangents.reserve (num);
vertexFormat = 2;
}
else if (ASSIMP_stricmp("standard", t))
{
else if (ASSIMP_stricmp("standard", t)) {
delete curMat;
DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
}
else vertexFormat = 0;
textMeaning = 1;
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"indices"))
{
if (curVertices.empty() && curMat)
{
else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) {
if (curVertices.empty() && curMat) {
delete curMat;
throw new ImportErrorException("IRRMESH: indices must come after vertices");
}
@ -257,11 +237,8 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
// allocate storage for all faces
curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount");
if (!curMesh->mNumVertices)
{
// This is possible ... remove the mesh from the list
// and skip further reading
if (!curMesh->mNumVertices) {
// This is possible ... remove the mesh from the list and skip further reading
DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
// mesh - away
@ -274,8 +251,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
continue;
}
if (curMesh->mNumVertices % 3)
{
if (curMesh->mNumVertices % 3) {
DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3");
}
@ -289,28 +265,22 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
// allocate storage for all vertices
curMesh->mVertices = new aiVector3D[curMesh->mNumVertices];
if (curNormals.size() == curVertices.size())
{
if (curNormals.size() == curVertices.size()) {
curMesh->mNormals = new aiVector3D[curMesh->mNumVertices];
}
if (curTangents.size() == curVertices.size())
{
if (curTangents.size() == curVertices.size()) {
curMesh->mTangents = new aiVector3D[curMesh->mNumVertices];
}
if (curBitangents.size() == curVertices.size())
{
if (curBitangents.size() == curVertices.size()) {
curMesh->mBitangents = new aiVector3D[curMesh->mNumVertices];
}
if (curColors.size() == curVertices.size() && useColors)
{
if (curColors.size() == curVertices.size() && useColors) {
curMesh->mColors[0] = new aiColor4D[curMesh->mNumVertices];
}
if (curUVs.size() == curVertices.size())
{
if (curUVs.size() == curVertices.size()) {
curMesh->mTextureCoords[0] = new aiVector3D[curMesh->mNumVertices];
}
if (curUV2s.size() == curVertices.size())
{
if (curUV2s.size() == curVertices.size()) {
curMesh->mTextureCoords[1] = new aiVector3D[curMesh->mNumVertices];
}
}
@ -319,13 +289,11 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
case EXN_TEXT:
{
const char* sz = reader->getNodeData();
if (textMeaning == 1)
{
if (textMeaning == 1) {
textMeaning = 0;
// read vertices
do
{
do {
SkipSpacesAndLineEnd(&sz);
aiVector3D temp;aiColor4D c;
@ -373,8 +341,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
curUVs.push_back(temp);
// read the (optional) second UV coordinate set
if (vertexFormat == 1)
{
if (vertexFormat == 1) {
sz = fast_atof_move(sz,(float&)temp.x);
SkipSpaces(&sz);
@ -383,8 +350,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
curUV2s.push_back(temp);
}
// read optional tangent and bitangent vectors
else if (vertexFormat == 2)
{
else if (vertexFormat == 2) {
// tangents
sz = fast_atof_move(sz,(float&)temp.x);
SkipSpaces(&sz);
@ -418,8 +384,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
while (SkipLine(&sz));
}
else if (textMeaning == 2)
{
else if (textMeaning == 2) {
textMeaning = 0;
// read indices
@ -436,22 +401,18 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
unsigned int curIdx = 0;
unsigned int total = 0;
while(SkipSpacesAndLineEnd(&sz))
{
if (curFace >= faceEnd)
{
while(SkipSpacesAndLineEnd(&sz)) {
if (curFace >= faceEnd) {
DefaultLogger::get()->error("IRRMESH: Too many indices");
break;
}
if (!curIdx)
{
if (!curIdx) {
curFace->mNumIndices = 3;
curFace->mIndices = new unsigned int[3];
}
unsigned int idx = strtol10(sz,&sz);
if (idx >= curVertices.size())
{
if (idx >= curVertices.size()) {
DefaultLogger::get()->error("IRRMESH: Index out of range");
idx = 0;
}
@ -466,8 +427,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
if (pcT0)*pcT0++ = curUVs[idx];
if (pcT1)*pcT1++ = curUV2s[idx];
if (++curIdx == 3)
{
if (++curIdx == 3) {
++curFace;
curIdx = 0;
}
@ -477,8 +437,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
DefaultLogger::get()->error("IRRMESH: Not enough indices");
// Finish processing the mesh - do some small material workarounds
if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors)
{
if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) {
// Take the opacity value of the current material
// from the common vertex color alpha
MaterialHelper* mat = (MaterialHelper*)curMat;
@ -496,16 +455,13 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
}
// End of the last buffer. A material and a mesh should be there
if (curMat || curMesh)
{
if ( !curMat || !curMesh)
{
if (curMat || curMesh) {
if ( !curMat || !curMesh) {
DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
delete curMat;
delete curMesh;
}
else
{
else {
materials.push_back(curMat);
meshes.push_back(curMesh);
}
@ -518,8 +474,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
// now generate the output scene
pScene->mNumMeshes = (unsigned int)meshes.size();
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] = meshes[i];
// clean this value ...
@ -538,9 +493,6 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
pScene->mRootNode->mMeshes[i] = i;
// transformation matrix to convert from IRRMESH to ASSIMP coordinates
pScene->mRootNode->mTransformation *= AI_TO_IRR_MATRIX;
// clean up and return
delete reader;
AI_DEBUG_INVALIDATE_PTR(reader);

View File

@ -167,7 +167,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BUILD_NO_JOINVERTICES_PROCESS
# include "JoinVerticesProcess.h"
#endif
#ifndef AI_BUILD_NO_CONVERTTOLH_PROCESS
#if !(defined AI_BUILD_NO_MAKELEFTHANDED_PROCESS && defined AI_BUILD_NO_FLIPUVS_PROCESS && defined AI_BUILD_NO_FLIPWINDINGORDER_PROCESS)
# include "ConvertToLHProcess.h"
#endif
#ifndef AI_BUILD_NO_TRIANGULATE_PROCESS
@ -436,8 +436,14 @@ Importer::Importer()
#if (!defined AI_BUILD_NO_SPLITLARGEMESHES_PROCESS)
mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Vertex());
#endif
#if (!defined AI_BUILD_NO_CONVERTTOLH_PROCESS)
mPostProcessingSteps.push_back( new ConvertToLHProcess());
#if (!defined AI_BUILD_NO_MAKELEFTHANDED_PROCESS)
mPostProcessingSteps.push_back( new MakeLeftHandedProcess());
#endif
#if (!defined AI_BUILD_NO_FLIPUVS_PROCESS)
mPostProcessingSteps.push_back( new FlipUVsProcess());
#endif
#if (!defined AI_BUILD_NO_FLIPWINDINGORDER_PROCESS)
mPostProcessingSteps.push_back( new FlipWindingOrderProcess());
#endif
#if (!defined AI_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
mPostProcessingSteps.push_back( new LimitBoneWeightsProcess());

View File

@ -549,7 +549,7 @@ void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0
for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
aiQuatKey& qk = anim->mRotationKeys[i];
qk.mTime = keys[i].mTime;
qk.mValue = aiQuaternion( keys[i].mValue.x ,keys[i].mValue.y ,keys[i].mValue.z );
qk.mValue = aiQuaternion( keys[i].mValue.x ,keys[i].mValue.z ,keys[i].mValue.y );
}
}

View File

@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SGSpatialSort.h"
#include "ByteSwap.h"
#include "ProcessHelper.h"
#include "ConvertToLHProcess.h"
using namespace Assimp;
@ -314,24 +315,20 @@ void LWOImporter::InternReadFile( const std::string& pFile,
// now convert all faces
unsigned int vert = 0;
std::vector<unsigned int>::iterator outIt = smoothingGroups.begin();
for (it = sorted.begin(); it != end;++it,++outIt)
{
for (it = sorted.begin(); it != end;++it,++outIt) {
const LWO::Face& face = layer.mFaces[*it];
*outIt = face.smoothGroup;
// copy all vertices
for (unsigned int q = 0; q < face.mNumIndices;++q)
{
for (unsigned int q = 0; q < face.mNumIndices;++q,++vert) {
register unsigned int idx = face.mIndices[q];
*pv = layer.mTempPoints[idx] + layer.mPivot;
pv->z *= -1.0f; // DX to OGL
//std::swap(pv->z,pv->y);
pv++;
// process UV coordinates
for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS;++w)
{
if (0xffffffff == vUVChannelIndices[w])break;
for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS;++w) {
if (0xffffffff == vUVChannelIndices[w])
break;
aiVector3D*& pp = pvUV[w];
const aiVector2D& src = ((aiVector2D*)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx];
pp->x = src.x;
@ -345,9 +342,9 @@ void LWOImporter::InternReadFile( const std::string& pFile,
}
// process vertex colors
for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w)
{
if (0xffffffff == vVColorIndices[w])break;
for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w) {
if (0xffffffff == vVColorIndices[w])
break;
*pvVC[w] = ((aiColor4D*)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx];
// If a RGB color map is explicitly requested delete the
@ -364,10 +361,8 @@ void LWOImporter::InternReadFile( const std::string& pFile,
{
}
#endif
face.mIndices[q] = vert + (face.mNumIndices-q-1);
face.mIndices[q] = vert;
}
vert += face.mNumIndices;
pf->mIndices = face.mIndices;
pf->mNumIndices = face.mNumIndices;
unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // make sure it won't be deleted
@ -568,8 +563,7 @@ void LWOImporter::GenerateNodeGraph(std::vector<aiNode*>& apcNodes)
for (unsigned int i = 0; i < apcNodes.size();++i)
if (apcNodes[i] && apcNodes[i]->mNumMeshes)++extra;
if (extra)
{
if (extra) {
// we need to add extra nodes to the root
const unsigned int newSize = extra + pScene->mRootNode->mNumChildren;
aiNode** const apcNewNodes = new aiNode*[newSize];
@ -596,15 +590,17 @@ void LWOImporter::GenerateNodeGraph(std::vector<aiNode*>& apcNodes)
if (!pScene->mRootNode->mNumChildren)
throw new ImportErrorException("LWO: Unable to build a valid node graph");
// remove a single root node
// TODO: implement directly in the above loop, no need to deallocate here
if (1 == pScene->mRootNode->mNumChildren)
{
// Remove a single root node with no meshes assigned ...
if (1 == pScene->mRootNode->mNumChildren) {
aiNode* pc = pScene->mRootNode->mChildren[0];
pc->mParent = pScene->mRootNode->mChildren[0] = NULL;
delete pScene->mRootNode;
pScene->mRootNode = pc;
}
// convert the whole stuff to RH
MakeLeftHandedProcess maker;
maker.Execute(pScene);
}
// ------------------------------------------------------------------------------------------------

View File

@ -136,12 +136,10 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, a
break;
};
if (mapping != aiTextureMapping_UV)
{
if (mapping != aiTextureMapping_UV) {
// Setup the main axis
aiVector3D v;
switch ((*it).majorAxis)
{
switch ((*it).majorAxis) {
case Texture::AXIS_X:
v = aiVector3D(1.f,0.f,0.f);
break;
@ -156,8 +154,7 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, a
pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur));
// Setup UV scalings for cylindric and spherical projections
if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE)
{
if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) {
aiUVTransform trafo;
trafo.mScaling.x = (*it).wrapAmountW;
trafo.mScaling.y = (*it).wrapAmountH;

View File

@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SceneCombiner.h"
#include "GenericProperty.h"
#include "SkeletonMeshBuilder.h"
#include "ConvertToLHProcess.h"
using namespace Assimp;
@ -858,6 +859,10 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
std::copy(anims.begin(),anims.end(),anim->mChannels);
}
// convert the master scene to RH
MakeLeftHandedProcess monster_cheat;
monster_cheat.Execute(master);
// OK ... finally build the output graph
SceneCombiner::MergeScenes(&pScene,master,attach,
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
@ -872,4 +877,5 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
SkeletonMeshBuilder builder(pScene);
}
}
}

View File

@ -144,7 +144,11 @@ void MD5Importer::InternReadFile( const std::string& pFile,
// make sure we have at least one file
if (!bHadMD5Mesh && !bHadMD5Anim && !bHadMD5Camera)
throw new ImportErrorException("Failed to read valid contents from this MD5 data set");
throw new ImportErrorException("Failed to read valid contents from this MD5* file");
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
// the output scene wouldn't pass the validation without this flag
if (!bHadMD5Mesh)
@ -156,7 +160,6 @@ void MD5Importer::InternReadFile( const std::string& pFile,
void MD5Importer::LoadFileIntoMemory (IOStream* file)
{
ai_assert(NULL != file);
fileSize = (unsigned int)file->FileSize();
// allocate storage and copy the contents of the file to a memory buffer
@ -211,6 +214,8 @@ void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc)
}
else abHad[face.mIndices[i]] = true;
}
// swap face order
std::swap(face.mIndices[0],face.mIndices[2]);
}
}
@ -443,8 +448,7 @@ void MD5Importer::LoadMD5MeshFile ()
}
// process bone weights
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
{
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) {
if (w >= meshSrc.mWeights.size())
throw new ImportErrorException("MD5MESH: Invalid weight index");
@ -478,8 +482,7 @@ void MD5Importer::LoadMD5MeshFile ()
// (however, take care that the aiFace destructor doesn't delete the mIndices array)
mesh->mNumFaces = (unsigned int)meshSrc.mFaces.size();
mesh->mFaces = new aiFace[mesh->mNumFaces];
for (unsigned int c = 0; c < mesh->mNumFaces;++c)
{
for (unsigned int c = 0; c < mesh->mNumFaces;++c) {
mesh->mFaces[c].mNumIndices = 3;
mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices;
meshSrc.mFaces[c].mIndices = NULL;
@ -621,6 +624,7 @@ void MD5Importer::LoadMD5AnimFile ()
if (!pScene->mRootNode) {
pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<MD5_Hierarchy>");
AttachChilds_Anim(-1,pScene->mRootNode,animParser.mAnimatedBones,(const aiNodeAnim**)anim->mChannels);
// Call SkeletonMeshBuilder to construct a mesh to represent the shape
@ -659,14 +663,17 @@ void MD5Importer::LoadMD5CameraFile ()
std::vector<unsigned int>& cuts = cameraParser.cuts;
std::vector<MD5::CameraAnimFrameDesc>& frames = cameraParser.frames;
// Construct output graph - a simple dummy node
aiNode* root = pScene->mRootNode = new aiNode();
root->mName.Set("<MD5Camera>");
// Construct output graph - a simple root with a dummy child.
// The root node performs the coordinate system conversion
aiNode* root = pScene->mRootNode = new aiNode("<MD5CameraRoot>");
root->mChildren = new aiNode*[root->mNumChildren = 1];
root->mChildren[0] = new aiNode("<MD5Camera>");
root->mChildren[0]->mParent = root;
// ... but with one camera assigned to it
pScene->mCameras = new aiCamera*[pScene->mNumCameras = 1];
aiCamera* cam = pScene->mCameras[0] = new aiCamera();
cam->mName = root->mName;
cam->mName = "<MD5Camera>";
// FIXME: Fov is currently set to the first frame's value
cam->mHorizontalFOV = AI_DEG_TO_RAD( frames.front().fFOV );

File diff suppressed because it is too large Load Diff

View File

@ -338,23 +338,18 @@ void PLYImporter::ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
{
bool bNeedDefaultMat = false;
for (std::vector<PLY::Face>::iterator
i = avFaces->begin();i != avFaces->end();++i)
{
if (0xFFFFFFFF == (*i).iMaterialIndex)
{
for (std::vector<PLY::Face>::iterator i = avFaces->begin();i != avFaces->end();++i) {
if (0xFFFFFFFF == (*i).iMaterialIndex) {
bNeedDefaultMat = true;
(*i).iMaterialIndex = (unsigned int)avMaterials->size();
}
else if ((*i).iMaterialIndex >= avMaterials->size() )
{
else if ((*i).iMaterialIndex >= avMaterials->size() ) {
// clamp the index
(*i).iMaterialIndex = (unsigned int)avMaterials->size()-1;
}
}
if (bNeedDefaultMat)
{
if (bNeedDefaultMat) {
// generate a default material
MaterialHelper* pcHelper = new MaterialHelper();
@ -370,6 +365,11 @@ void PLYImporter::ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
// The face order is absolutely undefined for PLY, so we have to
// use two-sided rendering to be sure it's ok.
const int two_sided = 1;
pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
avMaterials->push_back(pcHelper);
}
}
@ -997,11 +997,8 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
}
}
// check whether we have a valid source for the material data
if (NULL != pcList)
{
for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
i != pcList->alInstances.end();++i)
{
if (NULL != pcList) {
for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
aiColor4D clrOut;
MaterialHelper* pcHelper = new MaterialHelper();
@ -1019,16 +1016,12 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
// handle phong power and shading mode
int iMode;
if (0xFFFFFFFF != iPhong)
{
float fSpec = PLY::PropertyInstance::ConvertTo<float>(
(*i).alProperties[iPhong].avList.front(),ePhong);
if (0xFFFFFFFF != iPhong) {
float fSpec = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),ePhong);
// if shininess is 0 (and the pow() calculation would therefore always
// become 1, not depending on the angle) use gouraud lighting
if (fSpec)
{
// become 1, not depending on the angle), use gouraud lighting
if (fSpec) {
// scale this with 15 ... hopefully this is correct
fSpec *= 15;
pcHelper->AddProperty<float>(&fSpec, 1, AI_MATKEY_SHININESS);
@ -1041,14 +1034,16 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
// handle opacity
if (0xFFFFFFFF != iOpacity)
{
float fOpacity = PLY::PropertyInstance::ConvertTo<float>(
(*i).alProperties[iPhong].avList.front(),eOpacity);
if (0xFFFFFFFF != iOpacity) {
float fOpacity = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),eOpacity);
pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
}
// The face order is absolutely undefined for PLY, so we have to
// use two-sided rendering to be sure it's ok.
const int two_sided = 1;
pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
// add the newly created material instance to the list
pvOut->push_back(pcHelper);
}

View File

@ -62,8 +62,7 @@ void ScenePreprocessor::ProcessScene ()
ProcessAnimation(scene->mAnimations[i]);
// Generate a default material if none was specified
if (!scene->mNumMaterials && scene->mNumMeshes)
{
if (!scene->mNumMaterials && scene->mNumMeshes) {
scene->mMaterials = new aiMaterial*[2];
MaterialHelper* helper;
@ -76,13 +75,11 @@ void ScenePreprocessor::ProcessScene ()
if (scene->mMeshes[i]->mTextureCoords[0]) {
if (mat0 == 0xffffffff) {
scene->mMaterials[scene->mNumMaterials] = helper = new MaterialHelper();
// dummy texture
name.Set("texture.png");
scene->mMaterials[scene->mNumMaterials] = helper = new MaterialHelper();
name.Set("$texture.png");
helper->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(0));
// setup default name
name.Set(AI_DEFAULT_TEXTURED_MATERIAL_NAME);
helper->AddProperty(&name,AI_MATKEY_NAME);
@ -94,16 +91,11 @@ void ScenePreprocessor::ProcessScene ()
else
{
if (mat1 == 0xffffffff) {
scene->mMaterials[scene->mNumMaterials] = helper = new MaterialHelper();
// gray
scene->mMaterials[scene->mNumMaterials] = helper = new MaterialHelper();
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);
// setup the default name
name.Set(AI_DEFAULT_MATERIAL_NAME);
helper->AddProperty(&name,AI_MATKEY_NAME);
@ -121,8 +113,7 @@ void ScenePreprocessor::ProcessScene ()
void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
{
// If aiMesh::mNumUVComponents is *not* set assign the default value of 2
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i)
{
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (!mesh->mTextureCoords[i])
mesh->mNumUVComponents[i] = 0;
@ -146,10 +137,8 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
// If the information which primitive types are there in the
// mesh is currently not available, compute it.
if (!mesh->mPrimitiveTypes)
{
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
{
if (!mesh->mPrimitiveTypes) {
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
aiFace& face = mesh->mFaces[a];
switch (face.mNumIndices)
{
@ -173,8 +162,8 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
}
// If tangents and normals are given but no bitangents compute them
if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents)
{
if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) {
mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
for (unsigned int i = 0; i < mesh->mNumVertices;++i) {
mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i];
@ -186,34 +175,30 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
{
double first = 10e10, last = -10e10;
for (unsigned int i = 0; i < anim->mNumChannels;++i)
{
for (unsigned int i = 0; i < anim->mNumChannels;++i) {
aiNodeAnim* channel = anim->mChannels[i];
/* If the exact duration of the animation is not given
* compute it now.
*/
if (anim->mDuration == -1.)
{
if (anim->mDuration == -1.) {
// Position keys
for (unsigned int i = 0; i < channel->mNumPositionKeys;++i)
{
for (unsigned int i = 0; i < channel->mNumPositionKeys;++i) {
aiVectorKey& key = channel->mPositionKeys[i];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
}
// Scaling keys
for (unsigned int i = 0; i < channel->mNumScalingKeys;++i)
{
for (unsigned int i = 0; i < channel->mNumScalingKeys;++i) {
aiVectorKey& key = channel->mScalingKeys[i];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
}
// Rotation keys
for (unsigned int i = 0; i < channel->mNumRotationKeys;++i)
{
for (unsigned int i = 0; i < channel->mNumRotationKeys;++i) {
aiQuatKey& key = channel->mRotationKeys[i];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
@ -225,8 +210,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
* track from the information we have in the transformation
* matrix of the corresponding node.
*/
if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys)
{
if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) {
// Find the node that belongs to this animation
aiNode* node = scene->mRootNode->FindNode(channel->mNodeName);
if (node) // ValidateDS will complain later if 'node' is NULL
@ -238,8 +222,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
node->mTransformation.Decompose(scaling, rotation,position);
// No rotation keys? Generate a dummy track
if (!channel->mNumRotationKeys)
{
if (!channel->mNumRotationKeys) {
channel->mNumRotationKeys = 1;
channel->mRotationKeys = new aiQuatKey[1];
aiQuatKey& q = channel->mRotationKeys[0];
@ -251,8 +234,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
}
// No scaling keys? Generate a dummy track
if (!channel->mNumScalingKeys)
{
if (!channel->mNumScalingKeys) {
channel->mNumScalingKeys = 1;
channel->mScalingKeys = new aiVectorKey[1];
aiVectorKey& q = channel->mScalingKeys[0];
@ -264,8 +246,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
}
// No position keys? Generate a dummy track
if (!channel->mNumPositionKeys)
{
if (!channel->mNumPositionKeys) {
channel->mNumPositionKeys = 1;
channel->mPositionKeys = new aiVectorKey[1];
aiVectorKey& q = channel->mPositionKeys[0];
@ -278,9 +259,9 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
}
}
}
if (anim->mDuration == -1.)
{
DefaultLogger::get()->debug("Setting animation duration");
if (anim->mDuration == -1.) {
DefaultLogger::get()->debug("ScenePreprocessor: Setting animation duration");
anim->mDuration = last - std::min( first, 0. );
}
}

View File

@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StreamReader.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
#include "ConvertToLHProcess.h"
using namespace Assimp;
@ -107,14 +108,10 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
// For any of the 3 files being passed get the three correct paths
// First of all, determine file extension
std::string::size_type pos = pFile.find_last_of('.');
std::string extension = pFile.substr( pos);
for( std::string::iterator it = extension.begin(); it != extension.end(); ++it)
*it = tolower( *it);
std::string extension = GetExtension(pFile);
std::string d_path,a_path,uc_path;
if (extension == ".3d")
{
if (extension == "3d") {
// jjjj_d.3d
// jjjj_a.3d
pos = pFile.find_last_of('_');
@ -123,8 +120,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
}
extension = pFile.substr(0,pos);
}
else // if (extension == ".uc")
{
else {
extension = pFile.substr(0,pos);
}
@ -154,16 +150,13 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
// collect triangles
std::vector<Unreal::Triangle> triangles(numTris);
for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();
it != end; ++it)
{
for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) {
Unreal::Triangle& tri = *it;
for (unsigned int i = 0; i < 3;++i)
{
for (unsigned int i = 0; i < 3;++i) {
tri.mVertex[i] = d_reader.GetI2();
if (tri.mVertex[i] >= numTris)
{
if (tri.mVertex[i] >= numTris) {
DefaultLogger::get()->warn("UNREAL: vertex index out of range");
tri.mVertex[i] = 0;
}
@ -208,9 +201,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
// collect vertices
std::vector<aiVector3D> vertices(numVert);
for (std::vector<aiVector3D>::iterator it = vertices.begin(), end = vertices.end();
it != end; ++it)
{
for (std::vector<aiVector3D>::iterator it = vertices.begin(), end = vertices.end(); it != end; ++it) {
int32_t val = a_reader.GetI4();
Unreal::DecompressVertex(*it,val);
}
@ -236,8 +227,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
std::vector< std::pair< std::string,std::string > > tempTextures;
// do a quick search in the UC file for some known, usually texture-related, tags
for (;*data;++data)
{
for (;*data;++data) {
if (TokenMatchI(data,"#exec",5)) {
SkipSpacesAndLineEnd(&data);
@ -245,20 +235,16 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
if (TokenMatchI(data,"TEXTURE",7)) {
SkipSpacesAndLineEnd(&data);
if (TokenMatchI(data,"IMPORT",6))
{
if (TokenMatchI(data,"IMPORT",6)) {
tempTextures.push_back(std::pair< std::string,std::string >());
std::pair< std::string,std::string >& me = tempTextures.back();
for (;!IsLineEnd(*data);++data)
{
if (!::ASSIMP_strincmp(data,"NAME=",5))
{
for (;!IsLineEnd(*data);++data) {
if (!::ASSIMP_strincmp(data,"NAME=",5)) {
const char *d = data+=5;
for (;!IsSpaceOrNewLine(*data);++data);
me.first = std::string(d,(size_t)(data-d));
}
else if (!::ASSIMP_strincmp(data,"FILE=",5))
{
else if (!::ASSIMP_strincmp(data,"FILE=",5)) {
const char *d = data+=5;
for (;!IsSpaceOrNewLine(*data);++data);
me.second = std::string(d,(size_t)(data-d));
@ -279,13 +265,11 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
std::pair<unsigned int, std::string>& me = textures.back();
for (;!IsLineEnd(*data);++data) {
if (!::ASSIMP_strincmp(data,"NUM=",4))
{
if (!::ASSIMP_strincmp(data,"NUM=",4)) {
data += 4;
me.first = strtol10(data,&data);
}
else if (!::ASSIMP_strincmp(data,"TEXTURE=",8))
{
else if (!::ASSIMP_strincmp(data,"TEXTURE=",8)) {
data += 8;
const char *d = data;
for (;!IsSpaceOrNewLine(*data);++data);
@ -293,10 +277,8 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
// try to find matching path names, doesn't care if we don't find them
for (std::vector< std::pair< std::string,std::string > >::const_iterator it = tempTextures.begin();
it != tempTextures.end(); ++it)
{
if ((*it).first == me.second)
{
it != tempTextures.end(); ++it) {
if ((*it).first == me.second) {
me.second = (*it).second;
break;
}
@ -330,9 +312,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
materials.reserve(textures.size()*2+5);
// find out how many output meshes and materials we'll have and build material indices
for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();
it != end; ++it)
{
for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) {
Unreal::Triangle& tri = *it;
Unreal::TempMat mat(tri);
std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
@ -389,8 +369,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
else ::strcat(s.data,"os_");
// make TRANS faces 90% opaque that RemRedundantMaterials won't catch us
if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS)
{
if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS) {
const float opac = 0.9f;
mat->AddProperty(&opac,1,AI_MATKEY_OPACITY);
::strcat(s.data,"tran_");
@ -398,8 +377,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
else ::strcat(s.data,"opaq_");
// a special name for the weapon attachment point
if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER)
{
if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) {
s.length = ::sprintf(s.data,"$WeaponTag$");
color = aiColor3D(0.f,0.f,0.f);
}
@ -411,11 +389,8 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
// set texture, if any
const unsigned int tex = materials[i].tex;
for (std::vector< std::pair< unsigned int, std::string > >::const_iterator it = textures.begin();
it != textures.end();++it)
{
if ((*it).first == tex)
{
for (std::vector< std::pair< unsigned int, std::string > >::const_iterator it = textures.begin();it != textures.end();++it) {
if ((*it).first == tex) {
s.Set((*it).second);
mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
break;
@ -424,9 +399,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
}
// fill them.
for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();
it != end; ++it)
{
for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) {
Unreal::Triangle& tri = *it;
Unreal::TempMat mat(tri);
std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
@ -435,14 +408,17 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
aiFace& f = mesh->mFaces[mesh->mNumFaces++];
f.mIndices = new unsigned int[f.mNumIndices = 3];
for (unsigned int i = 0; i < 3;++i,mesh->mNumVertices++)
{
for (unsigned int i = 0; i < 3;++i,mesh->mNumVertices++) {
f.mIndices[i] = mesh->mNumVertices;
mesh->mVertices[mesh->mNumVertices] = vertices[ tri.mVertex[i] ];
mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D( tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f);
}
}
// convert to RH
MakeLeftHandedProcess hero;
hero.Execute(pScene);
}
#endif // !! AI_BUILD_NO_3D_IMPORTER

View File

@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "XFileImporter.h"
#include "XFileParser.h"
#include "MaterialSystem.h"
#include "ConvertToLHProcess.h"
using namespace Assimp;
@ -141,9 +140,9 @@ void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, const X
CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes);
}
// convert the root node's transformation to OGL coords
if( pScene->mRootNode)
ConvertToLHProcess::ConvertToOGL( pScene->mRootNode->mTransformation);
// Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly
MakeLeftHandedProcess convertProcess;
convertProcess.Execute( pScene);
// finally: create a dummy material if not material was imported
if( pScene->mNumMaterials == 0)
@ -305,7 +304,7 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
// collect vertex data for indices of this face
for( unsigned int d = 0; d < df.mNumIndices; d++)
{
df.mIndices[df.mNumIndices - 1 - d] = newIndex; // inverted face orientation for OGL
df.mIndices[d] = newIndex;
orgPoints[newIndex] = pf.mIndices[d];
// Position
@ -313,6 +312,7 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
// Normal, if present
if( mesh->HasNormals())
mesh->mNormals[newIndex] = sourceMesh->mNormals[sourceMesh->mNormFaces[f].mIndices[d]];
// texture coord sets
for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; e++)
{
@ -434,9 +434,6 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
nbone->mNodeName.Set( bone->mBoneName);
nanim->mChannels[b] = nbone;
// apply the LH->RH conversion if the animation affects the root bone
bool isRootAnim = (bone->mBoneName == pScene->mRootNode->mName.data);
// keyframes are given as combined transformation matrix keys
if( bone->mTrafoKeys.size() > 0)
{
@ -455,8 +452,6 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
// extract position
aiVector3D pos( trafo.a4, trafo.b4, trafo.c4);
if( isRootAnim)
ConvertToLHProcess::ConvertToOGL( pos);
nbone->mPositionKeys[c].mTime = time;
nbone->mPositionKeys[c].mValue = pos;
@ -475,9 +470,6 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z,
trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z);
if( isRootAnim)
ConvertToLHProcess::ConvertToOGL( rotmat);
// and convert it into a quaternion
nbone->mRotationKeys[c].mTime = time;
nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat);
@ -493,8 +485,6 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
for( unsigned int c = 0; c < nbone->mNumPositionKeys; c++)
{
aiVector3D pos = bone->mPosKeys[c].mValue;
if( isRootAnim)
ConvertToLHProcess::ConvertToOGL( pos);
nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime;
nbone->mPositionKeys[c].mValue = pos;
@ -506,8 +496,6 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
for( unsigned int c = 0; c < nbone->mNumRotationKeys; c++)
{
aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix();
if( isRootAnim)
ConvertToLHProcess::ConvertToOGL( rotmat);
nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime;
nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat);

Binary file not shown.

View File

@ -31,7 +31,7 @@ PROJECT_NAME = assimp
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = r281
PROJECT_NUMBER = r350
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

View File

@ -17,7 +17,7 @@ processing steps to the imported data such as conversion to indexed meshes, calc
or conversion from right-handed to left-handed coordinate systems.
ASSIMP currently supports the following file formats (note that some loaders lack some features of their formats because
some file formats contain data not supported by Assimp, some stuff would require so much conversion work
some file formats contain data not supported by ASSIMP, some stuff would require so much conversion work
that it has not yet been implemented, and some formats have not completely been documented by their inventors):
<hr>
<br><tt>
@ -37,7 +37,7 @@ that it has not yet been implemented, and some formats have not completely been
<b>Quake II</b> ( <i>*.md2</i> ) <br>
<b>Quake III</b> ( <i>*.md3</i> ) <br>
<b>RtCW</b> ( <i>*.mdc</i> )<br>
<b>Doom 3</b> ( <i>*.md5</i> ) <sup>3</sup> <br>
<b>Doom 3</b> ( <i>*.md5mesh;*.md5anim;*.md5camera</i> ) <br>
<b>DirectX X </b> ( <i>*.x</i> ). <br>
<b>Quick3D </b> ( <i>*.q3o;*q3s</i> ). <br>
<b>Raw Triangles </b> ( <i>*.raw</i> ). <br>
@ -51,7 +51,7 @@ that it has not yet been implemented, and some formats have not completely been
<b>3D GameStudio Model </b> ( <i>*.mdl</i> ) <br>
<b>3D GameStudio Terrain</b> ( <i>*.hmp</i> )<br><br><br>
</tt>
<sup>3</sup>: These formats support animations, but Assimp doesn't yet support them (or they're buggy)
<sup>3</sup>: These formats support animations, but ASSIMP doesn't yet support them (or they're buggy)
<br>
<hr>
@ -115,9 +115,9 @@ assimp-discussions</a>.
@section install_prebuilt Using the pre-built libraries with Visual C++ 8/9
If you develop at Visual Studio 2005 or 2008, you can simply use the pre-built linker libraries provided in the distribution.
Extract all files to a place of your choice. A directory called "Assimp" will be created there. Add the Assimp/include path
Extract all files to a place of your choice. A directory called "ASSIMP" will be created there. Add the ASSIMP/include path
to your include paths (Menu-&gt;Extras-&gt;Options-&gt;Projects and Solutions-&gt;VC++ Directories-&gt;Include files)
and the Assimp/lib/&lt;Compiler&gt; path to your linker paths (Menu-&gt;Extras-&gt;Options-&gt;Projects and Solutions-&gt;VC++ Directories-&gt;Library files).
and the ASSIMP/lib/&lt;Compiler&gt; path to your linker paths (Menu-&gt;Extras-&gt;Options-&gt;Projects and Solutions-&gt;VC++ Directories-&gt;Library files).
This is neccessary only once to setup all paths inside you IDE.
To use the library in your C++ project you have to include either &lt;assimp.hpp&gt; or &lt;assimp.h&gt; plus some others starting with &lt;aiTypes.h&gt;.
@ -140,7 +140,7 @@ various useful debug checks. Actually they are really helpful for debugging, but
so extremely slow that they can make the STL up to 100 times slower (imagine a <i>std::vector<T>::operator[] </i>
performing 3 or 4 single checks! scary ...).
These security enhancements are - thanks MS! - also active in release builds, rendering Assimp several times
These security enhancements are - thanks MS! - also active in release builds, rendering ASSIMP several times
slower. However, it is possible to disable them by defining
@code
@ -149,14 +149,14 @@ _SECURE_SCL=0
@endcode
in the preprocessor options (or alternatively in the source code, just before the STL is included for the first time).
<b>Assimp's vc8 and vc9 configs enable these flags by default</b>.
<b>ASSIMP's vc8 and vc9 configs enable these flags by default</b>.
<i>If you're linking statically against Assimp:</i> Make sure your applications uses the same STl settings!
<i>If you're linking statically against ASSIMP:</i> Make sure your applications uses the same STl settings!
If you do not, there are two binary incompatible STL versions mangled together and you'll crash.
Alternatively you can disable the fast STL settings for Assimp by removing the 'FastSTL' property sheet from
Alternatively you can disable the fast STL settings for ASSIMP by removing the 'FastSTL' property sheet from
the vc project file.
<i>If you're using Assimp in a DLL:</i> It's ok. There's no STL used in the DLL interface, so it doesn't care whether
<i>If you're using ASSIMP in a DLL:</i> It's ok. There's no STL used in the DLL interface, so it doesn't care whether
your application uses the same STL settings or not.
<br><br>
Another option is to build against a different STL implementation, for example STlport. There's a special
@ -200,7 +200,7 @@ The Boost-Workaround consists of dummy replacements for some boost utility templ
<li><i>boost.foreach</i> </li>
<li><i>boost.tuple</i></li>
</ul>
These implementations are very limited and are not intended for use outside Assimp. A compiler
These implementations are very limited and are not intended for use outside ASSIMP. A compiler
with full support for partial template specializations is required. To enable the workaround, put the following in
your compiler's list of predefined macros:
@code
@ -220,26 +220,26 @@ for more details.
@section assimp_dll DLL build
Assimp can be built as DLL. You just need to select a -dll config from the list of project
ASSIMP can be built as DLL. You just need to select a -dll config from the list of project
configs and you're fine. Don't forget to copy the DLL to the directory of your executable :-)
<b>NOTE:</b> Theoretically Assimp-dll can be used with multithreaded (non-dll) runtime libraries,
<b>NOTE:</b> Theoretically ASSIMP-dll can be used with multithreaded (non-dll) runtime libraries,
as long as you don't utilize any non-public stuff from the code dir. However, if you happen
to encounter *very* strange problems try changing the runtime to multithreaded (Debug) DLL.
@section assimp_stlport Building against STLport
If your compiler's default implementation of the STL is too slow, lacks some features,
contains bugs or if you just want to tweak Assimp's performance a little try a build
contains bugs or if you just want to tweak ASSIMP's performance a little try a build
against STLport. STLport is a free, fast and secure STL replacement that works with
all major compilers and platforms. To get it visit their website at
<a href="http://www.stlport.org"/><stlport.org></a> and download the latest STLport release.
Usually you'll just need to run 'configure' + a makefile (see the README for more details).
Don't miss to add <stlport_root>/stlport to your compiler's default include paths - <b>prior</b>
to the directory where the compiler vendor's STL lies. Do the same for <stlport_root>/lib and
recompile Assimp. To ensure you're really building against STLport see aiGetCompileFlags().
recompile ASSIMP. To ensure you're really building against STLport see aiGetCompileFlags().
<br>
Usually building Assimp against STLport yields a better overall performance so it might be
Usually building ASSIMP against STLport yields a better overall performance so it might be
worth a try if the library is too slow for you.
*/
@ -251,8 +251,8 @@ worth a try if the library is too slow for you.
@section access_cpp Access by C++ class interface
The ASSIMP library can be accessed by both a class or flat function interface. The C++ class
interface is the preferred way of interaction: you create an instance of class Assimp::Importer,
maybe adjust some settings of it and then call Assimp::Importer::ReadFile(). The class will
interface is the preferred way of interaction: you create an instance of class ASSIMP::Importer,
maybe adjust some settings of it and then call ASSIMP::Importer::ReadFile(). The class will
read the files and process its data, handing back the imported data as a pointer to an aiScene
to you. You can now extract the data you need from the file. The importer manages all the resources
for itsself. If the importer is destroyed, all the data that was created/read by it will be
@ -269,7 +269,7 @@ C++ example:
bool DoTheImportThing( const std::string& pFile)
{
// Create an instance of the Importer class
Assimp::Importer importer;
ASSIMP::Importer importer;
// And have it read the given file with some example postprocessing
// Usually - if speed is not the most important aspect for you - you'll
@ -358,7 +358,7 @@ custom implementations of IOStream and IOSystem. A shortened example might look
#include <IOSystem.h>
// My own implementation of IOStream
class MyIOStream : public Assimp::IOStream
class MyIOStream : public ASSIMP::IOStream
{
friend class MyIOSystem;
@ -377,7 +377,7 @@ public:
};
// Fisher Price - My First Filesystem
class MyIOSystem : public Assimp::IOSystem
class MyIOSystem : public ASSIMP::IOSystem
{
MyIOSystem() { ... }
~MyIOSystem() { ... }
@ -402,12 +402,12 @@ class MyIOSystem : public Assimp::IOSystem
@endcode
Now that your IO system is implemented, supply an instance of it to the Importer object by calling
Assimp::Importer::SetIOHandler().
ASSIMP::Importer::SetIOHandler().
@code
void DoTheImportThing( const std::string& pFile)
{
Assimp::Importer importer;
ASSIMP::Importer importer;
// put my custom IO handling in place
importer.SetIOHandler( new MyIOSystem());
@ -435,7 +435,7 @@ following prerequisites are fulfilled:
</ul>
See the @link assimp_st Single-threaded build section @endlink to learn how to build a lightweight variant
of Assimp which is not thread-safe and does not utilize multiple threads for loading.
of ASSIMP which is not thread-safe and does not utilize multiple threads for loading.
@section logging Logging in the AssetImporter
@ -448,13 +448,13 @@ by calling it as a singleton with the requested logging-type. To see how this wo
@code
// Create a logger instance
Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE);
ASSIMP::DefaultLogger::create("",ASSIMP::Logger::VERBOSE);
// Now I am ready for logging my stuff
Assimp::DefaultLogger::get()->info("this is my info-call");
ASSIMP::DefaultLogger::get()->info("this is my info-call");
// Kill it after the work is done
Assimp::DefaultLogger::kill();
ASSIMP::DefaultLogger::kill();
@endcode
At first you have to create the default-logger-instance (create). Now you are ready to rock and can log a
@ -498,7 +498,7 @@ severity |= Logger::WARN;
severity |= Logger::ERR;
// Attaching it to the default logger
Assimp::DefaultLogger::get()->attachStream( new myStream(), severity );
ASSIMP::DefaultLogger::get()->attachStream( new myStream(), severity );
@endcode
@ -514,7 +514,7 @@ unsigned int severity = 0;
severity |= Logger::DEBUGGING;
// Detach debug messages from you self defined stream
Assimp::DefaultLogger::get()->attachStream( new myStream(), severity );
ASSIMP::DefaultLogger::get()->attachStream( new myStream(), severity );
@endcode
@ -541,7 +541,7 @@ In the verbose level debug messages will be logged, too.
The ASSIMP library returns the imported data in a collection of structures. aiScene forms the root
of the data, from here you gain access to all the nodes, meshes, materials, animations or textures
that were read from the imported file. The aiScene is returned from a successful call to
Assimp::Importer::ReadFile(), aiImportFile() or aiImportFileEx() - see the @link usage Usage page @endlink
ASSIMP::Importer::ReadFile(), aiImportFile() or aiImportFileEx() - see the @link usage Usage page @endlink
for further information on how to use the library.
By default, all 3D data is provided in a right-handed coordinate system such as OpenGL uses. In
@ -549,7 +549,25 @@ this coordinate system, +X points to the right, +Y points away from the viewer i
+Z points upwards. Several modeling packages such as 3D Studio Max use this coordinate system as well.
By contrast, some other environments use left-handed coordinate systems, a prominent example being
DirectX. If you need the imported data to be in a left-handed coordinate system, supply the
aiProcess_ConvertToLeftHanded flag to the ReadFile() function call.
#aiProcess_MakeLeftHanded flag to the ReadFile() function call.
The output face winding is counter-clockwise. Use #aiProcess_FlipWindingOrder to get CW data.
@code
x0
x2
x1
@endcode
The output UV coordinate system has its origin in the lower-left corner:
@code
0y|1y ---------- 1x|1y
| |
| |
| |
0x|0y ---------- 1x|0y
@endcode
Use the #aiProcess_FlipUVs flag to get UV coordinates with the upper-left corner als origin.
All matrices in the library are row-major. That means that the matrices are stored row by row in memory,
which is similar to the OpenGL matrix layout. A typical 4x4 matrix including a translational part looks like this:
@ -650,7 +668,7 @@ a set of properties accessible by their names. Have a look at aiMaterial.h to se
properties are defined. In this file there are also various functions defined to test for the
presence of certain properties in a material and retrieve their values.
Example to convert from an Assimp material to a Direct3D 9 material for use with the fixed
Example to convert from an ASSIMP material to a Direct3D 9 material for use with the fixed
function pipeline. Textures are not handled, only colors and the specular power, sometimes
also refered to as "shininess":
@code

View File

@ -65,12 +65,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//////////////////////////////////////////////////////////////////////////
// Define ASSIMP_BUILD_NO_XX_PROCESS to disable a specific
// post-processing step. The spe will be excluded from the
// build in this case. 'XX' stands for the name of the loader.
// List of defines:
// post-processing step.
// Full list of all 'XX':
// CALCTANGENTS
// JOINVERTICES
// CONVERTTOLH
// TRIANGULATE
// GENFACENORMALS
// GENVERTEXNORMALS
@ -88,6 +86,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// TRANSFORMTEXCOORDS
// GENUVCOORDS
// ENTITYMESHBUILDER
// MAKELEFTHANDED
// FLIPUVS
// FLIPWINDINGORDER
// *OPTIMIZEMESHES
// *OPTIMIZEANIMS
// *OPTIMIZENODES
// *GENENTITYMESHES
// Compiler specific includes and definitions
#if (defined _MSC_VER)

View File

@ -50,89 +50,152 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern "C" {
#endif
/** Defines the flags for all possible post processing steps. */
// -----------------------------------------------------------------------------------
/** @enum aiPostProcessSteps
* @brief Defines the flags for all possible post processing steps.
*
* @see Importer::ReadFile
* @see aiImportFile
* @see aiImportFileEx
*/
// -----------------------------------------------------------------------------------
enum aiPostProcessSteps
{
/** <hr>Calculates the tangents and bitangents for the imported meshes. Does nothing
* if a mesh does not have normals. You might want this post processing step to be
* executed if you plan to use tangent space calculations such as normal mapping
* applied to the meshes. There exists a configuration option,
* #AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE that allows you to specify
* an angle maximum for the step.
*/
aiProcess_CalcTangentSpace = 1,
/** <hr>Identifies and joins identical vertex data sets within all imported meshes.
// -------------------------------------------------------------------------
/** <hr>Calculates the tangents and bitangents for the imported meshes.
*
* Does nothing if a mesh does not have normals. You might want this post
* processing step to be executed if you plan to use tangent space calculations
* such as normal mapping applied to the meshes. There's a config setting,
* <tt>#AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE</tt>, which allows you to specify
* a maximum smoothing angle for the algorithm. However, usually you'll
* want to let the default value. Thanks.
*/
aiProcess_CalcTangentSpace = 0x1,
// -------------------------------------------------------------------------
/** <hr>Identifies and joins identical vertex data sets within all
* imported meshes.
*
* After this step is run each mesh does contain only unique vertices anymore,
* so a vertex is possibly used by multiple faces. You usually want
* to use this post processing step.*/
aiProcess_JoinIdenticalVertices = 2,
* to use this post processing step. If your application deals with
* indexed geometry, this step is compulsory or you'll just waste rendering
* time. <b>If this flag is not specified</b>, no vertices are referenced by
* more than one face and <b>no index buffer is required</b> for rendering.
*/
aiProcess_JoinIdenticalVertices = 0x2,
/** <hr>Converts all the imported data to a left-handed coordinate space such as
* the DirectX coordinate system. By default the data is returned in a right-handed
* coordinate space which for example OpenGL prefers. In this space, +X points to the
* right, +Y points towards the viewer and and +Z points upwards. In the DirectX
// -------------------------------------------------------------------------
/** <hr>Converts all the imported data to a left-handed coordinate space.
*
* By default the data is returned in a right-handed coordinate space which
* for example OpenGL prefers. In this space, +X points to the right,
* +Z points towards the viewer and and +Y points upwards. In the DirectX
* coordinate space +X points to the right, +Y points upwards and +Z points
* away from the viewer.
*
* You'll probably want to consider this flag if you use Direct3D for
* rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
* setting and boundles all conversions typically required for D3D-based
* applications.
*/
aiProcess_ConvertToLeftHanded = 4,
aiProcess_MakeLeftHanded = 0x4,
/** <hr>Triangulates all faces of all meshes. By default the imported mesh data might
* contain faces with more than 3 indices. For rendering a mesh you usually need
* all faces to be triangles. This post processing step splits up all higher faces
* to triangles. This step won't modify line and point primitives. If you need
* only triangles, do the following:<br>
* 1. Specify both the aiProcess_Triangulate and the aiProcess_SortByPType
* step. <br>
* 2. Ignore all point and line meshes when you process assimp's output data.
// -------------------------------------------------------------------------
/** <hr>Triangulates all faces of all meshes.
*
* By default the imported mesh data might contain faces with more than 3
* indices. For rendering you'll usually want all faces to be triangles.
* This post processing step splits up all higher faces to triangles.
* Line and point primitives are *not* modified!. If you want
* 'triangles only' with no other kinds of primitives, try the following
* solution:
* <ul>
* <li>Specify both #aiProcess_Triangulate and #aiProcess_SortByPType </li>
* </li>Ignore all point and line meshes when you process assimp's output</li>
* </ul>
*/
aiProcess_Triangulate = 8,
aiProcess_Triangulate = 0x8,
// -------------------------------------------------------------------------
/** <hr>Removes some parts of the data structure (animations, materials,
* light sources, cameras, textures, vertex components).
*
* The components to be removed are specified in a separate
* configuration option, #AI_CONFIG_PP_RVC_FLAGS. This is quite useful
* configuration option, <tt>#AI_CONFIG_PP_RVC_FLAGS</tt>. This is quite useful
* if you don't need all parts of the output structure. Especially vertex
* colors are rarely used today ... . Calling this step to exclude non-required
* colors are rarely used today ... . Calling this step to remove unrequired
* stuff from the pipeline as early as possible results in an increased
* performance and a better optimized output data structure.
* This step is also useful if you want to force Assimp to recompute
* normals or tangents. The corresponding steps don't recompute them if
* they're already there (loaded from the source asset). By using this
* step you can make sure they are NOT there.
*
* This flag is a poor one, mainly because it's purpose is usually
* misunderstood. Consider the following case: a 3d model has been exported
* from a CAD app, it has per-face vertex colors. Vertex positions can't be
* shared, thus the #aiProcess_JoinIdenticalVertices step fails to
* optimize the data. Just because these nasty, little vertex colors.
* Most apps don't even process them, so it's all for nothing. By using
* this step, unneeded components are excluded as early as possible
* thus opening more room for internal optimzations.
*/
aiProcess_RemoveComponent = 0x10,
/** <hr>Generates normals for all faces of all meshes. The normals are shared
* between the three vertices of a face. This is ignored
* if normals are already existing. This flag may not be specified together
* with aiProcess_GenSmoothNormals.
// -------------------------------------------------------------------------
/** <hr>Generates normals for all faces of all meshes.
*
* This is ignored if normals are already there at the time where this flag
* is evaluated. Model importers try to load them from the source file, so
* they're usually already there. Face normals are shared between all points
* of a single face, so a single point can have multiple normals, which in
* other words, enforces the library to duplicate vertices in some cases.
* #aiProcess_JoinIdenticalVertices is *senseless* then.
*
* This flag may not be specified together with #aiProcess_GenSmoothNormals.
*/
aiProcess_GenNormals = 0x20,
/** <hr>Generates smooth normals for all vertices in the mesh. This is ignored
* if normals are already existing. This flag may not be specified together
* with aiProcess_GenNormals. There's a configuration option,
* #AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE that allows you to specify
// -------------------------------------------------------------------------
/** <hr>Generates smooth normals for all vertices in the mesh.
*
* This is ignored if normals are already there at the time where this flag
* is evaluated. Model importers try to load them from the source file, so
* they're usually already there.
*
* This flag may (of course) not be specified together with
* #aiProcess_GenNormals. There's a configuration option,
* <tt>#AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE</tt> which allows you to specify
* an angle maximum for the normal smoothing algorithm. Normals exceeding
* this limit are not smoothed, resulting in a a 'hard' seam between two faces.
* Using a decent angle here (e.g. 80°) results in very good visual
* appearance.
*/
aiProcess_GenSmoothNormals = 0x40,
/** <hr>Splits large meshes into submeshes
* This is quite useful for realtime rendering where the number of triangles
* to be maximally rendered in one drawcall is usually limited by the video driver.
* The maximum vertex buffer size suffers from limitations, too. Both
* requirements are met with this step: you can specify both a triangle and vertex
* limit for a single mesh.
// -------------------------------------------------------------------------
/** <hr>Splits large meshes into smaller submeshes
*
* The split limits can be set through the <tt>AI_CONFIG_PP_SLM_VERTEX_LIMIT</tt>
* and <tt>AI_CONFIG_PP_SLM_TRIANGLE_LIMIT</tt> The default values are
* <tt>AI_SLM_DEFAULT_MAX_VERTICES</tt> and <tt>AI_SLM_DEFAULT_MAX_TRIANGLES</tt>.
* This is quite useful for realtime rendering where the number of triangles
* which can be maximally processed in a single draw-call is usually limited
* by the video driver/hardware. The maximum vertex buffer is usually limited,
* too. Both requirements can be met with this step: you may specify both a
* triangle and vertex limit for a single mesh.
*
* The split limits can (and should!) be set through the
* <tt>#AI_CONFIG_PP_SLM_VERTEX_LIMIT</tt> and <tt>#AI_CONFIG_PP_SLM_TRIANGLE_LIMIT</tt>
* settings. The default values are <tt>#AI_SLM_DEFAULT_MAX_VERTICES</tt> and
* <tt>#AI_SLM_DEFAULT_MAX_TRIANGLES</tt>.
*
* Note that splitting is generally a time-consuming task, but not if there's
* nothing to split. The use of this step is recommended for most users.
*/
aiProcess_SplitLargeMeshes = 0x80,
// -------------------------------------------------------------------------
/** <hr>Removes the node graph and pre-transforms all vertices with
* the local transformation matrices of their nodes. The output
* scene does still contain nodes, however, there is only a
@ -149,44 +212,87 @@ enum aiPostProcessSteps
*/
aiProcess_PreTransformVertices = 0x100,
// -------------------------------------------------------------------------
/** <hr>Limits the number of bones simultaneously affecting a single vertex
* to a maximum value. If any vertex is affected by more than that number
* of bones, the least important vertex weights are removed and the remaining
* vertex weights are renormalized so that the weights still sum up to 1.
* The default bone weight limit is 4 (defined as AI_LMW_MAX_WEIGHTS in
* LimitBoneWeightsProcess.h), but you can use the aiSetBoneWeightLimit
* function to supply your own limit to the post processing step.
* to a maximum value.
*
* If you intend to perform the skinning in hardware, this post processing step
* might be of interest for you.
* If any vertex is affected by more than that number of bones, the least
* important vertex weights are removed and the remaining vertex weights are
* renormalized so that the weights still sum up to 1.
* The default bone weight limit is 4 (defined as <tt>#AI_LMW_MAX_WEIGHTS</tt> in
* aiConfig.h), but you can use the <tt>#AI_CONFIG_PP_LBW_MAX_WEIGHTS</tt> setting to
* supply your own limit to the post processing step.
*
* If you intend to perform the skinning in hardware, this post processing
* step might be of interest for you.
*/
aiProcess_LimitBoneWeights = 0x200,
/** <hr>Validates the aiScene data structure before it is returned.
// -------------------------------------------------------------------------
/** <hr>Validates the imported scene data structure
* This makes sure that all indices are valid, all animations and
* bones are linked correctly, all material are correct and so on ...
* This is primarily intended for our internal debugging stuff,
* however, it could be of interest for applications like editors
* where stability is more important than loading performance.
* bones are linked correctly, all material references are correct .. etc.
*
* It is recommended to capture Assimp's log output if you use this flag,
* so you can easily find ot what's actually wrong if a file fails the
* validation. The validator is quite rude and will find *all*
* inconsistencies in the data structure ... plugin developers are
* recommended to use it to debug their loaders. There are two types of
* validation failures:
* <ul>
* <li>Error: There's something wrong with the imported data. Further
* postprocessing is not possible and the data is not usable at all.
* The import fails. #Importer::GetErrorString() or #aiGetErrorString()
* carry the error message around.</li>
* <li>Warning: There are some minor issues (e.g. 1000000 animation
* keyframes with the same time), but further postprocessing and use
* of the data structure is still safe. Warning details are written
* to the log file, <tt>#AI_SCENE_FLAGS_VALIDATION_WARNING</tt> is set
* in #aiScene::mFlags</li>
* </ul>
*
* This post-processing step is not time-consuming. It's use is not
* compulsory, but recommended.
*/
aiProcess_ValidateDataStructure = 0x400,
/** <hr>Reorders triangles for vertex cache locality and thus better performance.
// -------------------------------------------------------------------------
/** <hr>Reorders triangles for better vertex cache locality.
*
* The step tries to improve the ACMR (average post-transform vertex cache
* miss ratio) for all meshes. The step runs in O(n) and is roughly
* basing on the algorithm described in this paper:
* http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf
* miss ratio) for all meshes. The implementation runs in O(n) and is
* roughly based on the 'tipsify' algorithm (see <a href="
* http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf">this
* paper</a>).
*
* If you intend to render huge models in hardware, this step might
* be of interest for you. The <tt>#AI_CONFIG_PP_ICL_PTCACHE_SIZE</tt>config
* setting can be used to fine-tune the cache optimization.
*/
aiProcess_ImproveCacheLocality = 0x800,
/** <hr>Searches for redundant materials and removes them.
// -------------------------------------------------------------------------
/** <hr>Searches for redundant/unreferenced materials and removes them.
*
* This is especially useful in combination with the PretransformVertices
* and OptimizeGraph steps. Both steps join small meshes, but they
* can't do that if two meshes have different materials.
* This is especially useful in combination with the
* #aiProcess_PretransformVertices and #aiProcess_OptimizeMeshes flags.
* Both join small meshes with equal characteristics, but they can't do
* their work if two meshes have different materials. Because several
* material settings are always lost during Assimp's import filters,
* (and because many exporters don't check for redundant materials), huge
* models often have materials which are are defined several times with
* exactly the same settings ..
*
* Several material settings not contributing to the final appearance of
* a surface are ignored in all comparisons ... the material name is
* one of them. So, if you're passing additional information through the
* content pipeline (probably using using *magic* material names), don't
* specify this flag. Alternatively take a look at the
* <tt>#AI_CONFIG_PP_RRM_EXCLUDE_LIST</tt> setting.
*/
aiProcess_RemoveRedundantMaterials = 0x1000,
// -------------------------------------------------------------------------
/** <hr>This step tries to determine which meshes have normal vectors
* that are facing inwards. The algorithm is simple but effective:
* the bounding box of all vertices + their normals is compared against
@ -198,7 +304,7 @@ enum aiPostProcessSteps
*/
aiProcess_FixInfacingNormals = 0x2000,
// -------------------------------------------------------------------------
/** <hr>This step splits meshes with more than one primitive type in
* homogeneous submeshes.
*
@ -206,16 +312,17 @@ enum aiPostProcessSteps
* returns, just one bit is set in aiMesh::mPrimitiveTypes. This is
* especially useful for real-time rendering where point and line
* primitives are often ignored or rendered separately.
* You can use the AI_CONFIG_PP_SBP_REMOVE option to specify which
* You can use the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> option to specify which
* primitive types you need. This can be used to easily exclude
* lines and points, which are rarely used, from the import.
*/
aiProcess_SortByPType = 0x8000,
// -------------------------------------------------------------------------
/** <hr>This step searches all meshes for degenerated primitives and
* converts them to proper lines or points.
*
* A face is degenerated if one or more of its points are identical.
* A face is 'degenerated' if one or more of its points are identical.
* To have the degenerated stuff not only detected and collapsed but
* also removed, try one of the following procedures:
* <br><b>1.</b> (if you support lines&points for rendering but don't
@ -224,7 +331,7 @@ enum aiPostProcessSteps
* <li>Specify the #aiProcess_FindDegenerates flag.
* </li>
* <li>Set the <tt>AI_CONFIG_PP_FD_REMOVE</tt> option to 1. This will
* cause the step to remove degenerated triangles rom the import
* cause the step to remove degenerated triangles from the import
* as soon as they're detected. They won't pass any further
* pipeline steps.
* </li>
@ -249,6 +356,7 @@ enum aiPostProcessSteps
*/
aiProcess_FindDegenerates = 0x10000,
// -------------------------------------------------------------------------
/** <hr>This step searches all meshes for invalid data, such as zeroed
* normal vectors or invalid UV coords and removes them.
*
@ -259,35 +367,88 @@ enum aiPostProcessSteps
*/
aiProcess_FindInvalidData = 0x20000,
// -------------------------------------------------------------------------
/** <hr>This step converts non-UV mappings (such as spherical or
* cylindrical) to proper UV mapping channels.
* cylindrical apping) to proper texture coordinate channels.
*
* Most applications will support UV mapping only, so you will
* probably want to specify this step in every case.
* probably want to specify this step in every case. Note tha Assimp is not
* always able to match the original mapping implementation of the
* 3d app which produced a model perfectly. It's always better to let the
* father app compute the UV channels, at least 3ds max, maja, blender,
* lightwave, modo, ... are able to achieve this.
*
* @note If this step is not requested, you'll need to process the
* <tt>#AI_MATKEY_MAPPING<7tt> material property in order to display all assets
* properly.
*/
aiProcess_GenUVCoords = 0x40000,
/** <hr>This step pre-transforms UV coordinates by the UV transformations
* (such as scalings or rotations).
// -------------------------------------------------------------------------
/** <hr>This step applies per-texture UV transformations and bakes
* them to stand-alone vtexture coordinate channelss.
*
* UV transformations are specified per-texture - see the
* AI_MATKEY_UVTRANSFORM key for more information on this topic.
* This step finds all textures with transformed input UV
* coordinates and generates a new, transformed, UV channel for it.
* Most applications won't support UV transformations, so you will
* probably want to specify this step in every case.
* todo ... rewrite doc
* <tt>#AI_MATKEY_UVTRANSFORM</tt> material key for more information.
* This step processes all textures with
* transformed input UV coordinates and generates new (pretransformed) UV channel
* which replace the old channel. Most applications won't support UV
* transformations, so you will probably want to specify this step.
*
* @note UV transformations are usually implemented in realtime apps by
* transforming texture coordinates at vertex shader stage with a 3x3
* (homogenous) transformation matrix.
*/
aiProcess_TransformUVCoords = 0x80000,
// -------------------------------------------------------------------------
/** <hr>This step searches for duplicate meshes and replaces duplicates
* with references to the first mesh.
*
* todo ... add more doc
* This step takes a while, don't use it if you have no time.
* It's main purpose is to workaround the limitation that many export
* file formats don't support instanced meshes, so exporters need to
* duplicate meshes. This step removes the duplicates again. Please
* note that Assimp does currently not support per-node material
* assignment to meshes, which means that identical meshes with
* differnent materials are currently *not* joined, although this is
* planned for future versions.
*/
aiProcess_FindInstances = 0x100000
aiProcess_FindInstances = 0x100000,
// -------------------------------------------------------------------------
/** <hr>This step flips all UV coordinates along the y-axis and adjusts
* material settings and bitangents accordingly.
* <br><b>Output UV coordinate system:</b>
* @code
* 0y|0y ---------- 1x|0y
* | |
* | |
* | |
* 0x|1y ---------- 1x|1y
* @endcode
*
* You'll probably want to consider this flag if you use Direct3D for
* rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
* setting and boundles all conversions typically required for D3D-based
* applications.
*/
aiProcess_FlipUVs = 0x80000000, /* don't change */
// -------------------------------------------------------------------------
/** <hr>This step adjusts the output face winding order to be clock-wise.
*
* The default face winding order is counter-clockwise.
* <br><b>Output face order:</b>
* @code
* x0
*
* x1
* x2
* @endcode
*/
aiProcess_FlipWindingOrder = 0x40000000 /* don't change */
// aiProcess_GenEntityMeshes = 0x100000,
@ -296,6 +457,23 @@ enum aiPostProcessSteps
};
// ---------------------------------------------------------------------------------------
/** @def aiProcess_ConvertToLeftHanded
* @brief Shortcut flag for Direct3D-based applications.
*
* Supersedes the #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
* #aiProcess_FlipWindingOrder flags. The output data matches Direct3D's conventions:
* left-handed geometry, upper-left origin for UV coordinates and finally clockwise
* face order, suitable for CCW culling.
*
* @deprecated
*/
#define aiProcess_ConvertToLeftHanded ( \
aiProcess_MakeLeftHanded | \
aiProcess_FlipUVs | \
0 )
// ---------------------------------------------------------------------------------------
/** @def aiProcessPreset_TargetRealtimeUse_Fast
* @brief Default postprocess configuration optimizing the data for real-time rendering.
@ -310,14 +488,14 @@ enum aiPostProcessSteps
* Some of them offer further configurable properties, some of them might not be of
* use for you so it might be better to not specify them.
*/
#define aiProcessPreset_TargetRealtime_Fast \
#define aiProcessPreset_TargetRealtime_Fast ( \
aiProcess_CalcTangentSpace | \
aiProcess_GenNormals | \
aiProcess_JoinIdenticalVertices | \
aiProcess_Triangulate | \
aiProcess_GenUVCoords | \
aiProcess_SortByPType | \
0
0 )
// ---------------------------------------------------------------------------------------
/** @def aiProcessPreset_TargetRealtime_Quality
@ -331,11 +509,11 @@ enum aiPostProcessSteps
* If you're using DirectX, don't forget to combine this value with
* the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
* in your application apply the #aiProcess_TransformUVCoords step, too.
* @note Please take the time to read the doc to the steps enabled by this preset.
* @note Please take the time to read the doc for the steps enabled by this preset.
* Some of them offer further configurable properties, some of them might not be of
* use for you so it might be better to not specify them.
*/
#define aiProcessPreset_TargetRealtime_Quality \
#define aiProcessPreset_TargetRealtime_Quality ( \
aiProcess_CalcTangentSpace | \
aiProcess_GenSmoothNormals | \
aiProcess_JoinIdenticalVertices | \
@ -348,7 +526,7 @@ enum aiPostProcessSteps
aiProcess_SortByPType | \
aiProcess_FindDegenerates | \
aiProcess_FindInvalidData | \
0
0 )
// ---------------------------------------------------------------------------------------
/** @def aiProcessPreset_TargetRealtime_MaxQuality
@ -360,16 +538,16 @@ enum aiPostProcessSteps
*
* If you're using DirectX, don't forget to combine this value with
* the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
* in your application apply the #aiProcess_TransformUVCoords step, too.
* @note Please take the time to read the doc to the steps enabled by this preset.
* in your application, apply the #aiProcess_TransformUVCoords step, too.
* @note Please take the time to read the doc for the steps enabled by this preset.
* Some of them offer further configurable properties, some of them might not be of
* use for you so it might be better to not specify them.
*/
#define aiProcessPreset_TargetRealtime_MaxQuality \
#define aiProcessPreset_TargetRealtime_MaxQuality ( \
aiProcessPreset_TargetRealtime_Quality | \
aiProcess_FindInstances | \
aiProcess_ValidateDataStructure | \
0
0 )
#ifdef __cplusplus

View File

@ -221,10 +221,10 @@ void SceneAnimator::UpdateTransforms( SceneAnimNode* pNode, const std::vector<ai
{
ai_assert( pNode->mChannelIndex < pTransforms.size());
pNode->mLocalTransform = pTransforms[pNode->mChannelIndex];
}
// update global transform as well
CalculateGlobalTransform( pNode);
}
// continue for all children
for( std::vector<SceneAnimNode*>::iterator it = pNode->mChildren.begin(); it != pNode->mChildren.end(); ++it)

View File

@ -2255,10 +2255,6 @@
RelativePath="..\..\code\ValidateDataStructure.h"
>
</File>
<Filter
Name="util"
>
</Filter>
</Filter>
<Filter
Name="PCH"