Fixed third-person camera movement bug in the viewer.

Fixed a bug that caused the viewer to render "random" polygons in some special cases. 
ASE: Added parsing support for *GROUP nodes. Improved light & camera handling (still WIP). Fixed a bug that was caused by a recent change. Improved logging.
Updated PretransformVertices. The step works now (and supports line and point meshes). Important: The position of the step in the pipeline has changed. No unit test yet.
Minor fixes to SortByPType. Added a config option that allows users to specify which primitive types they don't need. 
Added WIP version of an Irrlicht Scene Loader (.irr).
Added a small helper class ("BatchLoader") to make it easy for loaders to load subsequent meshes from external files (needed for irr and lws).
Added test models for IRR. Added dwarf.x from the Irrlicht repository (readme included) to the test X files.
[Current TODO: Fix bugs in: AC, 3DS, LWO. Finish MDR and OG. Implement: IRR, LWS. Write some more ut's ... ]

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@197 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2008-10-27 00:36:26 +00:00
parent a62b94079f
commit 3d3b9719f8
39 changed files with 19979 additions and 323 deletions

View File

@ -78,20 +78,22 @@ bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
return false; return false;
std::string extension = pFile.substr( pos); std::string extension = pFile.substr( pos);
if (extension.length() < 4)return false; // Either ASE or ASK
if (extension[0] != '.')return false; return !(extension.length() < 4 || extension[0] != '.' ||
extension[1] != 'a' && extension[1] != 'A' ||
if (extension[1] != 'a' && extension[1] != 'A')return false; extension[2] != 's' && extension[2] != 'S' ||
if (extension[2] != 's' && extension[2] != 'S')return false; extension[3] != 'e' && extension[3] != 'E' &&
extension[3] != 'k' && extension[3] != 'K');
// NOTE: Sometimes the extension .ASK is also used
// however, it often contains static animation skeletons
// only (without real animations).
if (extension[3] != 'e' && extension[3] != 'E' &&
extension[3] != 'k' && extension[3] != 'K')return false;
return true;
} }
// ------------------------------------------------------------------------------------------------
// Setup configuration options
void ASEImporter::SetupProperties(const Importer* pImp)
{
configRecomputeNormals = (pImp->GetPropertyInteger(
AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,0) ? true : false);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void ASEImporter::InternReadFile( void ASEImporter::InternReadFile(
@ -125,6 +127,7 @@ void ASEImporter::InternReadFile(
GenerateDefaultMaterial(); GenerateDefaultMaterial();
// process all meshes // process all meshes
bool tookNormals = false;
std::vector<aiMesh*> avOutMeshes; std::vector<aiMesh*> avOutMeshes;
avOutMeshes.reserve(mParser->m_vMeshes.size()*2); avOutMeshes.reserve(mParser->m_vMeshes.size()*2);
for (std::vector<ASE::Mesh>::iterator for (std::vector<ASE::Mesh>::iterator
@ -140,11 +143,17 @@ void ASEImporter::InternReadFile(
BuildUniqueRepresentation(*i); BuildUniqueRepresentation(*i);
// need to generate proper vertex normals if necessary // need to generate proper vertex normals if necessary
GenerateNormals(*i); if(GenerateNormals(*i))tookNormals = true;
// convert all meshes to aiMesh objects // convert all meshes to aiMesh objects
ConvertMeshes(*i,avOutMeshes); ConvertMeshes(*i,avOutMeshes);
} }
if (tookNormals)
{
DefaultLogger::get()->debug("ASE: Taking normals from the file. Use "
"the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS option if you "
"experience problems");
}
// now build the output mesh list. remove dummies // now build the output mesh list. remove dummies
pScene->mNumMeshes = (unsigned int)avOutMeshes.size(); pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
@ -192,15 +201,15 @@ void ASEImporter::GenerateDefaultMaterial()
} }
if (bHas || mParser->m_vMaterials.empty()) if (bHas || mParser->m_vMaterials.empty())
{ {
// add a simple material without sub materials to the parser's list // add a simple material without submaterials to the parser's list
mParser->m_vMaterials.push_back ( ASE::Material() ); mParser->m_vMaterials.push_back ( ASE::Material() );
ASE::Material& mat = mParser->m_vMaterials.back(); ASE::Material& mat = mParser->m_vMaterials.back();
mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f); mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f);
mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f); mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f); mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
mat.mShading = Dot3DSFile::Gouraud; mat.mShading = Dot3DSFile::Gouraud;
mat.mName = AI_DEFAULT_MATERIAL_NAME; mat.mName = AI_DEFAULT_MATERIAL_NAME;
} }
} }
@ -295,7 +304,7 @@ void ASEImporter::BuildCameras()
// copy members // copy members
out->mClipPlaneFar = in.mFar; out->mClipPlaneFar = in.mFar;
out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f); out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f);
out->mHorizontalFOV = AI_RAD_TO_DEG( in.mFOV ); out->mHorizontalFOV = in.mFOV;
out->mName.Set(in.mName); out->mName.Set(in.mName);
} }
@ -317,6 +326,7 @@ void ASEImporter::BuildLights()
out->mName.Set(in.mName); out->mName.Set(in.mName);
out->mType = aiLightSource_POINT; out->mType = aiLightSource_POINT;
out->mColorDiffuse = out->mColorSpecular = in.mColor * in.mIntensity;
} }
} }
} }
@ -329,6 +339,64 @@ void ASEImporter::AddNodes(std::vector<BaseNode*>& nodes,
this->AddNodes(nodes,pcParent,szName,m); this->AddNodes(nodes,pcParent,szName,m);
} }
// ------------------------------------------------------------------------------------------------
void ASEImporter::AddMeshes(const ASE::BaseNode* snode,aiNode* node)
{
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
{
// Get the name of the mesh (the mesh instance has been temporarily
// stored in the third vertex color)
const aiMesh* pcMesh = pcScene->mMeshes[i];
const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
if (mesh == snode)++node->mNumMeshes;
}
if(node->mNumMeshes)
{
node->mMeshes = new unsigned int[node->mNumMeshes];
for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes;++i)
{
const aiMesh* pcMesh = pcScene->mMeshes[i];
const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
if (mesh == snode)
{
node->mMeshes[p++] = i;
// Transform all vertices of the mesh back into their local space ->
// at the moment they are pretransformed
aiMatrix4x4 m = mesh->mTransform;
m.Inverse();
aiVector3D* pvCurPtr = pcMesh->mVertices;
const aiVector3D* pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
while (pvCurPtr != pvEndPtr)
{
*pvCurPtr = m * (*pvCurPtr);
pvCurPtr++;
}
// Do the same for the normal vectors if we have them
// Here we need to use the (Inverse)Transpose of a 3x3
// matrix without the translational component.
if (pcMesh->mNormals)
{
aiMatrix3x3 m3 = aiMatrix3x3( mesh->mTransform );
m3.Transpose();
pvCurPtr = pcMesh->mNormals;
pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
while (pvCurPtr != pvEndPtr)
{
*pvCurPtr = m3 * (*pvCurPtr);
pvCurPtr++;
}
}
}
}
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes (std::vector<BaseNode*>& nodes, void ASEImporter::AddNodes (std::vector<BaseNode*>& nodes,
aiNode* pcParent, const char* szName, aiNode* pcParent, const char* szName,
@ -375,64 +443,17 @@ void ASEImporter::AddNodes (std::vector<BaseNode*>& nodes,
// be used when this code is refactored next. // be used when this code is refactored next.
if (snode->mType == BaseNode::Mesh) if (snode->mType == BaseNode::Mesh)
{ {
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) AddMeshes(snode,node);
{
// Get the name of the mesh (the mesh instance has been temporarily
// stored in the third vertex color)
const aiMesh* pcMesh = pcScene->mMeshes[i];
const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
if (mesh == snode)++node->mNumMeshes;
}
if(node->mNumMeshes)
{
node->mMeshes = new unsigned int[node->mNumMeshes];
for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes;++i)
{
const aiMesh* pcMesh = pcScene->mMeshes[i];
const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
if (mesh == snode)
{
node->mMeshes[p++] = i;
// Transform all vertices of the mesh back into their local space ->
// at the moment they are pretransformed
mParentAdjust = mesh->mTransform;
mParentAdjust.Inverse();
aiVector3D* pvCurPtr = pcMesh->mVertices;
const aiVector3D* pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
while (pvCurPtr != pvEndPtr)
{
*pvCurPtr = mParentAdjust * (*pvCurPtr);
pvCurPtr++;
}
// Do the same for the normal vectors if we have them
// Here we need to use the (Inverse)Transpose of a 3x3
// matrix without the translational component.
if (pcMesh->mNormals)
{
aiMatrix3x3 m3 = aiMatrix3x3( mesh->mTransform );
m3.Transpose();
pvCurPtr = pcMesh->mNormals;
pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
while (pvCurPtr != pvEndPtr)
{
*pvCurPtr = m3 * (*pvCurPtr);
pvCurPtr++;
}
}
}
}
}
} }
// add sub nodes // add sub nodes
aiMatrix4x4 mNewAbs = mat * node->mTransformation; aiMatrix4x4 mNewAbs = mat * node->mTransformation;
AddNodes(nodes,node,node->mName.data,mNewAbs);
// prevent stack overflow
if (node->mName != node->mParent->mName)
{
AddNodes(nodes,node,node->mName.data,mNewAbs);
}
} }
// allocate enough space for the child nodes // allocate enough space for the child nodes
@ -493,7 +514,7 @@ void ASEImporter::BuildNodes()
{ {
if (it2 == it)continue; if (it2 == it)continue;
if ((*it2)->mParent == (*it)->mName) if ((*it2)->mName == (*it)->mParent)
{ {
bKnowParent = true; bKnowParent = true;
break; break;
@ -521,17 +542,12 @@ void ASEImporter::BuildNodes()
{ {
const ASE::BaseNode* src = *i; const ASE::BaseNode* src = *i;
/*
DefaultLogger::get()->info("Generating dummy node: " + src->mName + ". "
"This node is not defined in the ASE file, but referenced as "
"parent node");
*/
// the parent is not known, so we can assume that we must add // the parent is not known, so we can assume that we must add
// this node to the root node of the whole scene // this node to the root node of the whole scene
aiNode* pcNode = new aiNode(); aiNode* pcNode = new aiNode();
pcNode->mParent = pcScene->mRootNode; pcNode->mParent = pcScene->mRootNode;
pcNode->mName.Set(src->mName); pcNode->mName.Set(src->mName);
AddMeshes(src,pcNode);
AddNodes(nodes,pcNode,pcNode->mName.data); AddNodes(nodes,pcNode,pcNode->mName.data);
apcNodes.push_back(pcNode); apcNodes.push_back(pcNode);
} }
@ -1252,9 +1268,9 @@ void ASEImporter::BuildMaterialIndices()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Generate normal vectors basing on smoothing groups // Generate normal vectors basing on smoothing groups
void ASEImporter::GenerateNormals(ASE::Mesh& mesh) bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)
{ {
if (!mesh.mNormals.empty()) if (!mesh.mNormals.empty() && !configRecomputeNormals)
{ {
// check whether there are only uninitialized normals. If there are // check whether there are only uninitialized normals. If there are
// some, skip all normals from the file and compute them on our own // some, skip all normals from the file and compute them on our own
@ -1264,14 +1280,11 @@ void ASEImporter::GenerateNormals(ASE::Mesh& mesh)
{ {
if ((*qq).x || (*qq).y || (*qq).z) if ((*qq).x || (*qq).y || (*qq).z)
{ {
DefaultLogger::get()->debug("Using normal vectors from the ASE file. They are sometimes crappy"); return true;
return;
} }
} }
mesh.mNormals.clear();
}
if (mesh.mNormals.empty())
{
ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh);
} }
// The array will be reused
ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh);
return false;
} }

View File

@ -93,12 +93,20 @@ protected:
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.
*/
void SetupProperties(const Importer* pImp);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate normal vectors basing on smoothing groups /** Generate normal vectors basing on smoothing groups
* (in some cases the normal are already contained in the file) * (in some cases the normal are already contained in the file)
* \param mesh Mesh to work on * \param mesh Mesh to work on
* \return false if the normals have been recomputed
*/ */
void GenerateNormals(ASE::Mesh& mesh); bool GenerateNormals(ASE::Mesh& mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Create valid vertex/normal/UV/color/face lists. /** Create valid vertex/normal/UV/color/face lists.
@ -164,6 +172,8 @@ protected:
aiNode* pcParent,const char* szName, aiNode* pcParent,const char* szName,
const aiMatrix4x4& matrix); const aiMatrix4x4& matrix);
void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate a default material and add it to the parser's list /** Generate a default material and add it to the parser's list
* Called if no material has been found in the file (rare for ASE, * Called if no material has been found in the file (rare for ASE,
@ -181,6 +191,10 @@ protected:
/** Scene to be filled */ /** Scene to be filled */
aiScene* pcScene; aiScene* pcScene;
/** Config options: Recompute the normals in every case - WA
for 3DS Max broken ASE normal export */
bool configRecomputeNormals;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -254,6 +254,12 @@ void Parser::Parse()
ParseLV1SceneBlock(); ParseLV1SceneBlock();
continue; continue;
} }
// "group"
if (TokenMatch(m_szFile,"GROUP",5))
{
Parse();
continue;
}
// material list // material list
if (TokenMatch(m_szFile,"MATERIAL_LIST",13)) if (TokenMatch(m_szFile,"MATERIAL_LIST",13))
{ {

View File

@ -139,4 +139,124 @@ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler,
} }
// ------------------------------------------------------------------------------------------------
struct LoadRequest
{
LoadRequest(const std::string& _file, unsigned int _flags)
: file (_file)
, flags (_flags)
, scene (NULL)
, refCnt (1)
, loaded (false)
{}
const std::string file;
unsigned int flags;
unsigned int refCnt;
aiScene* scene;
bool loaded;
bool operator== (const std::string& f)
{return file == f;}
};
struct BatchData
{
// IO system to be used for all imports
IOSystem* pIOSystem;
// Importer used to load all meshes
Importer* pImporter;
// List of all imports
std::list<LoadRequest> requests;
};
// ------------------------------------------------------------------------------------------------
BatchLoader::BatchLoader(IOSystem* pIO)
{
ai_assert(NULL != pIO);
pimpl = new BatchData();
BatchData* data = ( BatchData* )pimpl;
data->pIOSystem = pIO;
data->pImporter = new Importer();
}
// ------------------------------------------------------------------------------------------------
BatchLoader::~BatchLoader()
{
// delete all scenes wthat have not been polled by the user
BatchData* data = ( BatchData* )pimpl;
for (std::list<LoadRequest>::iterator it = data->requests.begin();
it != data->requests.end(); ++it)
{
delete (*it).scene;
}
delete data->pImporter;
delete data;
}
// ------------------------------------------------------------------------------------------------
void BatchLoader::AddLoadRequest (const std::string& file)
{
// no threaded implementation for the moment
BatchData* data = ( BatchData* )pimpl;
std::list<LoadRequest>::iterator it = std::find(data->requests.begin(),
data->requests.end(), file);
if (it != data->requests.end())
{
(*it).refCnt++;
return;
}
data->requests.push_back(LoadRequest(file,0));
}
// ------------------------------------------------------------------------------------------------
aiScene* BatchLoader::GetImport (const std::string& file)
{
// no threaded implementation for the moment
BatchData* data = ( BatchData* )pimpl;
std::list<LoadRequest>::iterator it = std::find(data->requests.begin(),
data->requests.end(), file);
if (it != data->requests.end() && (*it).loaded)
{
aiScene* sc = (*it).scene;
if (!(--(*it).refCnt))
{
data->requests.erase(it);
}
return sc;
}
return NULL;
}
// ------------------------------------------------------------------------------------------------
void BatchLoader::LoadAll()
{
BatchData* data = ( BatchData* )pimpl;
// no threaded implementation for the moment
for (std::list<LoadRequest>::iterator it = data->requests.begin();
it != data->requests.end(); ++it)
{
// no postprocessing for the moment except validation
// in debug builds
unsigned int pp = 0;
#ifdef _DEBUG
pp |= aiProcess_ValidateDataStructure;
#endif
data->pImporter->ReadFile((*it).file,pp);
(*it).scene = const_cast<aiScene*>(data->pImporter->GetOrphanedScene());
(*it).loaded = true;
}
}

