General
- 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-9d2fd5bffc1fpull/1/head
parent
68d7e43056
commit
c2d8881549
|
@ -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
|
@ -1889,18 +1889,20 @@ 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];
|
||||
if (index == face.mIndices[0])
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
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)
|
||||
void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
|
||||
{
|
||||
for (unsigned int a = 0; a < mat->mNumProperties;++a)
|
||||
{
|
||||
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"))
|
||||
{
|
||||
ai_assert( prop->mDataLength >= sizeof(aiUVTransform));
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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" )
|
||||
{
|
||||
curNode->sphereRadius = prop.value;
|
||||
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,51 +1272,33 @@ 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");
|
||||
const std::string extension = GetExtension(prop.value);
|
||||
if ("irr" == extension) {
|
||||
DefaultLogger::get()->error("IRR: Can't load another IRR file recursively");
|
||||
}
|
||||
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)
|
||||
{
|
||||
DefaultLogger::get()->error("IRR: Can't load another IRR file recursively");
|
||||
}
|
||||
else
|
||||
{
|
||||
curNode->id = batch.AddLoadRequest(prop.value,pp,&map);
|
||||
curNode->meshPath = prop.value;
|
||||
}
|
||||
curNode->id = batch.AddLoadRequest(prop.value,pp,&map);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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. );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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++)
|
||||
{
|
||||
|
@ -413,9 +413,9 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
|
|||
for( unsigned int a = 0; a < pData->mAnims.size(); a++)
|
||||
{
|
||||
const XFile::Animation* anim = pData->mAnims[a];
|
||||
// some exporters mock me with empty animation tags.
|
||||
if( anim->mAnims.size() == 0)
|
||||
continue;
|
||||
// some exporters mock me with empty animation tags.
|
||||
if( anim->mAnims.size() == 0)
|
||||
continue;
|
||||
|
||||
// create a new animation to hold the data
|
||||
aiAnimation* nanim = new aiAnimation;
|
||||
|
@ -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.
|
@ -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.
|
||||
|
|
82
doc/dox.h
82
doc/dox.h
|
@ -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->Extras->Options->Projects and Solutions->VC++ Directories->Include files)
|
||||
and the Assimp/lib/<Compiler> path to your linker paths (Menu->Extras->Options->Projects and Solutions->VC++ Directories->Library files).
|
||||
and the ASSIMP/lib/<Compiler> path to your linker paths (Menu->Extras->Options->Projects and Solutions->VC++ Directories->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 <assimp.hpp> or <assimp.h> plus some others starting with <aiTypes.h>.
|
||||
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
* 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
|
||||
* 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.
|
||||
* The components to be removed are specified in a separate
|
||||
* 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 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.
|
||||
*
|
||||
* If you intend to perform the skinning in hardware, this post processing step
|
||||
* might be of interest for you.
|
||||
* 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 <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).
|
||||
*
|
||||
* 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
|
||||
// -------------------------------------------------------------------------
|
||||
/** <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
|
||||
* <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,
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** <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_FindInstances = 0x100000
|
||||
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
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -221,11 +221,11 @@ 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);
|
||||
}
|
||||
|
||||
// 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)
|
||||
UpdateTransforms( *it, pTransforms);
|
||||
|
|
|
@ -2255,10 +2255,6 @@
|
|||
RelativePath="..\..\code\ValidateDataStructure.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="util"
|
||||
>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="PCH"
|
||||
|
|
Loading…
Reference in New Issue