View File

@ -215,12 +215,77 @@ protected:
unsigned int numTokens, unsigned int numTokens,
unsigned int searchBytes = 200); unsigned int searchBytes = 200);
#if 0 /** TODO **/
// -------------------------------------------------------------------
/** An utility for all text file loaders. It converts a file to our
* ASCII/UTF8 character set. Special unicode characters are lost.
*
* @param buffer Input buffer. Needn't be terminated with zero.
* @param length Length of the input buffer, in bytes. Receives the
* number of output characters, excluding the terminal char.
* @return true if the source format did not match our internal
* format so it was converted.
*/
static bool ConvertToUTF8(const char* buffer,
unsigned int& length);
#endif
protected: protected:
/** Error description in case there was one. */ /** Error description in case there was one. */
std::string mErrorText; std::string mErrorText;
}; };
// ---------------------------------------------------------------------------
/** A helper class that can be used by importers which need to load many
* extern meshes recursively.
*
* The class uses several threads to load these meshes (or at least it
* could, this has not yet been implemented at the moment).
*
* @note The class may not be used by more than one thread
*/
class ASSIMP_API BatchLoader
{
public:
/** Construct a batch loader from a given IO system
*/
BatchLoader(IOSystem* pIO);
~BatchLoader();
/** Add a new file to the list of files to be loaded.
*
* No postprocessing steps are executed on the file
* @param file File to be loaded
*/
void AddLoadRequest (const std::string& file);
/** Get an imported scene.
*
* This polls the import from the internal request list.
* If an import is requested several times, this function
* can be called several times, too.
*
* @param file File name of the scene
* @return NULL if there is no scene with this file name
* in the queue of the scene hasn't been loaded yet.
*/
aiScene* GetImport (const std::string& file);
/** Waits until all scenes have been loaded.
*/
void LoadAll();
private:
// No need to have that in the public API ...
void* pimpl;
};
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -78,8 +78,7 @@ bool ConvertToLHProcess::IsActive( unsigned int pFlags) const
{ {
if (pFlags & aiProcess_ConvertToLeftHanded) if (pFlags & aiProcess_ConvertToLeftHanded)
{ {
if (pFlags & aiProcess_PreTransformVertices) bTransformVertices = (0 != (pFlags & aiProcess_PreTransformVertices) ? true : false);
this->bTransformVertices = true;
return true; return true;
} }
return false; return false;
@ -99,25 +98,28 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
DefaultLogger::get()->debug("ConvertToLHProcess begin"); DefaultLogger::get()->debug("ConvertToLHProcess begin");
// transform vertex by vertex or change the root transform? // transform vertex by vertex or change the root transform?
if (this->bTransformVertices) // 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)
{ {
this->bTransformVertices = false;
aiMatrix4x4 mTransform; aiMatrix4x4 mTransform;
this->ConvertToDX(mTransform); ConvertToDX(mTransform);
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{ {
aiMesh* pcMesh = pScene->mMeshes[i]; aiMesh* pcMesh = pScene->mMeshes[i];
// transform all vertices
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
{ pcMesh->mVertices[n] = mTransform * pcMesh->mVertices[n];
pcMesh->mVertices[n] = mTransform * pcMesh->mVertices[n];
} // transform all normals
if (pcMesh->HasNormals()) if (pcMesh->HasNormals())
{ {
mTransform.Inverse().Transpose(); mTransform.Inverse().Transpose();
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
{ pcMesh->mNormals[n] = mTransform * pcMesh->mNormals[n];
pcMesh->mNormals[n] = mTransform * pcMesh->mNormals[n];
}
} }
} }
} }

View File

@ -141,7 +141,7 @@ void FindDegeneratesProcess::Execute( aiScene* pScene)
break; break;
}; };
} }
if (deg) if (deg && !DefaultLogger::isNullLogger())
{ {
char s[64]; char s[64];
itoa10(s,deg); itoa10(s,deg);

424
code/IRRLoader.cpp 100644
View File

@ -0,0 +1,424 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (ASSIMP)
---------------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the Irr importer class */
#include "AssimpPCH.h"
#include "IRRLoader.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
#include "StandardShapes.h"
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// 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.
bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
{
/* NOTE: A simple check for the file extension is not enough
* here. Irrmesh and irr are easy, but xml is too generic
* and could be collada, too. So we need to open the file and
* search for typical tokens.
*/
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)
return false;
std::string extension = pFile.substr( pos);
for (std::string::iterator i = extension.begin(); i != extension.end();++i)
*i = ::tolower(*i);
if (extension == ".irr")return true;
else if (extension == ".xml")
{
/* If CanRead() is called to check whether the loader
* supports a specific file extension in general we
* must return true here.
*/
if (!pIOHandler)return true;
const char* tokens[] = {"irr_scene"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void IRRImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file
if( file.get() == NULL)
throw new ImportErrorException( "Failed to open IRR file " + pFile + "");
// Construct the irrXML parser
CIrrXML_IOStreamReader st(file.get());
reader = createIrrXMLReader((IFileReadCallBack*) &st);
// The root node of the scene
Node* root = new Node(Node::DUMMY);
root->parent = NULL;
// Current node parent
Node* curParent = root;
// Scenegraph node we're currently working on
Node* curNode = NULL;
// List of output cameras
std::vector<aiCamera*> cameras;
// List of output lights
std::vector<aiLight*> lights;
// List of output meshes
std::vector<aiMesh*> meshes;
// List of output animation channels
std::vector<aiNodeAnim*> animations;
BatchLoader batch(pIOHandler);
cameras.reserve(5);
lights.reserve(5);
animations.reserve(5);
meshes.reserve(5);
bool inMaterials = false;
// Parse the XML file
while (reader->read())
{
switch (reader->getNodeType())
{
case EXN_ELEMENT:
if (!ASSIMP_stricmp(reader->getNodeName(),"node"))
{
/* What we're going to do with the node depends
* on its type:
*
* "mesh" - Load a mesh from an external file
* "cube" - Generate a cube
* "skybox" - Generate a skybox
* "light" - A light source
* "sphere" - Generate a sphere mesh
* "animatedMesh" - Load an animated mesh from an external file
* and join its animation channels with ours.
* "empty" - A dummy node
* "camera" - A camera
*
* Each of these nodes can be animated.
*/
const char* sz = reader->getAttributeValueSafe("type");
Node* nd;
if (!ASSIMP_stricmp(sz,"mesh"))
{
nd = new Node(Node::MESH);
}
else if (!ASSIMP_stricmp(sz,"cube"))
{
nd = new Node(Node::CUBE);
meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
}
else if (!ASSIMP_stricmp(sz,"skybox"))
{
nd = new Node(Node::SKYBOX);
}
else if (!ASSIMP_stricmp(sz,"camera"))
{
nd = new Node(Node::CAMERA);
// Setup a temporary name for the camera
aiCamera* cam = new aiCamera();
cam->mName.Set( nd->name );
cameras.push_back(cam);
}
else if (!ASSIMP_stricmp(sz,"light"))
{
nd = new Node(Node::LIGHT);
// Setup a temporary name for the light
aiLight* cam = new aiLight();
cam->mName.Set( nd->name );
lights.push_back(cam);
}
else if (!ASSIMP_stricmp(sz,"sphere"))
{
nd = new Node(Node::SPHERE);
}
else if (!ASSIMP_stricmp(sz,"animatedMesh"))
{
nd = new Node(Node::ANIMMESH);
}
else if (!ASSIMP_stricmp(sz,"empty"))
{
nd = new Node(Node::DUMMY);
}
else
{
DefaultLogger::get()->warn("IRR: Found unknown node: " + std::string(sz));
/* We skip the contents of nodes we don't know.
* We parse the transformation and all animators
* and skip the rest.
*/
nd = new Node(Node::DUMMY);
}
/* Attach the newly created node to the scenegraph
*/
curNode = nd;
nd->parent = curParent;
curParent->children.push_back(nd);
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"materials"))
{
inMaterials = true;
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes"))
{
/* We should have a valid node here
*/
if (!curNode)
{
DefaultLogger::get()->error("IRR: Encountered <attributes> element, but "
"there is no node active");
continue;
}
if (inMaterials && curNode->type == Node::ANIMMESH ||
curNode->type == Node::MESH )
{
/* This is a material description - parse it!
*/
curNode->materials.push_back(std::pair< aiMaterial*, unsigned int > () );
std::pair< aiMaterial*, unsigned int >& p = curNode->materials.back();
p.first = ParseMaterial(p.second);
continue;
}
/* Parse all elements in the attributes block
* and process them.
*/
while (reader->read())
{
if (reader->getNodeType() == EXN_ELEMENT)
{
if (!ASSIMP_stricmp(reader->getNodeName(),"vector3d"))
{
VectorProperty prop;
ReadVectorProperty(prop);
// Convert to our coordinate system
std::swap( (float&)prop.value.z, (float&)prop.value.y );
prop.value.y *= -1.f;
if (prop.name == "Position")
{
curNode->position = prop.value;
}
else if (prop.name == "Rotation")
{
curNode->rotation = prop.value;
}
else if (prop.name == "Scale")
{
curNode->scaling = prop.value;
}
else if (Node::CAMERA == curNode->type)
{
aiCamera* cam = cameras.back();
if (prop.name == "Target")
{
cam->mLookAt = prop.value;
}
else if (prop.name == "UpVector")
{
cam->mUp = prop.value;
}
}
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"float"))
{
FloatProperty prop;
ReadFloatProperty(prop);
if (prop.name == "FramesPerSecond" &&
Node::ANIMMESH == curNode->type)
{
curNode->framesPerSecond = prop.value;
}
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")
{
cameras.back()->mHorizontalFOV = prop.value;
}
else if (prop.name == "Aspect")
{
cameras.back()->mAspect = prop.value;
}
else if (prop.name == "ZNear")
{
cameras.back()->mClipPlaneNear = prop.value;
}
else if (prop.name == "ZFar")
{
cameras.back()->mClipPlaneFar = prop.value;
}
}
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"string"))
{
StringProperty prop;
ReadStringProperty(prop);
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)
{
cameras.back()->mName.Set(prop.value);
}
else if (Node::LIGHT == curNode->type)
{
lights.back()->mName.Set(prop.value);
}
}
else if (prop.name == "Mesh" && Node::MESH == curNode->type ||
Node::ANIMMESH == curNode->type)
{
/* This is the file name of the mesh - either
* animated or not. We don't need any postprocessing
* steps here. However, it would be useful it we'd
* be able to use RemoveVC to remove animations
* if this isn't an animated mesh. But that's not
* possible at the moment.
*/
batch.AddLoadRequest(prop.value);
}
}
}
}
else if (reader->getNodeType() == EXN_ELEMENT_END &&
!ASSIMP_stricmp(reader->getNodeName(),"attributes"))
{
break;
}
}
}
break;
case EXN_ELEMENT_END:
if (!ASSIMP_stricmp(reader->getNodeName(),"node"))
{
if (!curNode)
{
// currently is no node set. We need to go
// back in the node hierarchy
curParent = curParent->parent;
if (!curParent)
{
curParent = root;
DefaultLogger::get()->error("IRR: Too many closing <node> elements");
}
}
else curNode = NULL;
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"materials"))
{
inMaterials = false;
}
break;
default:
// GCC complains that not all enumeration values are handled
break;
}
}
/* 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)
{
aiCamera* cam = *it;
if (cam->mAspect) // screen aspect could be missing
{
cam->mHorizontalFOV *= cam->mAspect;
}
else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV");
}
}

168
code/IRRLoader.h 100644
View File

@ -0,0 +1,168 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file Declaration of the .irrMesh (Irrlight Engine Mesh Format)
importer class. */
#ifndef AI_IRRLOADER_H_INCLUDED
#define AI_IRRLOADER_H_INCLUDED
#include "IRRMeshLoader.h"
namespace Assimp {
// ---------------------------------------------------------------------------
/** Irr importer class.
*
* Irr is the native scene file format of the Irrlight engine and its editor
* irrEdit. As IrrEdit itself is capable of importing quite many file formats,
* it might be a good file format for data exchange.
*/
class IRRImporter : public BaseImporter, public IrrlichtBase
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
IRRImporter();
/** Destructor, private as well */
~IRRImporter();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
*/
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
protected:
// -------------------------------------------------------------------
/** Called by Importer::GetExtensionList() for each loaded importer.
* See BaseImporter::GetExtensionList() for details
*/
void GetExtensionList(std::string& append)
{
/* NOTE: The file extenxsion .xml is too generic. We'll
* need to open the file in CanRead() and check whether it is
* a real irrlicht file
*/
append.append("*.xml;*.irr");
}
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private:
/** Data structure for a scenegraph node in an IRR file
*/
struct Node
{
// Type of the node
enum ET
{
LIGHT,
CUBE,
MESH,
SKYBOX,
DUMMY,
CAMERA,
TERRAIN,
SPHERE,
ANIMMESH
} type;
Node(ET t)
: type (t)
, scaling (1.f,1.f,1.f) // assume uniform scaling by default
, animation (NULL)
, framesPerSecond (0.f)
{
// Generate a default name for the node
char buffer[128];
static int cnt;
::sprintf(buffer,"IrrNode_%i",cnt++);
name = std::string(buffer);
// reserve space for up to 5 materials
materials.reserve(5);
// reserve space for up to 5 children
children.reserve(5);
}
// Transformation of the node
aiVector3D position, rotation, scaling;
// Name of the node
std::string name;
// List of all child nodes
std::vector<Node*> children;
// Parent node
Node* parent;
// Animation channels that belongs to this node
aiNodeAnim* animation;
// Animated meshes: frames per second
// 0.f if not specified
float framesPerSecond;
//! Meshes: List of materials to be assigned
//! along with their corresponding material flags
std::vector< std::pair<aiMaterial*, unsigned int> > materials;
};
};
} // end of namespace Assimp
#endif // AI_IRRIMPORTER_H_INC

View File

@ -50,58 +50,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
/**** AT FIRST: IrrlightBase, base class for IrrMesh and Irr *******/
// ------------------------------------------------------------------------------------------------
// 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.
bool IRRMeshImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
{
/* NOTE: A simple check for the file extension is not enough
* here. Irrmesh and irr are easy, but xml is too generic
* and could be collada, too. So we need to open the file and
* search for typical tokens.
*/
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)
return false;
std::string extension = pFile.substr( pos);
for (std::string::iterator i = extension.begin(); i != extension.end();++i)
*i = ::tolower(*i);
if (extension == ".irrmesh")return true;
else if (extension == ".xml")
{
/* If CanRead() is called to check whether the loader
* supports a specific file extension in general we
* must return true here.
*/
if (!pIOHandler)return true;
const char* tokens[] = {"irrlicht","irrmesh"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
}
return false;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a property in hexadecimal format (i.e. ffffffff) // read a property in hexadecimal format (i.e. ffffffff)
void IRRMeshImporter::ReadHexProperty (HexProperty& out) void IrrlichtBase::ReadHexProperty (HexProperty& out)
{ {
for (int i = 0; i < reader->getAttributeCount();++i) for (int i = 0; i < reader->getAttributeCount();++i)
{ {
@ -119,7 +72,7 @@ void IRRMeshImporter::ReadHexProperty (HexProperty& out)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a string property // read a string property
void IRRMeshImporter::ReadStringProperty (StringProperty& out) void IrrlichtBase::ReadStringProperty (StringProperty& out)
{ {
for (int i = 0; i < reader->getAttributeCount();++i) for (int i = 0; i < reader->getAttributeCount();++i)
{ {
@ -137,7 +90,7 @@ void IRRMeshImporter::ReadStringProperty (StringProperty& out)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a boolean property // read a boolean property
void IRRMeshImporter::ReadBoolProperty (BoolProperty& out) void IrrlichtBase::ReadBoolProperty (BoolProperty& out)
{ {
for (int i = 0; i < reader->getAttributeCount();++i) for (int i = 0; i < reader->getAttributeCount();++i)
{ {
@ -156,7 +109,7 @@ void IRRMeshImporter::ReadBoolProperty (BoolProperty& out)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a float property // read a float property
void IRRMeshImporter::ReadFloatProperty (FloatProperty& out) void IrrlichtBase::ReadFloatProperty (FloatProperty& out)
{ {
for (int i = 0; i < reader->getAttributeCount();++i) for (int i = 0; i < reader->getAttributeCount();++i)
{ {
@ -166,12 +119,47 @@ void IRRMeshImporter::ReadFloatProperty (FloatProperty& out)
} }
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
{ {
// true or false, case insensitive // just parse the float
out.value = fast_atof( reader->getAttributeValue(i) ); out.value = fast_atof( reader->getAttributeValue(i) );
} }
} }
} }
// ------------------------------------------------------------------------------------------------
// read a vector property
void IrrlichtBase::ReadVectorProperty (VectorProperty& out)
{
for (int i = 0; i < reader->getAttributeCount();++i)
{
if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
{
out.name = std::string( reader->getAttributeValue(i) );
}
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
{
// three floats, separated with commas
const char* ptr = reader->getAttributeValue(i);
SkipSpaces(&ptr);
ptr = fast_atof_move( ptr,(float&)out.value.x );
SkipSpaces(&ptr);
if (',' != *ptr)
{
DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
}
else SkipSpaces(ptr+1,&ptr);
ptr = fast_atof_move( ptr,(float&)out.value.y );
SkipSpaces(&ptr);
if (',' != *ptr)
{
DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
}
else SkipSpaces(ptr+1,&ptr);
ptr = fast_atof_move( ptr,(float&)out.value.z );
}
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ColorFromARGBPacked(uint32_t in, aiColor4D& clr) void ColorFromARGBPacked(uint32_t in, aiColor4D& clr)
{ {
@ -194,7 +182,7 @@ int ConvertMappingMode(const std::string& mode)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Parse a material from the XML file // Parse a material from the XML file
aiMaterial* IRRMeshImporter::ParseMaterial(unsigned int& matFlags) aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
{ {
MaterialHelper* mat = new MaterialHelper(); MaterialHelper* mat = new MaterialHelper();
aiColor4D clr; aiColor4D clr;
@ -351,9 +339,11 @@ aiMaterial* IRRMeshImporter::ParseMaterial(unsigned int& matFlags)
/* Assume there are no further nested nodes in <material> elements /* Assume there are no further nested nodes in <material> elements
*/ */
if (/* IRRMESH */ !ASSIMP_stricmp(reader->getNodeName(),"material") ||
return mat; /* IRR */ !ASSIMP_stricmp(reader->getNodeName(),"attributes"))
{
return mat;
}
default: default:
// GCC complains here ... // GCC complains here ...
@ -364,6 +354,55 @@ aiMaterial* IRRMeshImporter::ParseMaterial(unsigned int& matFlags)
return mat; return mat;
} }
// ------------------------------------------------------------------------------------------------
// 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.
bool IRRMeshImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
{
/* NOTE: A simple check for the file extension is not enough
* here. Irrmesh and irr are easy, but xml is too generic
* and could be collada, too. So we need to open the file and
* search for typical tokens.
*/
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)
return false;
std::string extension = pFile.substr( pos);
for (std::string::iterator i = extension.begin(); i != extension.end();++i)
*i = ::tolower(*i);
if (extension == ".irrmesh")return true;
else if (extension == ".xml")
{
/* If CanRead() is called to check whether the loader
* supports a specific file extension in general we
* must return true here.
*/
if (!pIOHandler)return true;
const char* tokens[] = {"irrmesh"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void IRRMeshImporter::InternReadFile( const std::string& pFile, void IRRMeshImporter::InternReadFile( const std::string& pFile,
@ -428,6 +467,8 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
curNormals.clear(); curNormals.clear();
curUV2s.clear(); curUV2s.clear();
curUVs.clear(); curUVs.clear();
curTangents.clear();
curBitangents.clear();
} }
@ -591,7 +632,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
curUV2s.push_back(temp); curUV2s.push_back(temp);
} }
// read optional tangent and bitangent vectors // read optional tangent and bitangent vectors
if (vertexFormat == 2) else if (vertexFormat == 2)
{ {
// tangents // tangents
sz = fast_atof_move(sz,(float&)temp.x); sz = fast_atof_move(sz,(float&)temp.x);
@ -721,6 +762,9 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
} }
} }
if (materials.empty())
throw new ImportErrorException("IRRMESH: Unable to read a mesh from this file");
// now generate the output scene // now generate the output scene
pScene->mNumMeshes = (unsigned int)meshes.size(); pScene->mNumMeshes = (unsigned int)meshes.size();
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];

View File

@ -52,6 +52,51 @@ namespace Assimp {
#define AI_IRRMESH_MAT_lightmap_m2 (AI_IRRMESH_MAT_lightmap|0x4) #define AI_IRRMESH_MAT_lightmap_m2 (AI_IRRMESH_MAT_lightmap|0x4)
#define AI_IRRMESH_MAT_lightmap_m4 (AI_IRRMESH_MAT_lightmap|0x5) #define AI_IRRMESH_MAT_lightmap_m4 (AI_IRRMESH_MAT_lightmap|0x5)
// ---------------------------------------------------------------------------
/** Base class for the Irr and IrrMesh importers
*/
class IrrlichtBase
{
protected:
template <class T>
struct Property
{
std::string name;
T value;
};
typedef Property<uint32_t> HexProperty;
typedef Property<std::string> StringProperty;
typedef Property<bool> BoolProperty;
typedef Property<float> FloatProperty;
typedef Property<aiVector3D> VectorProperty;
/** XML reader instance
*/
IrrXMLReader* reader;
// -------------------------------------------------------------------
/** Parse a material description from the XML
* @return The created material
* @param matFlags Receives AI_IRRMESH_MAT_XX flags
*/
aiMaterial* ParseMaterial(unsigned int& matFlags);
// -------------------------------------------------------------------
/** Read a property of the specified type from the current XML element.
* @param out Recives output data
*/
void ReadHexProperty (HexProperty& out);
void ReadStringProperty (StringProperty& out);
void ReadBoolProperty (BoolProperty& out);
void ReadFloatProperty (FloatProperty& out);
void ReadVectorProperty (VectorProperty& out);
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** IrrMesh importer class. /** IrrMesh importer class.
* *
@ -59,7 +104,7 @@ namespace Assimp {
* irrEdit. As IrrEdit itself is capable of importing quite many file formats, * irrEdit. As IrrEdit itself is capable of importing quite many file formats,
* it might be a good file format for data exchange. * it might be a good file format for data exchange.
*/ */
class IRRMeshImporter : public BaseImporter class IRRMeshImporter : public BaseImporter, public IrrlichtBase
{ {
friend class Importer; friend class Importer;
@ -102,40 +147,6 @@ protected:
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
private:
template <class T>
struct Property
{
std::string name;
T value;
};
typedef Property<uint32_t> HexProperty;
typedef Property<std::string> StringProperty;
typedef Property<bool> BoolProperty;
typedef Property<float> FloatProperty;
IrrXMLReader* reader;
// -------------------------------------------------------------------
/** Parse a material description from the XML
* @return The created material
* @param matFlags Receives AI_IRRMESH_MAT_XX flags
*/
aiMaterial* ParseMaterial(unsigned int& matFlags);
// -------------------------------------------------------------------
/** Read a property of the specified type from the current XML element.
* @param out Recives output data
*/
void ReadHexProperty (HexProperty& out);
void ReadStringProperty (StringProperty& out);
void ReadBoolProperty (BoolProperty& out);
void ReadFloatProperty (FloatProperty& out);
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -119,7 +119,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BUILD_NO_IRRMESH_IMPORTER #ifndef AI_BUILD_NO_IRRMESH_IMPORTER
# include "IRRMeshLoader.h" # include "IRRMeshLoader.h"
#endif #endif
#ifndef AI_BUILD_NO_IRR_IMPORTER
# include "IRRLoader.h"
#endif
// PostProcess-Steps // PostProcess-Steps
@ -270,6 +272,9 @@ Importer::Importer() :
#if (!defined AI_BUILD_NO_IRRMESH_IMPORTER) #if (!defined AI_BUILD_NO_IRRMESH_IMPORTER)
mImporter.push_back( new IRRMeshImporter()); mImporter.push_back( new IRRMeshImporter());
#endif #endif
#if (!defined AI_BUILD_NO_IRR_IMPORTER)
mImporter.push_back( new IRRImporter());
#endif
// add an instance of each post processing step here in the order // add an instance of each post processing step here in the order
// of sequence it is executed. steps that are added here are not validated - // of sequence it is executed. steps that are added here are not validated -
@ -291,6 +296,10 @@ Importer::Importer() :
mPostProcessingSteps.push_back( new RemoveVCProcess()); mPostProcessingSteps.push_back( new RemoveVCProcess());
#endif #endif
#if (!defined AI_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess());
#endif
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS) #if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
mPostProcessingSteps.push_back( new PretransformVertices()); mPostProcessingSteps.push_back( new PretransformVertices());
#endif #endif
@ -306,9 +315,6 @@ Importer::Importer() :
#endif #endif
#if (!defined AI_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess());
#endif
#if (!defined AI_BUILD_NO_OPTIMIZEGRAPH_PROCESS) #if (!defined AI_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
mPostProcessingSteps.push_back( new OptimizeGraphProcess()); mPostProcessingSteps.push_back( new OptimizeGraphProcess());
#endif #endif

View File

@ -153,13 +153,16 @@ void ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshN
float fACMR = (float)iCacheMisses / pMesh->mNumFaces; float fACMR = (float)iCacheMisses / pMesh->mNumFaces;
if (3.0 == fACMR) if (3.0 == fACMR)
{ {
char szBuff[128]; // should be sufficiently large in every case if (!DefaultLogger::isNullLogger())
{
char szBuff[128]; // should be sufficiently large in every case
// the JoinIdenticalVertices process has not been executed on this // the JoinIdenticalVertices process has not been executed on this
// mesh, otherwise this value would normally be at least minimally# // mesh, otherwise this value would normally be at least minimally#
// smaller than 3.0 ... // smaller than 3.0 ...
::sprintf(szBuff,"Mesh %i: JIV-Step has not been executed properly (precondition)",meshNum); ::sprintf(szBuff,"Mesh %i: Not suitable for vcache optimization",meshNum);
DefaultLogger::get()->warn(szBuff); DefaultLogger::get()->warn(szBuff);
}
return; return;
} }

View File

@ -90,7 +90,9 @@ bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
// Setup configuration properties // Setup configuration properties
void LWOImporter::SetupProperties(const Importer* pImp) void LWOImporter::SetupProperties(const Importer* pImp)
{ {
configSpeedFlag = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0) ? true : false); configSpeedFlag = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0) ? true : false);
configLayerIndex = pImp->GetPropertyInteger (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,0xffffffff);
configLayerName = pImp->GetPropertyString (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,"");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -384,6 +384,8 @@ protected:
aiScene* pScene; aiScene* pScene;
bool configSpeedFlag; bool configSpeedFlag;
unsigned int configLayerIndex;
std::string configLayerName;
}; };

View File

@ -147,7 +147,6 @@ void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat, CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat,
iVFormat,piFaces,piVertices); iVFormat,piFaces,piVertices);
} }
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -167,7 +166,7 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] =
pcNode->mTransformation * pcMesh->mVertices[n]; pcNode->mTransformation * pcMesh->mVertices[n];
} }
if (iVFormat & 0x1) if (iVFormat & 0x2)
{ {
aiMatrix4x4 mWorldIT = pcNode->mTransformation; aiMatrix4x4 mWorldIT = pcNode->mTransformation;
mWorldIT.Inverse().Transpose(); mWorldIT.Inverse().Transpose();
@ -182,7 +181,7 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
m * pcMesh->mNormals[n]; m * pcMesh->mNormals[n];
} }
} }
if (iVFormat & 0x2) if (iVFormat & 0x4)
{ {
// copy tangents // copy tangents
memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX], memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX],
@ -250,7 +249,7 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
}; };
} }
aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices; aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices;
aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces; aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces;
} }
} }
for (unsigned int i = 0;i < pcNode->mNumChildren;++i) for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
@ -258,28 +257,22 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
CollectData(pcScene,pcNode->mChildren[i],iMat, CollectData(pcScene,pcNode->mChildren[i],iMat,
iVFormat,pcMeshOut,aiCurrent); iVFormat,pcMeshOut,aiCurrent);
} }
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a list of all vertex formats that occur for a given material index // Get a list of all vertex formats that occur for a given material index
// The output list contains duplicate elements // The output list contains duplicate elements
void GetVFormatList( aiScene* pcScene, aiNode* pcNode, unsigned int iMat, void GetVFormatList( aiScene* pcScene, unsigned int iMat,
std::list<unsigned int>& aiOut) std::list<unsigned int>& aiOut)
{ {
for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
{ {
aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; aiMesh* pcMesh = pcScene->mMeshes[ i ];
if (iMat == pcMesh->mMaterialIndex) if (iMat == pcMesh->mMaterialIndex)
{ {
aiOut.push_back(GetMeshVFormat(pcMesh)); aiOut.push_back(GetMeshVFormat(pcMesh));
} }
} }
for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
{
GetVFormatList(pcScene,pcNode->mChildren[i],iMat,aiOut);
}
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -295,7 +288,6 @@ void ComputeAbsoluteTransform( aiNode* pcNode )
{ {
ComputeAbsoluteTransform(pcNode->mChildren[i]); ComputeAbsoluteTransform(pcNode->mChildren[i]);
} }
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -333,8 +325,8 @@ void PretransformVertices::Execute( aiScene* pScene)
{ {
// get the list of all vertex formats for this material // get the list of all vertex formats for this material
aiVFormats.clear(); aiVFormats.clear();
GetVFormatList(pScene,pScene->mRootNode,i,aiVFormats); GetVFormatList(pScene,i,aiVFormats);
aiVFormats.sort(std::less<unsigned int>()); aiVFormats.sort();
aiVFormats.unique(); aiVFormats.unique();
for (std::list<unsigned int>::const_iterator for (std::list<unsigned int>::const_iterator
j = aiVFormats.begin(); j = aiVFormats.begin();
@ -352,11 +344,11 @@ void PretransformVertices::Execute( aiScene* pScene)
pcMesh->mFaces = new aiFace[iFaces]; pcMesh->mFaces = new aiFace[iFaces];
pcMesh->mVertices = new aiVector3D[iVertices]; pcMesh->mVertices = new aiVector3D[iVertices];
pcMesh->mMaterialIndex = i; pcMesh->mMaterialIndex = i;
if ((*j) & 0x1)pcMesh->mNormals = new aiVector3D[iVertices]; if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices];
if ((*j) & 0x2) if ((*j) & 0x4)
{ {
pcMesh->mTangents = new aiVector3D[iVertices]; pcMesh->mTangents = new aiVector3D[iVertices];
pcMesh->mBitangents = new aiVector3D[iVertices]; pcMesh->mBitangents = new aiVector3D[iVertices];
} }
iFaces = 0; iFaces = 0;
while ((*j) & (0x100 << iFaces)) while ((*j) & (0x100 << iFaces))
@ -396,17 +388,28 @@ void PretransformVertices::Execute( aiScene* pScene)
// the mesh array are not overridden. We set them to NULL to // the mesh array are not overridden. We set them to NULL to
// make sure the developer gets notified when his application // make sure the developer gets notified when his application
// attempts to access these fields ... // attempts to access these fields ...
AI_DEBUG_INVALIDATE_PTR( pScene->mMeshes[i] ); pScene->mMeshes[i] = NULL;
} }
pScene->mNumMeshes = (unsigned int)apcOutMeshes.size(); // If no meshes are referenced in the node graph it is
if (apcOutMeshes.size() > pScene->mNumMeshes) // possible that we get no output meshes. However, this
// is OK if we had no input meshes, too
if (apcOutMeshes.empty())
{ {
delete[] pScene->mMeshes; if (pScene->mNumMeshes)
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; {
throw new ImportErrorException("No output meshes: all meshes are orphaned "
"and have no node references");
}
}
else
{
// It is impossible that we have more output meshes than
// input meshes, so we can easily reuse the old mesh array
pScene->mNumMeshes = (unsigned int)apcOutMeshes.size();
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
pScene->mMeshes[i] = apcOutMeshes[i];
} }
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
pScene->mMeshes[i] = apcOutMeshes[i];
// --- we need to keep all cameras and lights // --- we need to keep all cameras and lights
for (unsigned int i = 0; i < pScene->mNumCameras;++i) for (unsigned int i = 0; i < pScene->mNumCameras;++i)

View File

@ -132,6 +132,12 @@ bool SortByPTypeProcess::IsActive( unsigned int pFlags) const
return (pFlags & aiProcess_SortByPType) != 0; return (pFlags & aiProcess_SortByPType) != 0;
} }
// ------------------------------------------------------------------------------------------------
void SortByPTypeProcess::SetupProperties(const Importer* pImp)
{
configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Update changed meshes in all nodes // Update changed meshes in all nodes
void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node) void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node)
@ -143,26 +149,38 @@ void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node
unsigned int newSize = 0; unsigned int newSize = 0;
for (unsigned int m = 0; m< node->mNumMeshes; ++m) for (unsigned int m = 0; m< node->mNumMeshes; ++m)
{ {
it = replaceMeshIndex.begin()+(node->mMeshes[m]*5u); unsigned int add = node->mMeshes[m]<<2;
for (;*it != 0xcdcdcdcd;++it) for (unsigned int i = 0; i < 4;++i)
{ {
if (0xffffffff != *it)++newSize; if (0xffffffff != replaceMeshIndex[add+i])++newSize;
} }
} }
if (!newSize)
ai_assert(0 != newSize);
unsigned int* newMeshes = new unsigned int[newSize];
for (unsigned int m = 0; m< node->mNumMeshes; ++m)
{ {
it = replaceMeshIndex.begin()+(node->mMeshes[m]*5u); delete[] node->mMeshes;
for (;*it != 0xcdcdcdcd;++it) node->mNumMeshes = 0;
{ node->mMeshes = NULL;
if (0xffffffff != *it)*newMeshes++ = *it; }
} else
{
// Try to reuse the old array if possible
unsigned int* newMeshes = (newSize > node->mNumMeshes
? new unsigned int[newSize] : node->mMeshes);
for (unsigned int m = 0; m< node->mNumMeshes; ++m)
{
unsigned int add = node->mMeshes[m]<<2;
for (unsigned int i = 0; i < 4;++i)
{
if (0xffffffff != replaceMeshIndex[add+i])
*newMeshes++ = replaceMeshIndex[add+i];
}
}
if (newSize > node->mNumMeshes)
delete[] node->mMeshes;
node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
} }
delete[] node->mMeshes;
node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
} }
// call all subnodes recursively // call all subnodes recursively
@ -189,7 +207,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
bool bAnyChanges = false; bool bAnyChanges = false;
std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*5,0xffffffff); std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,0xffffffff);
std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin(); std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{ {
@ -221,12 +239,14 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
if (1 == num) if (1 == num)
{ {
*meshIdx = (unsigned int) outMeshes.size(); if (!(configRemoveMeshes & mesh->mPrimitiveTypes))
outMeshes.push_back(mesh); {
*meshIdx = (unsigned int) outMeshes.size();
outMeshes.push_back(mesh);
}
else bAnyChanges = true;
meshIdx += 4; meshIdx += 4;
*meshIdx = 0xcdcdcdcd;
++meshIdx;
continue; continue;
} }
bAnyChanges = true; bAnyChanges = true;
@ -253,7 +273,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh); VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh);
for (unsigned int real = 0; real < 4; ++real,++meshIdx) for (unsigned int real = 0; real < 4; ++real,++meshIdx)
{ {
if ( !aiNumPerPType[real]) if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real))
{ {
continue; continue;
} }
@ -343,7 +363,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
if (vert) if (vert)
{ {
*vert++ = mesh->mVertices[idx]; *vert++ = mesh->mVertices[idx];
mesh->mVertices[idx].x = std::numeric_limits<float>::quiet_NaN(); //mesh->mVertices[idx].x = std::numeric_limits<float>::quiet_NaN();
} }
if (nor )*nor++ = mesh->mNormals[idx]; if (nor )*nor++ = mesh->mNormals[idx];
if (tan ) if (tan )
@ -370,6 +390,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
in.mIndices = NULL; in.mIndices = NULL;
++outFaces; ++outFaces;
} }
ai_assert(outFaces == out->mFaces + out->mNumFaces);
// now generate output bones // now generate output bones
for (unsigned int q = 0; q < mesh->mNumBones;++q) for (unsigned int q = 0; q < mesh->mNumBones;++q)
@ -399,9 +420,6 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
} }
} }
*meshIdx = 0xcdcdcdcd;
++meshIdx;
// delete the per-vertex bone weights table // delete the per-vertex bone weights table
delete[] avw; delete[] avw;
@ -409,6 +427,12 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
delete mesh; delete mesh;
} }
if (outMeshes.empty())
{
// This should not occur
throw new ImportErrorException("No meshes remaining");
}
// If we added at least one mesh process all nodes in the node // If we added at least one mesh process all nodes in the node
// graph and update their respective mesh indices. // graph and update their respective mesh indices.
if (bAnyChanges) if (bAnyChanges)
@ -421,17 +445,17 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
delete[] pScene->mMeshes; delete[] pScene->mMeshes;
pScene->mNumMeshes = (unsigned int)outMeshes.size(); pScene->mNumMeshes = (unsigned int)outMeshes.size();
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
} }
::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
if (!DefaultLogger::isNullLogger()) if (!DefaultLogger::isNullLogger())
{ {
char buffer[1024]; char buffer[1024];
::sprintf(buffer,"Points: %i, Lines: %i, Triangles: %i, Polygons: %i (Meshes)", ::sprintf(buffer,"Points: %i%s, Lines: %i%s, Triangles: %i%s, Polygons: %i%s (Meshes, X = removed)",
aiNumMeshesPerPType[0], aiNumMeshesPerPType[0], (configRemoveMeshes & aiPrimitiveType_POINT ? "X" : ""),
aiNumMeshesPerPType[1], aiNumMeshesPerPType[1], (configRemoveMeshes & aiPrimitiveType_LINE ? "X" : ""),
aiNumMeshesPerPType[2], aiNumMeshesPerPType[2], (configRemoveMeshes & aiPrimitiveType_TRIANGLE ? "X" : ""),
aiNumMeshesPerPType[3]); aiNumMeshesPerPType[3], (configRemoveMeshes & aiPrimitiveType_POLYGON ? "X" : ""));
DefaultLogger::get()->info(buffer); DefaultLogger::get()->info(buffer);
DefaultLogger::get()->debug("SortByPTypeProcess finished"); DefaultLogger::get()->debug("SortByPTypeProcess finished");
} }

View File

@ -102,6 +102,13 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void Execute( aiScene* pScene); void Execute( aiScene* pScene);
// -------------------------------------------------------------------
void SetupProperties(const Importer* pImp);
private:
int configRemoveMeshes;
}; };
#endif #endif

View File

@ -52,33 +52,36 @@ namespace Assimp {
positions.push_back(n1); \ positions.push_back(n1); \
positions.push_back(n0); positions.push_back(n0);
#ifdef AI_STANDARD_SHAPES_OUTPUT_POLYGONS
# define ADD_PENTAGON(n0,n1,n2,n3,n4) \ # define ADD_PENTAGON(n0,n1,n2,n3,n4) \
positions.push_back(n0); \ if (polygons) \
positions.push_back(n1); \ { \
positions.push_back(n2); \ positions.push_back(n0); \
positions.push_back(n3); \ positions.push_back(n1); \
positions.push_back(n4); positions.push_back(n2); \
positions.push_back(n3); \
positions.push_back(n4); \
} \
else \
{ \
ADD_TRIANGLE(n0, n1, n2) \
ADD_TRIANGLE(n0, n2, n3) \
ADD_TRIANGLE(n0, n3, n4) \
}
# define ADD_QUAD(n0,n1,n2,n3) \ # define ADD_QUAD(n0,n1,n2,n3) \
positions.push_back(n0); \ if (polygons) \
positions.push_back(n1); \ { \
positions.push_back(n2); \ positions.push_back(n0); \
positions.push_back(n3); positions.push_back(n1); \
positions.push_back(n2); \
positions.push_back(n3); \
} \
else \
{ \
ADD_TRIANGLE(n0, n1, n2) \
ADD_TRIANGLE(n0, n2, n3) \
}
#else
# define ADD_PENTAGON(n0,n1,n2,n3,n4) \
ADD_TRIANGLE(n0, n1, n2) \
ADD_TRIANGLE(n0, n2, n3) \
ADD_TRIANGLE(n0, n3, n4)
# define ADD_QUAD(n0,n1,n2,n3) \
ADD_TRIANGLE(n0, n1, n2) \
ADD_TRIANGLE(n0, n2, n3)
#endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Subdivide(std::vector<aiVector3D>& positions) void Subdivide(std::vector<aiVector3D>& positions)
@ -105,9 +108,74 @@ void Subdivide(std::vector<aiVector3D>& positions)
} }
} }
// ------------------------------------------------------------------------------------------------
aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
unsigned int numIndices)
{
if (positions.size() & numIndices || positions.empty() || !numIndices)return NULL;
aiMesh* out = new aiMesh();
switch (numIndices)
{
case 1:
out->mPrimitiveTypes = aiPrimitiveType_POINT;
break;
case 2:
out->mPrimitiveTypes = aiPrimitiveType_LINE;
break;
case 3:
out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
break;
default:
out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
break;
};
out->mNumFaces = (unsigned int)positions.size() / numIndices;
out->mFaces = new aiFace[out->mNumFaces];
for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i)
{
aiFace& f = out->mFaces[i];
f.mNumIndices = numIndices;
f.mIndices = new unsigned int[numIndices];
for (unsigned int i = 0; i < numIndices;++i,++a)
f.mIndices[i] = a;
}
out->mNumVertices = (unsigned int)positions.size();
out->mVertices = new aiVector3D[out->mNumVertices];
::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D));
return out;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions) aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
std::vector<aiVector3D>&))
{
std::vector<aiVector3D> temp;
unsigned num = (*GenerateFunc)(temp);
return MakeMesh(temp,num);
}
// ------------------------------------------------------------------------------------------------
aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
std::vector<aiVector3D>&, bool))
{
std::vector<aiVector3D> temp;
unsigned num = (*GenerateFunc)(temp,true);
return MakeMesh(temp,num);
}
// ------------------------------------------------------------------------------------------------
aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
unsigned int,std::vector<aiVector3D>&))
{
std::vector<aiVector3D> temp;
unsigned num = (*GenerateFunc)(4,temp);
return MakeMesh(temp,num);
}
// ------------------------------------------------------------------------------------------------
unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
{ {
positions.reserve(positions.size()+60); positions.reserve(positions.size()+60);
@ -151,10 +219,12 @@ void StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
ADD_TRIANGLE(v9,v4,v6); ADD_TRIANGLE(v9,v4,v6);
ADD_TRIANGLE(v10,v5,v7); ADD_TRIANGLE(v10,v5,v7);
ADD_TRIANGLE(v11,v7,v5); ADD_TRIANGLE(v11,v7,v5);
return 3;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions) unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions,
bool polygons /*= false*/)
{ {
positions.reserve(positions.size()+108); positions.reserve(positions.size()+108);
@ -196,10 +266,11 @@ void StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions)
ADD_PENTAGON(v7, v15, v5, v18, v19); ADD_PENTAGON(v7, v15, v5, v18, v19);
ADD_PENTAGON(v7, v11, v6, v14, v15); ADD_PENTAGON(v7, v11, v6, v14, v15);
ADD_PENTAGON(v7, v19, v3, v10, v11); ADD_PENTAGON(v7, v19, v3, v10, v11);
return (polygons ? 5 : 3);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions) unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions)
{ {
positions.reserve(positions.size()+24); positions.reserve(positions.size()+24);
@ -219,10 +290,11 @@ void StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions)
ADD_TRIANGLE(v5,v1,v2); ADD_TRIANGLE(v5,v1,v2);
ADD_TRIANGLE(v5,v3,v1); ADD_TRIANGLE(v5,v3,v1);
ADD_TRIANGLE(v5,v0,v3); ADD_TRIANGLE(v5,v0,v3);
return 3;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions) unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
{ {
positions.reserve(positions.size()+9); positions.reserve(positions.size()+9);
@ -238,10 +310,12 @@ void StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
ADD_TRIANGLE(v0,v2,v3); ADD_TRIANGLE(v0,v2,v3);
ADD_TRIANGLE(v0,v3,v1); ADD_TRIANGLE(v0,v3,v1);
ADD_TRIANGLE(v1,v3,v2); ADD_TRIANGLE(v1,v3,v2);
return 3;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions) unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
bool polygons /*= false*/)
{ {
positions.reserve(positions.size()+36); positions.reserve(positions.size()+36);
float length = 1.f/1.73205080f; float length = 1.f/1.73205080f;
@ -261,9 +335,13 @@ void StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions)
ADD_QUAD(v6,v5,v1,v2); ADD_QUAD(v6,v5,v1,v2);
ADD_QUAD(v6,v2,v3,v7); ADD_QUAD(v6,v2,v3,v7);
ADD_QUAD(v6,v7,v4,v5); ADD_QUAD(v6,v7,v4,v5);
return (polygons ? 4 : 3);
} }
// Cleanup ...
#undef ADD_TRIANGLE #undef ADD_TRIANGLE
#undef ADD_QUAD
#undef ADD_PENTAGON
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void StandardShapes::MakeSphere(unsigned int tess, void StandardShapes::MakeSphere(unsigned int tess,

View File

@ -60,45 +60,83 @@ class ASSIMP_API StandardShapes
public: public:
// ----------------------------------------------------------------
/** Generates a mesh from an array of vertex positions.
*
* @param positions List of vertex positions
* @param numIndices Number of indices per primitive
* @return Output mesh
*/
static aiMesh* MakeMesh(const std::vector<aiVector3D>& positions,
unsigned int numIndices);
static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
(std::vector<aiVector3D>&));
static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
(std::vector<aiVector3D>&, bool));
static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
(unsigned int,std::vector<aiVector3D>&));
// ----------------------------------------------------------------
/** @brief Generates a hexahedron (cube) /** @brief Generates a hexahedron (cube)
* *
* Hexahedrons can be scaled on all axes. * Hexahedrons can be scaled on all axes.
* @param positions Receives output triangles. * @param positions Receives output triangles.
* * @param polygons If you pass true here quads will be returned
* @note If you define AI_STANDARD_SHAPES_OUTPUT_POLYGONS quads * @return Number of vertices per face
* instead of triangles are returned.
*/ */
static void MakeHexahedron(std::vector<aiVector3D>& positions); static unsigned int MakeHexahedron(
std::vector<aiVector3D>& positions,
bool polygons = false);
// ----------------------------------------------------------------
/** @brief Generates an icosahedron /** @brief Generates an icosahedron
* *
* @param positions Receives output triangles. * @param positions Receives output triangles.
* @return Number of vertices per face
*/ */
static void MakeIcosahedron(std::vector<aiVector3D>& positions); static unsigned int MakeIcosahedron(
std::vector<aiVector3D>& positions);
// ----------------------------------------------------------------
/** @brief Generates a dodecahedron /** @brief Generates a dodecahedron
* *
* @param positions Receives output triangles * @param positions Receives output triangles
* @note If you define AI_STANDARD_SHAPES_OUTPUT_POLYGONS pentagons * @param polygons If you pass true here pentagons will be returned
* instead of triangles are returned. * @return Number of vertices per face
*/ */
static void MakeDodecahedron(std::vector<aiVector3D>& positions); static unsigned int MakeDodecahedron(
std::vector<aiVector3D>& positions,
bool polygons = false);
// ----------------------------------------------------------------
/** @brief Generates an octahedron /** @brief Generates an octahedron
* *
* @param positions Receives output triangles. * @param positions Receives output triangles.
* @return Number of vertices per face
*/ */
static void MakeOctahedron(std::vector<aiVector3D>& positions); static unsigned int MakeOctahedron(
std::vector<aiVector3D>& positions);
// ----------------------------------------------------------------
/** @brief Generates a tetrahedron /** @brief Generates a tetrahedron
* *
* @param positions Receives output triangles. * @param positions Receives output triangles.
* @return Number of vertices per face
*/ */
static void MakeTetrahedron(std::vector<aiVector3D>& positions); static unsigned int MakeTetrahedron(
std::vector<aiVector3D>& positions);
// ----------------------------------------------------------------
/** @brief Generates a sphere /** @brief Generates a sphere
* *
* @param tess Number of subdivions - 0 generates a octahedron * @param tess Number of subdivions - 0 generates a octahedron
@ -107,7 +145,9 @@ public:
static void MakeSphere(unsigned int tess, static void MakeSphere(unsigned int tess,
std::vector<aiVector3D>& positions); std::vector<aiVector3D>& positions);
/** @brief Generates a cone or a cylinder, either opened or closed.
// ----------------------------------------------------------------
/** @brief Generates a cone or a cylinder, either open or closed.
* *
* @code * @code
* *
@ -136,6 +176,8 @@ public:
aiVector3D& center2,float radius2,unsigned int tess, aiVector3D& center2,float radius2,unsigned int tess,
std::vector<aiVector3D>& positions,bool bOpened = false); std::vector<aiVector3D>& positions,bool bOpened = false);
// ----------------------------------------------------------------
/** @brief Generates a flat circle /** @brief Generates a flat circle
* *
* @param center Center point of the circle * @param center Center point of the circle

View File

@ -43,4 +43,4 @@ private:
} // ! Assimp } // ! Assimp
#endif #endif

View File

@ -69,7 +69,8 @@ SOURCES = AssimpPCH.cpp \
FindDegenerates.cpp \ FindDegenerates.cpp \
XFileParser.cpp \ XFileParser.cpp \
./irrXML/irrXML.cpp \ ./irrXML/irrXML.cpp \
IRRMeshLoader.cpp IRRMeshLoader.cpp \
IRRLoader.cpp
OBJECTS = $(SOURCES:.cpp=.o) OBJECTS = $(SOURCES:.cpp=.o)

View File

@ -69,7 +69,8 @@ SOURCES = AssimpPCH.cpp \
SkeletonMeshBuilder.cpp \ SkeletonMeshBuilder.cpp \
BVHLoader.cpp \ BVHLoader.cpp \
./irrXML/irrXML.cpp \ ./irrXML/irrXML.cpp \
IRRMeshLoader.cpp IRRMeshLoader.cpp \
IRRLoader.cpp
OBJECTS = $(SOURCES:.cpp=.o) OBJECTS = $(SOURCES:.cpp=.o)

View File

@ -120,6 +120,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL "imp.ac.sepbfcull" #define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL "imp.ac.sepbfcull"
// ---------------------------------------------------------------------------
/** \brief Configures the ASE loader to always reconstruct normal vectors
* basing on the smoothing groups loaded from the file.
*
* Many ASE files have invalid normals (they're not orthonormal). This
* is the fault of 3DS Max ASE exporter.
* Property type: integer (0: false; !0: true). Default value: false.
*/
#define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS "imp.ase.reconn"
// ---------------------------------------------------------------------------
/** \brief Configures the LWO loader to load just one layer from the model.
*
* LWO files consist of layers and in some cases it could be useful to load
* only one of them. This property can be either a string - which specifies
* the name of the layer - or an integer - the index of the layer. If the
* property is not set the whole LWO model is loaded. Loading fails if the
* requested layer is not available.
*/
#define AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY "imp.lwo.layer"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Specifies the maximum angle that may be between two vertex tangents /** \brief Specifies the maximum angle that may be between two vertex tangents
* that their tangents and bitangents are smoothed. * that their tangents and bitangents are smoothed.
@ -251,6 +274,16 @@ enum aiComponent
*/ */
#define AI_CONFIG_PP_RVC_FLAGS "pp.rvc.flags" #define AI_CONFIG_PP_RVC_FLAGS "pp.rvc.flags"
// ---------------------------------------------------------------------------
/** \brief Input parameter to the #aiProcess_SortByPType step:
* Specifies which primitive types are removed by the step.
*
* This is a bitwise combination of the aiPrimitiveType flags.
* Specifying all of them is illegal, of course. A typical use would
* be to easily exclude all line and point meshes from the import. This
* is an integer property, its default value is 0.
*/
#define AI_CONFIG_PP_SBP_REMOVE "pp.sbp.remove"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -264,4 +297,7 @@ enum aiComponent
*/ */
#define AI_CONFIG_FAVOUR_SPEED "imp.speed_flag" #define AI_CONFIG_FAVOUR_SPEED "imp.speed_flag"
#endif // !! AI_CONFIG_H_INC #endif // !! AI_CONFIG_H_INC

View File

@ -213,7 +213,7 @@ struct aiBone
* However one could use the vertex color sets for any other purpose, too. * However one could use the vertex color sets for any other purpose, too.
* *
* \note Some internal structures expect (and assert) this value * \note Some internal structures expect (and assert) this value
* to be at least 4 * to be at 4
*/ */
# define AI_MAX_NUMBER_OF_COLOR_SETS 0x4 # define AI_MAX_NUMBER_OF_COLOR_SETS 0x4
@ -228,7 +228,7 @@ struct aiBone
* which UVW channel serves as data source for a texture, * which UVW channel serves as data source for a texture,
* *
* \note Some internal structures expect (and assert) this value * \note Some internal structures expect (and assert) this value
* to be at least 4 * to be 4
*/ */
# define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x4 # define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x4
@ -311,7 +311,7 @@ struct aiMesh
*/ */
unsigned int mNumVertices; unsigned int mNumVertices;
/** The number of primitives (triangles, polygones, lines) in this mesh. /** The number of primitives (triangles, polygons, lines) in this mesh.
* This is also the size of the mFaces array * This is also the size of the mFaces array
*/ */
unsigned int mNumFaces; unsigned int mNumFaces;
@ -329,7 +329,16 @@ struct aiMesh
* lines only may not have normal vectors. Meshes with mixed * lines only may not have normal vectors. Meshes with mixed
* primitive types (i.e. lines and triangles) may have normals, * primitive types (i.e. lines and triangles) may have normals,
* but the normals for vertices that are only referenced by * but the normals for vertices that are only referenced by
* point or line primitives are undefined and set to QNaN. * point or line primitives are undefined and set to QNaN (WARN:
* qNaN compares to inequal to *everything*, even to qNaN itself.
* Use code like this
* @code
* #define IS_QNAN(f) (f != f)
* @endcode
* to check whether a field is qnan).
* @note Normal vectors computed by Assimp are always unit-length.
* However, this needn't apply for normals that have been taken
* directly from the model file.
*/ */
C_STRUCT aiVector3D* mNormals; C_STRUCT aiVector3D* mNormals;
@ -342,7 +351,8 @@ struct aiMesh
* normals, but the normals for vertices that are only referenced by * normals, but the normals for vertices that are only referenced by
* point or line primitives are undefined and set to QNaN. * point or line primitives are undefined and set to QNaN.
* @note If the mesh contains tangents, it automatically also * @note If the mesh contains tangents, it automatically also
* contains bitangents. * contains bitangents (the bitangent is just the cross product of
* tangent and normal vectors).
*/ */
C_STRUCT aiVector3D* mTangents; C_STRUCT aiVector3D* mTangents;

View File

@ -217,6 +217,9 @@ enum aiPostProcessSteps
* returns, just one bit is set in aiMesh::mPrimitiveTypes. This is * returns, just one bit is set in aiMesh::mPrimitiveTypes. This is
* especially useful for real-time rendering where point and line * especially useful for real-time rendering where point and line
* primitives are often ignored or rendered separately. * primitives are often ignored or rendered separately.
* You can use the AI_CONFIG_PP_SBP_REMOVE 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, aiProcess_SortByPType = 0x8000,

View File

@ -282,12 +282,14 @@ public:
* read-only, the importer object keeps ownership of the data and will * read-only, the importer object keeps ownership of the data and will
* destroy it upon destruction. If the import failes, NULL is returned. * destroy it upon destruction. If the import failes, NULL is returned.
* A human-readable error description can be retrieved by calling * A human-readable error description can be retrieved by calling
* GetErrorString(). * GetErrorString(). The previous scene will be deleted during this call.
* @param pFile Path and filename to the file to be imported. * @param pFile Path and filename to the file to be imported.
* @param pFlags Optional post processing steps to be executed after * @param pFlags Optional post processing steps to be executed after
* a successful import. Provide a bitwise combination of the * a successful import. Provide a bitwise combination of the
* #aiPostProcessSteps flags. * #aiPostProcessSteps flags.
* @return A pointer to the imported data, NULL if the import failed. * @return A pointer to the imported data, NULL if the import failed.
* The pointer to the scene remains in possession of the Importer
* instance. Use GetOrphanedScene() to take ownership of it.
*/ */
const aiScene* ReadFile( const std::string& pFile, unsigned int pFlags); const aiScene* ReadFile( const std::string& pFile, unsigned int pFlags);
@ -339,11 +341,30 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the scene loaded by the last successful call to ReadFile() /** Returns the scene loaded by the last successful call to ReadFile()
* *
* @return Current scene or NULL if there is currently no scene loaded * @return Current scene or NULL if there is currently no scene loaded
*/ */
inline const aiScene* GetScene() inline const aiScene* GetScene()
{return this->mScene;} {
return mScene;
}
// -------------------------------------------------------------------
/** Returns the scene loaded by the last successful call to ReadFile()
* and releases the scene from the ownership of the Importer
* instance. The application is now resposible for deleting the
* scene. Any further calls to GetScene() or GetOrphanedScene()
* will return NULL - until a new scene has been loaded via ReadFile().
*
* @return Current scene or NULL if there is currently no scene loaded
*/
inline const aiScene* GetOrphanedScene()
{
aiScene* scene = mScene;
mScene = NULL;
return scene;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test/XFiles/axe.jpg 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,51 @@
Dwarf lowpoly model Pack
Copyright 2004, Psionic Design
e-mail: psionic@blueyonder.co.uk
INSTALLATION INSTRUCTIONS:
To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go!
USAGE INFORMATION:
Each zip contains the models, textures and animation info for that particular format!
Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use
Credits to me "Psionic" are really appreciated but are not essential ;-)
Any questions, screenshots of him in use etc drop by my site or email me at:-
website: http://www.psionic3d.co.uk
email: psionic@blueyonder.co.uk
WHAT'S INCLUDED IN THE ZIP:
ReadMe.txt - This file
b3d.zip - Blitz 3D Format models and textures
ms3d.zip - Milkshape 3D Format models and textures
x.zip - DarkBasic Direct X 8 Format models and textures
RESTRICTIONS:
This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:-
**You may not sell/re-sell this model pack or claim it as your own.
***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent.
Psi
http://www.psionic3d.co.uk

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

18480
test/XFiles/dwarf.x 100644

File diff suppressed because it is too large Load Diff

View File

@ -1954,6 +1954,10 @@ int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
{ {
for (unsigned int i = 0; i < piNode->mNumMeshes;++i) for (unsigned int i = 0; i < piNode->mNumMeshes;++i)
{ {
// fix: Render triangle meshes only
if (g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
continue;
// don't render the mesh if the render pass is incorrect // don't render the mesh if the render pass is incorrect
if (g_sOptions.bRenderMats && ( if (g_sOptions.bRenderMats && (
g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piOpacityTexture || g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piOpacityTexture ||

View File

@ -78,9 +78,9 @@ void HandleMouseInputFPS( void )
if( 0 != nXDiff ) if( 0 != nXDiff )
{ {
D3DXVECTOR3 v(0,1,0); D3DXVECTOR3 v(0,1,0);
D3DXMatrixRotationAxis( &matRotation, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 6.0f) ); D3DXMatrixRotationAxis( &matRotation, (D3DXVECTOR3*)&g_sCamera.vUp, D3DXToRadian((float)nXDiff / 6.0f) );
D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)&g_sCamera.vLookAt, &matRotation ); D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)&g_sCamera.vLookAt, &matRotation );
D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vUp,(D3DXVECTOR3*) &g_sCamera.vUp, &matRotation ); D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vRight,(D3DXVECTOR3*) &g_sCamera.vRight, &matRotation );
CMeshRenderer::Instance().SetRotationChangedFlag(); CMeshRenderer::Instance().SetRotationChangedFlag();
} }

View File

@ -125,6 +125,9 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
// get current time // get current time
double fCur = (double)timeGetTime(); double fCur = (double)timeGetTime();
// Remove allline and point meshes from the import
aiSetImportPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,
aiPrimitiveType_LINE | aiPrimitiveType_POINT);
// call ASSIMPs C-API to load the file // call ASSIMPs C-API to load the file
g_pcAsset->pcScene = (aiScene*)aiImportFile(g_szFileName, g_pcAsset->pcScene = (aiScene*)aiImportFile(g_szFileName,
@ -136,7 +139,7 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes
aiProcess_ValidateDataStructure | aiProcess_ImproveCacheLocality aiProcess_ValidateDataStructure | aiProcess_ImproveCacheLocality
| aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType | | aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType |
aiProcess_FindInvalidData); // validate the output data structure aiProcess_FindDegenerates | aiProcess_FindInvalidData); // validate the output data structure
// get the end time of zje operation, calculate delta t // get the end time of zje operation, calculate delta t
double fEnd = (double)timeGetTime(); double fEnd = (double)timeGetTime();

View File

@ -69,7 +69,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif // min #endif // min
// default movement speed // default movement speed
#define MOVE_SPEED 0.4f #define MOVE_SPEED 3.f
using namespace Assimp; using namespace Assimp;

View File

@ -1362,6 +1362,18 @@
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="IRR"
>
<File
RelativePath="..\..\code\IRRLoader.cpp"
>
</File>
<File
RelativePath="..\..\code\IRRLoader.h"
>
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="PostProcess" Name="PostProcess"