Fixed some minor issues in the AC loader. However, it still crashes with large and complicated models. Line handling is complete.
Moved the code to find degenerated primitives to a separate step that is not anymore active by default. The FindInvalidData-Step isn't active by default now. It hast a flag and must be explicitly requested. Added line and point handling code to the CalcTangentsStep - not yet tested. Added support for the Sense 8 (WorldToolKit) NFF file format. The format uses the same file extension as the "Neutral File Format" (and is implemented in the same loader). Seems to work well, added test files for it. Added itoa10 function - so we have itoa on all platforms. Small optimizations in the SortByPType step. Fixed the material validation: textured meshes without uv coords cause a warning now. Fixed a minor isses with the OFF loader. Added empty unit tests for the new steps - to be filled in the next days. Added SceneCombiner.cpp. It contains utilities to join meshes and scenes. The latter will be needed by the LWS loader (LWS files contain references to external LWO files and the LWO loader is already to complicated that it would make sense to add an additional code path to it). Mesh joining is needed by some pp steps, but the code has not yet been moved to its new location. Added WIP light & camera support to the ASE loader. Works for the moment, but there's much missing. ASE parser refactored, the code is still quite long but at least cleaner. Fixed a bug that caused ASE to import invalid texture coordinates. Makefiles and VC8 solution are up-to-date. The rest isn't. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@192 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
013ff599a5
commit
383a614931
|
@ -683,7 +683,9 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
|
|||
if (1 != rootObjects.size())delete root;
|
||||
|
||||
// build output arrays
|
||||
ai_assert(!meshes.empty());
|
||||
if (meshes.empty())
|
||||
{
|
||||
}
|
||||
pScene->mNumMeshes = (unsigned int)meshes.size();
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||
::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
|
||||
|
|
|
@ -117,33 +117,33 @@ void ASEImporter::InternReadFile(
|
|||
// construct an ASE parser and parse the file
|
||||
// TODO: clean this up, mParser should be a reference, not a pointer ...
|
||||
ASE::Parser parser(this->mBuffer);
|
||||
this->mParser = &parser;
|
||||
this->mParser->Parse();
|
||||
mParser = &parser;
|
||||
mParser->Parse();
|
||||
|
||||
// if absolutely no material has been loaded from the file
|
||||
// we need to generate a default material
|
||||
this->GenerateDefaultMaterial();
|
||||
GenerateDefaultMaterial();
|
||||
|
||||
// process all meshes
|
||||
std::vector<aiMesh*> avOutMeshes;
|
||||
avOutMeshes.reserve(this->mParser->m_vMeshes.size()*2);
|
||||
avOutMeshes.reserve(mParser->m_vMeshes.size()*2);
|
||||
for (std::vector<ASE::Mesh>::iterator
|
||||
i = this->mParser->m_vMeshes.begin();
|
||||
i != this->mParser->m_vMeshes.end();++i)
|
||||
i = mParser->m_vMeshes.begin();
|
||||
i != mParser->m_vMeshes.end();++i)
|
||||
{
|
||||
if ((*i).bSkip)continue;
|
||||
|
||||
this->TransformVertices(*i);
|
||||
TransformVertices(*i);
|
||||
|
||||
// now we need to create proper meshes from the import we need to
|
||||
// split them by materials, build valid vertex/face lists ...
|
||||
this->BuildUniqueRepresentation(*i);
|
||||
BuildUniqueRepresentation(*i);
|
||||
|
||||
// need to generate proper vertex normals if necessary
|
||||
this->GenerateNormals(*i);
|
||||
GenerateNormals(*i);
|
||||
|
||||
// convert all meshes to aiMesh objects
|
||||
this->ConvertMeshes(*i,avOutMeshes);
|
||||
ConvertMeshes(*i,avOutMeshes);
|
||||
}
|
||||
|
||||
// now build the output mesh list. remove dummies
|
||||
|
@ -159,37 +159,42 @@ void ASEImporter::InternReadFile(
|
|||
pScene->mNumMeshes = (unsigned int)(pp - pScene->mMeshes);
|
||||
|
||||
// buil final material indices (remove submaterials and make the final list)
|
||||
this->BuildMaterialIndices();
|
||||
BuildMaterialIndices();
|
||||
|
||||
// build the final node graph
|
||||
this->BuildNodes();
|
||||
BuildNodes();
|
||||
|
||||
// build output animations
|
||||
this->BuildAnimations();
|
||||
return;
|
||||
BuildAnimations();
|
||||
|
||||
// build output cameras
|
||||
BuildCameras();
|
||||
|
||||
// build output lights
|
||||
BuildLights();
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::GenerateDefaultMaterial()
|
||||
{
|
||||
ai_assert(NULL != this->mParser);
|
||||
ai_assert(NULL != mParser);
|
||||
|
||||
bool bHas = false;
|
||||
for (std::vector<ASE::Mesh>::iterator
|
||||
i = this->mParser->m_vMeshes.begin();
|
||||
i != this->mParser->m_vMeshes.end();++i)
|
||||
i = mParser->m_vMeshes.begin();
|
||||
i != mParser->m_vMeshes.end();++i)
|
||||
{
|
||||
if ((*i).bSkip)continue;
|
||||
if (ASE::Face::DEFAULT_MATINDEX == (*i).iMaterialIndex)
|
||||
{
|
||||
(*i).iMaterialIndex = (unsigned int)this->mParser->m_vMaterials.size();
|
||||
(*i).iMaterialIndex = (unsigned int)mParser->m_vMaterials.size();
|
||||
bHas = true;
|
||||
}
|
||||
}
|
||||
if (bHas || this->mParser->m_vMaterials.empty())
|
||||
if (bHas || mParser->m_vMaterials.empty())
|
||||
{
|
||||
// add a simple material without sub materials to the parser's list
|
||||
this->mParser->m_vMaterials.push_back ( ASE::Material() );
|
||||
ASE::Material& mat = this->mParser->m_vMaterials.back();
|
||||
mParser->m_vMaterials.push_back ( ASE::Material() );
|
||||
ASE::Material& mat = mParser->m_vMaterials.back();
|
||||
|
||||
mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f);
|
||||
mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
|
||||
|
@ -198,13 +203,14 @@ void ASEImporter::GenerateDefaultMaterial()
|
|||
mat.mName = AI_DEFAULT_MATERIAL_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::BuildAnimations()
|
||||
{
|
||||
// check whether we have at least one mesh which has animations
|
||||
std::vector<ASE::Mesh>::iterator i = this->mParser->m_vMeshes.begin();
|
||||
std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin();
|
||||
unsigned int iNum = 0;
|
||||
for (;i != this->mParser->m_vMeshes.end();++i)
|
||||
for (;i != mParser->m_vMeshes.end();++i)
|
||||
{
|
||||
if ((*i).bSkip)continue;
|
||||
if ((*i).mAnim.akeyPositions.size() > 1 || (*i).mAnim.akeyRotations.size() > 1)
|
||||
|
@ -212,188 +218,294 @@ void ASEImporter::BuildAnimations()
|
|||
}
|
||||
if (iNum)
|
||||
{
|
||||
this->pcScene->mNumAnimations = 1;
|
||||
this->pcScene->mAnimations = new aiAnimation*[1];
|
||||
aiAnimation* pcAnim = this->pcScene->mAnimations[0] = new aiAnimation();
|
||||
// Generate a new animation channel and setup everything for it
|
||||
pcScene->mNumAnimations = 1;
|
||||
pcScene->mAnimations = new aiAnimation*[1];
|
||||
aiAnimation* pcAnim = pcScene->mAnimations[0] = new aiAnimation();
|
||||
pcAnim->mNumChannels = iNum;
|
||||
pcAnim->mChannels = new aiNodeAnim*[iNum];
|
||||
pcAnim->mTicksPerSecond = this->mParser->iFrameSpeed * this->mParser->iTicksPerFrame;
|
||||
pcAnim->mTicksPerSecond = mParser->iFrameSpeed * mParser->iTicksPerFrame;
|
||||
|
||||
iNum = 0;
|
||||
i = this->mParser->m_vMeshes.begin();
|
||||
for (;i != this->mParser->m_vMeshes.end();++i)
|
||||
i = mParser->m_vMeshes.begin();
|
||||
|
||||
// Now iterate through all meshes and collect all data we can find
|
||||
for (;i != mParser->m_vMeshes.end();++i)
|
||||
{
|
||||
if ((*i).bSkip)continue;
|
||||
if ((*i).bSkip)continue; // mesh unreferenced?
|
||||
if ((*i).mAnim.akeyPositions.size() > 1 || (*i).mAnim.akeyRotations.size() > 1)
|
||||
{
|
||||
// Begin a new node animation channel for this node
|
||||
aiNodeAnim* pcNodeAnim = pcAnim->mChannels[iNum++] = new aiNodeAnim();
|
||||
pcNodeAnim->mNodeName.Set((*i).mName);
|
||||
pcNodeAnim->mNodeName.Set((*i).mName);
|
||||
|
||||
// copy position keys
|
||||
if ((*i).mAnim.akeyPositions.size() > 1 )
|
||||
{
|
||||
// Allocate the key array and fill it
|
||||
pcNodeAnim->mNumPositionKeys = (unsigned int) (*i).mAnim.akeyPositions.size();
|
||||
pcNodeAnim->mPositionKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
|
||||
|
||||
::memcpy(pcNodeAnim->mPositionKeys,&(*i).mAnim.akeyPositions[0],
|
||||
pcNodeAnim->mNumPositionKeys * sizeof(aiVectorKey));
|
||||
|
||||
// get the longest node anim here
|
||||
for (unsigned int qq = 0; qq < pcNodeAnim->mNumPositionKeys;++qq)
|
||||
{
|
||||
double dTime = pcNodeAnim->mPositionKeys[qq].mTime;
|
||||
pcAnim->mDuration = std::max(pcAnim->mDuration,dTime);
|
||||
pcAnim->mDuration = std::max(pcAnim->mDuration,
|
||||
pcNodeAnim->mPositionKeys[qq].mTime);
|
||||
}
|
||||
}
|
||||
// copy rotation keys
|
||||
if ((*i).mAnim.akeyRotations.size() > 1 )
|
||||
{
|
||||
// Allocate the key array and fill it
|
||||
pcNodeAnim->mNumRotationKeys = (unsigned int) (*i).mAnim.akeyPositions.size();
|
||||
pcNodeAnim->mRotationKeys = new aiQuatKey[pcNodeAnim->mNumPositionKeys];
|
||||
|
||||
::memcpy(pcNodeAnim->mRotationKeys,&(*i).mAnim.akeyRotations[0],
|
||||
pcNodeAnim->mNumRotationKeys * sizeof(aiQuatKey));
|
||||
|
||||
// get the longest node anim here
|
||||
for (unsigned int qq = 0; qq < pcNodeAnim->mNumRotationKeys;++qq)
|
||||
{
|
||||
double dTime = pcNodeAnim->mRotationKeys[qq].mTime;
|
||||
pcAnim->mDuration = std::max(pcAnim->mDuration,dTime);
|
||||
pcAnim->mDuration = std::max(pcAnim->mDuration,
|
||||
pcNodeAnim->mRotationKeys[qq].mTime);
|
||||
}
|
||||
}
|
||||
// there are no scaling keys
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::AddNodes(aiNode* pcParent,const char* szName)
|
||||
void ASEImporter::BuildCameras()
|
||||
{
|
||||
if (!mParser->m_vCameras.empty())
|
||||
{
|
||||
pcScene->mNumCameras = (unsigned int)mParser->m_vCameras.size();
|
||||
pcScene->mCameras = new aiCamera*[pcScene->mNumCameras];
|
||||
|
||||
for (unsigned int i = 0; i < pcScene->mNumCameras;++i)
|
||||
{
|
||||
aiCamera* out = pcScene->mCameras[i] = new aiCamera();
|
||||
ASE::Camera& in = mParser->m_vCameras[i];
|
||||
|
||||
// copy members
|
||||
out->mClipPlaneFar = in.mFar;
|
||||
out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f);
|
||||
out->mHorizontalFOV = AI_RAD_TO_DEG( in.mFOV );
|
||||
|
||||
out->mName.Set(in.mName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::BuildLights()
|
||||
{
|
||||
if (!mParser->m_vLights.empty())
|
||||
{
|
||||
pcScene->mNumLights = (unsigned int)mParser->m_vLights.size();
|
||||
pcScene->mLights = new aiLight*[pcScene->mNumLights];
|
||||
|
||||
for (unsigned int i = 0; i < pcScene->mNumLights;++i)
|
||||
{
|
||||
aiLight* out = pcScene->mLights[i] = new aiLight();
|
||||
ASE::Light& in = mParser->m_vLights[i];
|
||||
|
||||
out->mName.Set(in.mName);
|
||||
out->mType = aiLightSource_POINT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::AddNodes(std::vector<BaseNode*>& nodes,
|
||||
aiNode* pcParent,const char* szName)
|
||||
{
|
||||
aiMatrix4x4 m;
|
||||
ASE::DecompTransform dec(m);
|
||||
this->AddNodes(pcParent,szName,dec);
|
||||
this->AddNodes(nodes,pcParent,szName,m);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::AddNodes(aiNode* pcParent,const char* szName,
|
||||
const ASE::DecompTransform& decompTrafo)
|
||||
void ASEImporter::AddNodes (std::vector<BaseNode*>& nodes,
|
||||
aiNode* pcParent, const char* szName,
|
||||
const aiMatrix4x4& mat)
|
||||
{
|
||||
const size_t len = szName ? strlen(szName) : 0;
|
||||
|
||||
const size_t len = szName ? ::strlen(szName) : 0;
|
||||
ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
|
||||
std::vector<aiNode*> apcNodes;
|
||||
aiMesh** pcMeshes = pcScene->mMeshes;
|
||||
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
|
||||
{
|
||||
// get the name of the mesh
|
||||
aiMesh* pcMesh = *pcMeshes++;
|
||||
const ASE::Mesh& mesh = *((const ASE::Mesh*)pcMesh->mColors[2]);
|
||||
|
||||
// TODO: experimental quick'n'dirty, clean this up ...
|
||||
std::string szMyName[2] = {mesh.mName,mesh.mParent} ;
|
||||
// Receives child nodes for the pcParent node
|
||||
std::vector<aiNode*> apcNodes;
|
||||
|
||||
// Now iterate through all nodes in the scene and search for one
|
||||
// which has *us* as parent.
|
||||
for (std::vector<BaseNode*>::const_iterator it = nodes.begin(), end = nodes.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
const BaseNode* snode = *it;
|
||||
if (szName)
|
||||
{
|
||||
if( len != szMyName[1].length() ||
|
||||
0 != ASSIMP_stricmp ( szName, szMyName[1].c_str() ))
|
||||
{
|
||||
if (len != snode->mParent.length() || ::strcmp(szName,snode->mParent.c_str()))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ('\0' != szMyName[1].c_str()[0])continue;
|
||||
}
|
||||
else if (snode->mParent.length())
|
||||
continue;
|
||||
|
||||
(*it)->mProcessed = true;
|
||||
|
||||
// Allocate a new node and add it to the output data structure
|
||||
apcNodes.push_back(new aiNode());
|
||||
aiNode* node = apcNodes.back();
|
||||
|
||||
node->mName.Set(szMyName[0]);
|
||||
node->mNumMeshes = 1;
|
||||
node->mMeshes = new unsigned int[1];
|
||||
node->mMeshes[0] = i;
|
||||
node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
|
||||
node->mParent = pcParent;
|
||||
|
||||
aiMatrix4x4 mParentAdjust = decompTrafo.mMatrix;
|
||||
// Setup the transformation matrix of the node
|
||||
aiMatrix4x4 mParentAdjust = mat;
|
||||
mParentAdjust.Inverse();
|
||||
node->mTransformation = mParentAdjust*mesh.mTransform;
|
||||
|
||||
// Transform all vertices of the mesh back into their local space ->
|
||||
// at the moment they are pretransformed
|
||||
aiMatrix4x4 mInverse = mesh.mTransform;
|
||||
mInverse.Inverse();
|
||||
node->mTransformation = mParentAdjust*snode->mTransform;
|
||||
|
||||
aiVector3D* pvCurPtr = pcMesh->mVertices;
|
||||
const aiVector3D* const pvEndPtr = pcMesh->mVertices + pcMesh->mNumVertices;
|
||||
while (pvCurPtr != pvEndPtr)
|
||||
// If the type of this node is "Mesh" we need to search
|
||||
// the list of output meshes in the data structure for
|
||||
// all those that belonged to this node once. This is
|
||||
// slightly inconvinient here and a better solution should
|
||||
// be used when this code is refactored next.
|
||||
if (snode->mType == BaseNode::Mesh)
|
||||
{
|
||||
*pvCurPtr = mInverse * (*pvCurPtr);
|
||||
pvCurPtr++;
|
||||
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
|
||||
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
|
||||
aiMatrix4x4 mNewAbs = decompTrafo.mMatrix * node->mTransformation;
|
||||
ASE::DecompTransform dec( mNewAbs);
|
||||
this->AddNodes(node,node->mName.data,dec);
|
||||
aiMatrix4x4 mNewAbs = mat * node->mTransformation;
|
||||
AddNodes(nodes,node,node->mName.data,mNewAbs);
|
||||
}
|
||||
|
||||
// allocate enough space for the child nodes
|
||||
pcParent->mNumChildren = (unsigned int)apcNodes.size();
|
||||
pcParent->mChildren = new aiNode*[apcNodes.size()];
|
||||
|
||||
// now build all nodes
|
||||
// now build all nodes for our nice new children
|
||||
for (unsigned int p = 0; p < apcNodes.size();++p)
|
||||
{
|
||||
pcParent->mChildren[p] = apcNodes[p];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::BuildNodes()
|
||||
{
|
||||
ai_assert(NULL != pcScene);
|
||||
|
||||
// allocate the root node
|
||||
// allocate the one and only root node
|
||||
pcScene->mRootNode = new aiNode();
|
||||
pcScene->mRootNode->mNumMeshes = 0;
|
||||
pcScene->mRootNode->mMeshes = 0;
|
||||
pcScene->mRootNode->mName.Set("<root>");
|
||||
|
||||
// add all nodes
|
||||
this->AddNodes(pcScene->mRootNode,NULL);
|
||||
// generate a full list of all scenegraph elements we have
|
||||
std::vector<BaseNode*> nodes;
|
||||
nodes.reserve(mParser->m_vMeshes.size() +mParser->m_vLights.size()
|
||||
+ mParser->m_vCameras.size());
|
||||
|
||||
// now iterate through al meshes and find those that have not yet
|
||||
for (std::vector<ASE::Light>::iterator it = mParser->m_vLights.begin(),
|
||||
end = mParser->m_vLights.end();it != end; ++it)nodes.push_back(&(*it));
|
||||
|
||||
for (std::vector<ASE::Camera>::iterator it = mParser->m_vCameras.begin(),
|
||||
end = mParser->m_vCameras.end();it != end; ++it)nodes.push_back(&(*it));
|
||||
|
||||
for (std::vector<ASE::Mesh>::iterator it = mParser->m_vMeshes.begin(),
|
||||
end = mParser->m_vMeshes.end();it != end; ++it)nodes.push_back(&(*it));
|
||||
|
||||
// add all nodes
|
||||
AddNodes(nodes,pcScene->mRootNode,NULL);
|
||||
|
||||
// now iterate through al nodes and find those that have not yet
|
||||
// been added to the nodegraph (= their parent could not be recognized)
|
||||
std::vector<unsigned int> aiList;
|
||||
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
|
||||
std::vector<const BaseNode*> aiList;
|
||||
for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
// get the name of the mesh
|
||||
const ASE::Mesh& mesh = *((const ASE::Mesh*)pcScene->mMeshes[i]->mColors[2]);
|
||||
// TODO: experimental quick'n'dirty, clean this up ...
|
||||
std::string szMyName[2] = {mesh.mName,mesh.mParent} ;
|
||||
if ((*it)->mProcessed)continue;
|
||||
|
||||
// check whether our parent is known
|
||||
bool bKnowParent = false;
|
||||
for (unsigned int i2 = 0; i2 < pcScene->mNumMeshes;++i2)
|
||||
|
||||
// research the list, beginning from now and try to find out whether
|
||||
// there is a node that references *us* as a parent
|
||||
for (std::vector<BaseNode*>::const_iterator it2 = nodes.begin();
|
||||
it2 != end; ++it2)
|
||||
{
|
||||
if (i2 == i)continue;
|
||||
const ASE::Mesh& mesh2 = *((const ASE::Mesh*)pcScene->mMeshes[i2]->mColors[2]);
|
||||
// TODO: experimental quick'n'dirty, clean this up ...
|
||||
std::string szMyName2[2] = {mesh2.mName,mesh2.mParent} ;
|
||||
if (!ASSIMP_stricmp ( szMyName[1], szMyName2[0]))
|
||||
if (it2 == it)continue;
|
||||
|
||||
if ((*it2)->mParent == (*it)->mName)
|
||||
{
|
||||
bKnowParent = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// check if there is another mesh with the same unknown parent
|
||||
// that has already been handled and added to the list
|
||||
if (i2 < i)
|
||||
{
|
||||
if (ASSIMP_stricmp ( szMyName[1], szMyName2[1]))
|
||||
{
|
||||
bKnowParent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bKnowParent)
|
||||
{
|
||||
aiList.push_back(i);
|
||||
aiList.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// Are there ane orphaned nodes?
|
||||
if (!aiList.empty())
|
||||
{
|
||||
std::vector<aiNode*> apcNodes;
|
||||
|
@ -403,25 +515,28 @@ void ASEImporter::BuildNodes()
|
|||
apcNodes.push_back(pcScene->mRootNode->mChildren[i]);
|
||||
|
||||
delete[] pcScene->mRootNode->mChildren;
|
||||
for (std::vector<unsigned int>::/*const_*/iterator
|
||||
for (std::vector<const BaseNode*>::/*const_*/iterator
|
||||
i = aiList.begin();
|
||||
i != aiList.end();++i)
|
||||
{
|
||||
std::string* szMyName = (std::string*)pcScene->mMeshes[*i]->mColors[1];
|
||||
if (!szMyName)continue;
|
||||
const ASE::BaseNode* src = *i;
|
||||
|
||||
DefaultLogger::get()->info("Generating dummy node: " + szMyName[1] + ". "
|
||||
/*
|
||||
DefaultLogger::get()->info("Generating dummy node: " + src->mName + ". "
|
||||
"This node is not defined in the ASE file, but referenced as "
|
||||
"parent node.");
|
||||
"parent node");
|
||||
*/
|
||||
|
||||
// the parent is not known, so we can assume that we must add
|
||||
// this node to the root node of the whole scene
|
||||
aiNode* pcNode = new aiNode();
|
||||
pcNode->mParent = pcScene->mRootNode;
|
||||
pcNode->mName.Set(szMyName[1]);
|
||||
this->AddNodes(pcNode,pcNode->mName.data);
|
||||
pcNode->mName.Set(src->mName);
|
||||
AddNodes(nodes,pcNode,pcNode->mName.data);
|
||||
apcNodes.push_back(pcNode);
|
||||
}
|
||||
|
||||
// Regenerate our output array
|
||||
pcScene->mRootNode->mChildren = new aiNode*[apcNodes.size()];
|
||||
for (unsigned int i = 0; i < apcNodes.size();++i)
|
||||
pcScene->mRootNode->mChildren[i] = apcNodes[i];
|
||||
|
@ -429,6 +544,8 @@ void ASEImporter::BuildNodes()
|
|||
pcScene->mRootNode->mNumChildren = (unsigned int)apcNodes.size();
|
||||
}
|
||||
|
||||
// Reset the third color set to NULL - we used this field to
|
||||
// store a temporary pointer
|
||||
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
|
||||
pcScene->mMeshes[i]->mColors[2] = NULL;
|
||||
|
||||
|
@ -445,12 +562,14 @@ void ASEImporter::BuildNodes()
|
|||
pc->mNumChildren = 0;
|
||||
delete pc;
|
||||
}
|
||||
// The root node should not have at least one child or the file is invalid
|
||||
else if (!pcScene->mRootNode->mNumChildren)
|
||||
{
|
||||
throw new ImportErrorException("No nodes loaded. The ASE/ASK file is either empty or corrupt");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::TransformVertices(ASE::Mesh& mesh)
|
||||
{
|
||||
|
@ -458,6 +577,7 @@ void ASEImporter::TransformVertices(ASE::Mesh& mesh)
|
|||
// but we need row major
|
||||
mesh.mTransform.Transpose();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
|
||||
{
|
||||
|
@ -556,6 +676,7 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
|
|||
mesh.amTexCoords[c] = amTexCoords[c];
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::ConvertMaterial(ASE::Material& mat)
|
||||
{
|
||||
|
@ -705,22 +826,22 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMeshes)
|
||||
{
|
||||
// validate the material index of the mesh
|
||||
if (mesh.iMaterialIndex >= this->mParser->m_vMaterials.size())
|
||||
if (mesh.iMaterialIndex >= mParser->m_vMaterials.size())
|
||||
{
|
||||
mesh.iMaterialIndex = (unsigned int)this->mParser->m_vMaterials.size()-1;
|
||||
mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1;
|
||||
DefaultLogger::get()->warn("Material index is out of range");
|
||||
}
|
||||
|
||||
|
||||
// if the material the mesh is assigned to is consisting of submeshes
|
||||
// we'll need to split it ... Quak.
|
||||
if (!this->mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty())
|
||||
if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty())
|
||||
{
|
||||
std::vector<ASE::Material> vSubMaterials = this->mParser->
|
||||
std::vector<ASE::Material> vSubMaterials = mParser->
|
||||
m_vMaterials[mesh.iMaterialIndex].avSubMaterials;
|
||||
|
||||
std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[
|
||||
|
@ -752,7 +873,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
p_pcOut->mMaterialIndex = p;
|
||||
|
||||
// we will need this material
|
||||
this->mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true;
|
||||
mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true;
|
||||
|
||||
// store the real index here ... color channel 3
|
||||
p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
|
||||
|
@ -775,15 +896,14 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
// allocate enough storage for faces
|
||||
p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
|
||||
|
||||
if (p_pcOut->mNumVertices != 0)
|
||||
unsigned int iBase = 0,iIndex;
|
||||
if (p_pcOut->mNumVertices)
|
||||
{
|
||||
p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
|
||||
p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
|
||||
unsigned int iBase = 0;
|
||||
|
||||
p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
|
||||
for (unsigned int q = 0; q < aiSplit[p].size();++q)
|
||||
{
|
||||
unsigned int iIndex = aiSplit[p][q];
|
||||
iIndex = aiSplit[p][q];
|
||||
|
||||
p_pcOut->mFaces[q].mIndices = new unsigned int[3];
|
||||
p_pcOut->mFaces[q].mNumIndices = 3;
|
||||
|
@ -792,8 +912,8 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
{
|
||||
const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t];
|
||||
|
||||
p_pcOut->mVertices[iBase] = mesh.mPositions[iIndex2];
|
||||
p_pcOut->mNormals[iBase] = mesh.mNormals[iIndex2];
|
||||
p_pcOut->mVertices[iBase] = mesh.mPositions [iIndex2];
|
||||
p_pcOut->mNormals [iBase] = mesh.mNormals [iIndex2];
|
||||
|
||||
// convert bones, if existing
|
||||
if (!mesh.mBones.empty())
|
||||
|
@ -814,21 +934,23 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
}
|
||||
++iBase;
|
||||
}
|
||||
|
||||
// Flip the face order
|
||||
p_pcOut->mFaces[q].mIndices[0] = iBase-3;
|
||||
p_pcOut->mFaces[q].mIndices[1] = iBase-2;
|
||||
p_pcOut->mFaces[q].mIndices[2] = iBase-1;
|
||||
}
|
||||
}
|
||||
// convert texture coordinates
|
||||
// convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported)
|
||||
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
|
||||
{
|
||||
if (!mesh.amTexCoords[c].empty())
|
||||
{
|
||||
p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices];
|
||||
unsigned int iBase = 0;
|
||||
iBase = 0;
|
||||
for (unsigned int q = 0; q < aiSplit[p].size();++q)
|
||||
{
|
||||
unsigned int iIndex = aiSplit[p][q];
|
||||
iIndex = aiSplit[p][q];
|
||||
for (unsigned int t = 0; t < 3;++t)
|
||||
{
|
||||
p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]];
|
||||
|
@ -843,10 +965,10 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
if (!mesh.mVertexColors.empty())
|
||||
{
|
||||
p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices];
|
||||
unsigned int iBase = 0;
|
||||
iBase = 0;
|
||||
for (unsigned int q = 0; q < aiSplit[p].size();++q)
|
||||
{
|
||||
unsigned int iIndex = aiSplit[p][q];
|
||||
iIndex = aiSplit[p][q];
|
||||
for (unsigned int t = 0; t < 3;++t)
|
||||
{
|
||||
p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]];
|
||||
|
@ -892,13 +1014,17 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
}
|
||||
else
|
||||
{
|
||||
// otherwise we can simply copy the data to one output mesh
|
||||
// Otherwise we can simply copy the data to one output mesh
|
||||
// This codepath needs less memory and uses fast memcpy()s
|
||||
// to do the actual copying. So I think it is worth the
|
||||
// effort here.
|
||||
|
||||
aiMesh* p_pcOut = new aiMesh();
|
||||
p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
|
||||
// set an empty sub material index
|
||||
p_pcOut->mMaterialIndex = ASE::Face::DEFAULT_MATINDEX;
|
||||
this->mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true;
|
||||
mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true;
|
||||
|
||||
// store the real index here ... in color channel 3
|
||||
p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
|
||||
|
@ -960,10 +1086,10 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
p_pcOut->mFaces[iFace].mNumIndices = 3;
|
||||
p_pcOut->mFaces[iFace].mIndices = new unsigned int[3];
|
||||
|
||||
// copy indices
|
||||
p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0];
|
||||
// copy indices (flip the face order, too)
|
||||
p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[2];
|
||||
p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
|
||||
p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2];
|
||||
p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[0];
|
||||
}
|
||||
|
||||
// copy vertex bones
|
||||
|
@ -1009,9 +1135,11 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
++pcBone;
|
||||
}
|
||||
}
|
||||
|
||||
// delete allocated storage
|
||||
delete[] avBonesOut;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -1020,24 +1148,24 @@ void ASEImporter::BuildMaterialIndices()
|
|||
ai_assert(NULL != pcScene);
|
||||
|
||||
// iterate through all materials and check whether we need them
|
||||
for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat)
|
||||
for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat)
|
||||
{
|
||||
if (this->mParser->m_vMaterials[iMat].bNeed)
|
||||
if (mParser->m_vMaterials[iMat].bNeed)
|
||||
{
|
||||
// convert it to the aiMaterial layout
|
||||
ASE::Material& mat = this->mParser->m_vMaterials[iMat];
|
||||
this->ConvertMaterial(mat);
|
||||
ASE::Material& mat = mParser->m_vMaterials[iMat];
|
||||
ConvertMaterial(mat);
|
||||
TextureTransform::ApplyScaleNOffset(mat);
|
||||
++pcScene->mNumMaterials;
|
||||
}
|
||||
for (unsigned int iSubMat = 0; iSubMat < this->mParser->m_vMaterials[
|
||||
for (unsigned int iSubMat = 0; iSubMat < mParser->m_vMaterials[
|
||||
iMat].avSubMaterials.size();++iSubMat)
|
||||
{
|
||||
if (this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed)
|
||||
if (mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed)
|
||||
{
|
||||
// convert it to the aiMaterial layout
|
||||
ASE::Material& mat = this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat];
|
||||
this->ConvertMaterial(mat);
|
||||
ASE::Material& mat = mParser->m_vMaterials[iMat].avSubMaterials[iSubMat];
|
||||
ConvertMaterial(mat);
|
||||
TextureTransform::ApplyScaleNOffset(mat);
|
||||
++pcScene->mNumMaterials;
|
||||
}
|
||||
|
@ -1049,15 +1177,15 @@ void ASEImporter::BuildMaterialIndices()
|
|||
Dot3DS::Material** pcIntMaterials = new Dot3DS::Material*[pcScene->mNumMaterials];
|
||||
|
||||
unsigned int iNum = 0;
|
||||
for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat)
|
||||
for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat)
|
||||
{
|
||||
if (this->mParser->m_vMaterials[iMat].bNeed)
|
||||
if (mParser->m_vMaterials[iMat].bNeed)
|
||||
{
|
||||
ai_assert(NULL != this->mParser->m_vMaterials[iMat].pcInstance);
|
||||
pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].pcInstance;
|
||||
ai_assert(NULL != mParser->m_vMaterials[iMat].pcInstance);
|
||||
pcScene->mMaterials[iNum] = mParser->m_vMaterials[iMat].pcInstance;
|
||||
|
||||
// store the internal material, too
|
||||
pcIntMaterials[iNum] = &this->mParser->m_vMaterials[iMat];
|
||||
pcIntMaterials[iNum] = &mParser->m_vMaterials[iMat];
|
||||
|
||||
// iterate through all meshes and search for one which is using
|
||||
// this top-level material index
|
||||
|
@ -1072,16 +1200,16 @@ void ASEImporter::BuildMaterialIndices()
|
|||
}
|
||||
iNum++;
|
||||
}
|
||||
for (unsigned int iSubMat = 0; iSubMat < this->mParser->m_vMaterials[iMat].avSubMaterials.size();++iSubMat)
|
||||
for (unsigned int iSubMat = 0; iSubMat < mParser->m_vMaterials[iMat].avSubMaterials.size();++iSubMat)
|
||||
{
|
||||
if (this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed)
|
||||
if (mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed)
|
||||
{
|
||||
ai_assert(NULL != this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].pcInstance);
|
||||
pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].
|
||||
ai_assert(NULL != mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].pcInstance);
|
||||
pcScene->mMaterials[iNum] = mParser->m_vMaterials[iMat].
|
||||
avSubMaterials[iSubMat].pcInstance;
|
||||
|
||||
// store the internal material, too
|
||||
pcIntMaterials[iNum] = &this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat];
|
||||
pcIntMaterials[iNum] = &mParser->m_vMaterials[iMat].avSubMaterials[iSubMat];
|
||||
|
||||
// iterate through all meshes and search for one which is using
|
||||
// this sub-level material index
|
||||
|
@ -1091,7 +1219,7 @@ void ASEImporter::BuildMaterialIndices()
|
|||
iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3])
|
||||
{
|
||||
pcScene->mMeshes[iMesh]->mMaterialIndex = iNum;
|
||||
pcScene->mMeshes[iMesh]->mColors[3] = NULL;
|
||||
pcScene->mMeshes[iMesh]->mColors[3] = NULL;
|
||||
}
|
||||
}
|
||||
iNum++;
|
||||
|
@ -1099,8 +1227,8 @@ void ASEImporter::BuildMaterialIndices()
|
|||
}
|
||||
}
|
||||
// prepare for the next step
|
||||
for (unsigned int hans = 0; hans < this->mParser->m_vMaterials.size();++hans)
|
||||
TextureTransform::ApplyScaleNOffset(this->mParser->m_vMaterials[hans]);
|
||||
for (unsigned int hans = 0; hans < mParser->m_vMaterials.size();++hans)
|
||||
TextureTransform::ApplyScaleNOffset(mParser->m_vMaterials[hans]);
|
||||
|
||||
// now we need to iterate through all meshes,
|
||||
// generating correct texture coordinates and material uv indices
|
||||
|
@ -1134,8 +1262,9 @@ void ASEImporter::GenerateNormals(ASE::Mesh& mesh)
|
|||
qq = mesh.mNormals.begin();
|
||||
qq != mesh.mNormals.end();++qq)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,6 +136,16 @@ protected:
|
|||
*/
|
||||
void BuildNodes();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Build output cameras
|
||||
*/
|
||||
void BuildCameras();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Build output lights
|
||||
*/
|
||||
void BuildLights();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Build output animations
|
||||
*/
|
||||
|
@ -145,11 +155,14 @@ protected:
|
|||
/** Add sub nodes to a node
|
||||
* \param pcParent parent node to be filled
|
||||
* \param szName Name of the parent node
|
||||
* \param decompTrafo Decomposed absolute parent transformation mat
|
||||
* \param matrix Current transform
|
||||
*/
|
||||
void AddNodes(aiNode* pcParent,const char* szName);
|
||||
void AddNodes(aiNode* pcParent,const char* szName,
|
||||
const ASE::DecompTransform& decompTrafo);
|
||||
void AddNodes(std::vector<BaseNode*>& nodes,
|
||||
aiNode* pcParent,const char* szName);
|
||||
|
||||
void AddNodes(std::vector<BaseNode*>& nodes,
|
||||
aiNode* pcParent,const char* szName,
|
||||
const aiMatrix4x4& matrix);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Generate a default material and add it to the parser's list
|
||||
|
|
File diff suppressed because it is too large
Load Diff
160
code/ASEParser.h
160
code/ASEParser.h
|
@ -190,50 +190,49 @@ struct InheritanceInfo
|
|||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Stores a decomposed transformation matrix */
|
||||
struct DecompTransform
|
||||
/** Represents an ASE file node. Base class for mesh, light and cameras */
|
||||
struct BaseNode
|
||||
{
|
||||
//! Construction from a reference to an existing matrix
|
||||
DecompTransform(aiMatrix4x4& ref)
|
||||
: vPosition(std::numeric_limits<float>::quiet_NaN(),0.0f,0.0f)
|
||||
, vScaling(1.0f,1.0f,1.0f)
|
||||
, mMatrix(ref)
|
||||
{}
|
||||
enum Type {Light, Camera, Mesh, Dummy} mType;
|
||||
|
||||
//! Translational component
|
||||
mutable aiVector3D vPosition;
|
||||
|
||||
//! Rotational component
|
||||
mutable aiQuaternion qRotation;
|
||||
|
||||
//! Scaling component
|
||||
mutable aiVector3D vScaling;
|
||||
|
||||
//! Reference to the matrix being decomposed
|
||||
const aiMatrix4x4& mMatrix;
|
||||
|
||||
//! Decomposes the matrix if this has not yet been done
|
||||
inline void NeedDecomposedMatrixNOW() const
|
||||
{
|
||||
if (is_qnan(vPosition.x))
|
||||
{
|
||||
mMatrix.Decompose(vScaling,qRotation,vPosition);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper structure to represent an ASE file mesh */
|
||||
struct Mesh : public MeshWithSmoothingGroups<ASE::Face>
|
||||
{
|
||||
//! Constructor. Creates a default name for the mesh
|
||||
Mesh() : bSkip(false)
|
||||
//! Constructor. Creates a default name for the node
|
||||
BaseNode(Type _mType)
|
||||
: mType (_mType)
|
||||
, mProcessed (false)
|
||||
{
|
||||
// generate a default name for the node
|
||||
static int iCnt = 0;
|
||||
char szTemp[128]; // should be sufficiently large
|
||||
::sprintf(szTemp,"UNNAMED_%i",iCnt++);
|
||||
mName = szTemp;
|
||||
}
|
||||
|
||||
//! Name of the mesh
|
||||
std::string mName;
|
||||
|
||||
//! Name of the parent of the node
|
||||
//! "" if there is no parent ...
|
||||
std::string mParent;
|
||||
|
||||
//! Transformation matrix of the node
|
||||
aiMatrix4x4 mTransform;
|
||||
|
||||
//! Specifies which axes transformations a node inherits
|
||||
//! from its parent ...
|
||||
InheritanceInfo inherit;
|
||||
|
||||
bool mProcessed;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper structure to represent an ASE file mesh */
|
||||
struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode
|
||||
{
|
||||
//! Constructor.
|
||||
Mesh()
|
||||
: BaseNode (BaseNode::Mesh)
|
||||
, bSkip (false)
|
||||
{
|
||||
// use 2 texture vertex components by default
|
||||
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
|
||||
this->mNumUVComponents[c] = 2;
|
||||
|
@ -242,13 +241,6 @@ struct Mesh : public MeshWithSmoothingGroups<ASE::Face>
|
|||
iMaterialIndex = Face::DEFAULT_MATINDEX;
|
||||
}
|
||||
|
||||
//! Name of the mesh
|
||||
std::string mName;
|
||||
|
||||
//! Name of the parent of the mesh
|
||||
//! "" if there is no parent ...
|
||||
std::string mParent;
|
||||
|
||||
//! List of all texture coordinate sets
|
||||
std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
|
||||
|
@ -261,9 +253,6 @@ struct Mesh : public MeshWithSmoothingGroups<ASE::Face>
|
|||
//! List of all bones
|
||||
std::vector<Bone> mBones;
|
||||
|
||||
//! Transformation matrix of the mesh
|
||||
aiMatrix4x4 mTransform;
|
||||
|
||||
//! Animation channels for the node
|
||||
Animation mAnim;
|
||||
|
||||
|
@ -275,10 +264,45 @@ struct Mesh : public MeshWithSmoothingGroups<ASE::Face>
|
|||
|
||||
//! used internally
|
||||
bool bSkip;
|
||||
};
|
||||
|
||||
//! Specifies which axes transformations a node inherits
|
||||
//! from its parent ...
|
||||
InheritanceInfo inherit;
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper structure to represent an ASE light source */
|
||||
struct Light : public BaseNode
|
||||
{
|
||||
enum LightType
|
||||
{
|
||||
OMNI
|
||||
};
|
||||
|
||||
//! Constructor.
|
||||
Light()
|
||||
: BaseNode (BaseNode::Light)
|
||||
, mLightType (OMNI)
|
||||
, mColor (1.f,1.f,1.f)
|
||||
, mIntensity (1.f) // light is white by default
|
||||
{
|
||||
}
|
||||
|
||||
LightType mLightType;
|
||||
aiColor3D mColor;
|
||||
float mIntensity;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper structure to represent an ASE camera */
|
||||
struct Camera : public BaseNode
|
||||
{
|
||||
//! Constructor
|
||||
Camera()
|
||||
: BaseNode (BaseNode::Camera)
|
||||
, mFOV (0.75f) // in radians
|
||||
, mNear (0.1f)
|
||||
, mFar (1000.f) // could be zero
|
||||
{
|
||||
}
|
||||
|
||||
float mFOV, mNear, mFar;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
@ -317,6 +341,23 @@ private:
|
|||
//! \param mesh Mesh object to be filled
|
||||
void ParseLV1GeometryObjectBlock(Mesh& mesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse a *LIGHTOBJECT block in a file
|
||||
//! \param light Light object to be filled
|
||||
void ParseLV1LightObjectBlock(Light& mesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse a *CAMERAOBJECT block in a file
|
||||
//! \param cam Camera object to be filled
|
||||
void ParseLV1CameraObjectBlock(Camera& cam);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse the shared parts of the *GEOMOBJECT, *LIGHTOBJECT and
|
||||
//! *CAMERAOBJECT chunks.
|
||||
//! \param mesh ..
|
||||
//! \return true = token parsed, get next please
|
||||
bool ParseSharedNodeInfo(ASE::BaseNode& mesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse a *MATERIAL blocks in a material list
|
||||
//! \param mat Material structure to be filled
|
||||
|
@ -324,8 +365,8 @@ private:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse a *NODE_TM block in a file
|
||||
//! \param mesh Mesh object to be filled
|
||||
void ParseLV2NodeTransformBlock(Mesh& mesh);
|
||||
//! \param mesh Node (!) object to be filled
|
||||
void ParseLV2NodeTransformBlock(BaseNode& mesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse a *TM_ANIMATION block in a file
|
||||
|
@ -339,6 +380,16 @@ private:
|
|||
//! \param mesh Mesh object to be filled
|
||||
void ParseLV2MeshBlock(Mesh& mesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse a *LIGHT_SETTINGS block in a file
|
||||
//! \param light Light object to be filled
|
||||
void ParseLV2LightSettingsBlock(Light& light);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse a *CAMERA_SETTINGS block in a file
|
||||
//! \param cam Camera object to be filled
|
||||
void ParseLV2CameraSettingsBlock(Camera& cam);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//! Parse the *MAP_XXXXXX blocks in a material
|
||||
//! \param map Texture structure to be filled
|
||||
|
@ -522,10 +573,15 @@ public:
|
|||
//! List of all meshes found in the file
|
||||
std::vector<Mesh> m_vMeshes;
|
||||
|
||||
//! List of all lights found in the file
|
||||
std::vector<Light> m_vLights;
|
||||
|
||||
//! List of all cameras found in the file
|
||||
std::vector<Camera> m_vCameras;
|
||||
|
||||
//! Current line in the file
|
||||
unsigned int iLineNumber;
|
||||
|
||||
|
||||
//! First frame
|
||||
unsigned int iFirstFrame;
|
||||
|
||||
|
|
|
@ -60,9 +60,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// If we have at least VC8 some C string manipulation functions
|
||||
// are mapped to their safe _s counterparts (e.g. _itoa_s).
|
||||
// *******************************************************************
|
||||
# if _MSC_VER >= 1400 && !(defined _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
||||
# define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
|
||||
# endif
|
||||
#if _MSC_VER >= 1400 && !(defined _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
||||
# define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
|
||||
#endif
|
||||
|
||||
// *******************************************************************
|
||||
// STL headers - we need quite a lot of them
|
||||
|
|
|
@ -105,10 +105,15 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
|||
// assert() it here.
|
||||
//assert( must be verbose, dammit);
|
||||
|
||||
if (pMesh->mTangents) // thisimplies that mBitangents is also there
|
||||
return false;
|
||||
|
||||
if (pMesh->mTangents && pMesh->mBitangents ||
|
||||
!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
// triangles or higher-order polygons the normal vectors
|
||||
// are undefined.
|
||||
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
|
||||
{
|
||||
DefaultLogger::get()->info("Tangents are undefined for line and point meshes");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -121,6 +126,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
|||
const float angleEpsilon = 0.9999f;
|
||||
|
||||
std::vector<bool> vertexDone( pMesh->mNumVertices, false);
|
||||
const float qnan = std::numeric_limits<float>::quiet_NaN();
|
||||
|
||||
// create space for the tangents and bitangents
|
||||
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
|
||||
|
@ -138,8 +144,14 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
|||
const aiFace& face = pMesh->mFaces[a];
|
||||
if (face.mNumIndices < 3)
|
||||
{
|
||||
// There are less than three indices, thus the tangent vector
|
||||
// is not defined. We are finished with these vertices now,
|
||||
// their tangent vectors are set to qnan.
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||
{
|
||||
vertexDone[face.mIndices[i]] = true;
|
||||
meshTang [face.mIndices[i]] = qnan;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -430,14 +430,14 @@ bool DXFImporter::ParsePolyLine()
|
|||
// optional number of vertices
|
||||
case 71:
|
||||
{
|
||||
positions.reserve(std::min(std::max(100u, strtol10(cursor)),100000000u));
|
||||
positions.reserve(strtol10(cursor));
|
||||
break;
|
||||
}
|
||||
|
||||
// optional number of faces
|
||||
case 72:
|
||||
{
|
||||
indices.reserve(std::min(std::max(100u, strtol10(cursor)),100000000u) * 4u);
|
||||
indices.reserve(strtol10(cursor) * 4u);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -496,6 +496,8 @@ bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,aiColor4D& clr, unsigned i
|
|||
case 0: ret = true;break;
|
||||
|
||||
// todo - handle the correct layer for the vertex
|
||||
// At the moment it is assumed that all vertices of
|
||||
// a polyline are placed on the same global layer.
|
||||
|
||||
// x position of the first corner
|
||||
case 10: out.x = fast_atof(cursor);break;
|
||||
|
|
|
@ -42,10 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_DXFLOADER_H_INCLUDED
|
||||
#define AI_DXFLOADER_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "BaseImporter.h"
|
||||
#include "../include/aiTypes.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -159,7 +155,8 @@ protected:
|
|||
* Wont't be modified otherwise. Size must be at least 4.
|
||||
* @return false if the end of the file was reached
|
||||
*/
|
||||
bool ParsePolyLineVertex(aiVector3D& out, aiColor4D& clr, unsigned int* outIdx);
|
||||
bool ParsePolyLineVertex(aiVector3D& out, aiColor4D& clr,
|
||||
unsigned int* outIdx);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
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 DeterminePTypeHelperProcess and
|
||||
* SortByPTypeProcess post-process steps.
|
||||
*/
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
|
||||
// internal headers
|
||||
#include "ProcessHelper.h"
|
||||
#include "FindDegenerates.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
FindDegeneratesProcess::FindDegeneratesProcess()
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
FindDegeneratesProcess::~FindDegeneratesProcess()
|
||||
{
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
return 0 != (pFlags & aiProcess_FindDegenerates);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void FindDegeneratesProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
DefaultLogger::get()->debug("FindDegeneratesProcess begin");
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
{
|
||||
aiMesh* mesh = pScene->mMeshes[i];
|
||||
mesh->mPrimitiveTypes = 0;
|
||||
|
||||
unsigned int deg = 0;
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
||||
{
|
||||
aiFace& face = mesh->mFaces[a];
|
||||
bool first = true;
|
||||
|
||||
// check whether the face contains degenerated entries
|
||||
for (register unsigned int i = 0; i < face.mNumIndices; ++i)
|
||||
{
|
||||
for (register unsigned int a = i+1; a < face.mNumIndices; ++a)
|
||||
{
|
||||
if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[a]])
|
||||
{
|
||||
// we have found a matching vertex position
|
||||
// remove the corresponding index from the array
|
||||
for (unsigned int m = a; m < face.mNumIndices-1; ++m)
|
||||
{
|
||||
face.mIndices[m] = face.mIndices[m+1];
|
||||
}
|
||||
--a;
|
||||
--face.mNumIndices;
|
||||
|
||||
// NOTE: we set the removed vertex index to an unique value
|
||||
// to make sure the developer gets notified when his
|
||||
// application attemps to access this data.
|
||||
face.mIndices[face.mNumIndices] = 0xdeadbeef;
|
||||
|
||||
if(first)
|
||||
{
|
||||
++deg;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We need to update the primitive flags array of the mesh.
|
||||
// Unfortunately it is not possible to execute
|
||||
// FindDegenerates before DeterminePType. The latter does
|
||||
// nothing if the primitive flags have already been set by
|
||||
// the loader - our changes would be ignored. Although
|
||||
// we could use some tricks regarding - i.e setting
|
||||
// mPrimitiveTypes to 0 in every case - but this is the cleanest
|
||||
// way and causes no additional dependencies in the pipeline.
|
||||
switch (face.mNumIndices)
|
||||
{
|
||||
case 1u:
|
||||
mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
||||
break;
|
||||
case 2u:
|
||||
mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
||||
break;
|
||||
case 3u:
|
||||
mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||
break;
|
||||
default:
|
||||
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
||||
break;
|
||||
};
|
||||
}
|
||||
if (deg)
|
||||
{
|
||||
char s[64];
|
||||
itoa10(s,deg);
|
||||
DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives");
|
||||
}
|
||||
}
|
||||
DefaultLogger::get()->debug("FindDegeneratesProcess finished");
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
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 Defines a post processing step to search all meshes for
|
||||
degenerated faces */
|
||||
#ifndef AI_FINDDEGENERATESPROCESS_H_INC
|
||||
#define AI_FINDDEGENERATESPROCESS_H_INC
|
||||
|
||||
#include "BaseProcess.h"
|
||||
#include "../include/aiMesh.h"
|
||||
|
||||
class FindDegeneratesProcessTest;
|
||||
namespace Assimp {
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** FindDegeneratesProcess: Searches a mesh for degenerated triangles.
|
||||
*/
|
||||
class ASSIMP_API FindDegeneratesProcess : public BaseProcess
|
||||
{
|
||||
friend class Importer;
|
||||
friend class ::FindDegeneratesProcessTest; // grant the unit test full access to us
|
||||
|
||||
protected:
|
||||
/** Constructor to be privately used by Importer */
|
||||
FindDegeneratesProcess();
|
||||
|
||||
/** Destructor, private as well */
|
||||
~FindDegeneratesProcess();
|
||||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
bool IsActive( unsigned int pFlags) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void Execute( aiScene* pScene);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !! AI_FINDDEGENERATESPROCESS_H_INC
|
|
@ -70,8 +70,7 @@ FindInvalidDataProcess::~FindInvalidDataProcess()
|
|||
// Returns whether the processing step is present in the given flag field.
|
||||
bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
// this step is always active
|
||||
return true;
|
||||
return 0 != (pFlags & aiProcess_FindInvalidData);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -258,18 +257,21 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
|
|||
}
|
||||
|
||||
// process mesh normals
|
||||
if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices,"normals",dirtyMask))
|
||||
if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices,
|
||||
"normals",dirtyMask))
|
||||
ret = true;
|
||||
|
||||
// process mesh tangents
|
||||
if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,"tangents",dirtyMask))
|
||||
if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,
|
||||
"tangents",dirtyMask))
|
||||
{
|
||||
delete[] pMesh->mBitangents; pMesh->mBitangents = NULL;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// process mesh bitangents
|
||||
if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,"bitangents",dirtyMask))
|
||||
if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,
|
||||
"bitangents",dirtyMask))
|
||||
{
|
||||
delete[] pMesh->mTangents; pMesh->mTangents = NULL;
|
||||
ret = true;
|
||||
|
|
|
@ -53,8 +53,7 @@ namespace Assimp
|
|||
{
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** The FindInvalidData postprocessing step is always active, there is
|
||||
* no corresponding aiPostProcess flag. It searches the mesh data
|
||||
/** The FindInvalidData postprocessing step. It searches the mesh data
|
||||
* for parts that are obviously invalid and removes them.
|
||||
*
|
||||
* Originally this was a workaround for some models written by Blender
|
||||
|
|
|
@ -108,7 +108,8 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
|
|||
// Executes the post processing step on the given imported data.
|
||||
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
|
||||
{
|
||||
if (NULL != pMesh->mNormals)return false;
|
||||
if (NULL != pMesh->mNormals)
|
||||
return false;
|
||||
|
||||
// If the mesh consists of lines and/or points but not of
|
||||
// triangles or higher-order polygons the normal vectors
|
||||
|
|
|
@ -167,6 +167,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_BUILD_NO_FINDINVALIDDATA_PROCESS
|
||||
# include "FindInvalidDataProcess.h"
|
||||
#endif
|
||||
#ifndef AI_BUILD_NO_FINDDEGENERATES_PROCESS
|
||||
# include "FindDegenerates.h"
|
||||
#endif
|
||||
|
||||
// NOTE: the preprocessor code has been moved to the header as
|
||||
// we've also declared the DeterminePType process in it, which
|
||||
|
@ -272,6 +275,11 @@ Importer::Importer() :
|
|||
|
||||
mPostProcessingSteps.push_back( new DeterminePTypeHelperProcess());
|
||||
|
||||
#if (!defined AI_BUILD_NO_FINDDEGENERATES_PROCESS)
|
||||
mPostProcessingSteps.push_back( new FindDegeneratesProcess());
|
||||
#endif
|
||||
|
||||
|
||||
#if (!defined AI_BUILD_NO_REMOVEVC_PROCESS)
|
||||
mPostProcessingSteps.push_back( new RemoveVCProcess());
|
||||
#endif
|
||||
|
@ -535,9 +543,9 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
|
|||
mScene = imp->ReadFile( pFile, mIOHandler);
|
||||
|
||||
// if successful, apply all active post processing steps to the imported data
|
||||
DefaultLogger::get()->info("Import succesful, entering postprocessing-steps");
|
||||
if( mScene)
|
||||
{
|
||||
DefaultLogger::get()->info("Import successful, entering postprocessing-steps");
|
||||
#ifdef _DEBUG
|
||||
if (bExtraVerbose)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
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 .LWS (LightWave Scene Format) importer class. */
|
||||
#ifndef AI_LWSLOADER_H_INCLUDED
|
||||
#define AI_LWSLOADER_H_INCLUDED
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** LWS (LightWave Scene Format) importer class.
|
||||
*
|
||||
* This class does heavily depend on the LWO importer class. LWS files
|
||||
* contain mainly descriptions how LWO objects are composed together
|
||||
* in a scene.
|
||||
*/
|
||||
class LWSImporter : public BaseImporter
|
||||
{
|
||||
friend class Importer;
|
||||
|
||||
protected:
|
||||
/** Constructor to be privately used by Importer */
|
||||
LWSImporter();
|
||||
|
||||
/** Destructor, private as well */
|
||||
~LWSImporter();
|
||||
|
||||
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)
|
||||
{
|
||||
append.append("*.lws");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_LWSIMPORTER_H_INC
|
|
@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "ParsingUtils.h"
|
||||
#include "StandardShapes.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
#include "RemoveComments.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -75,18 +75,13 @@ bool NFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|||
std::string extension = pFile.substr( pos);
|
||||
|
||||
// extensions: enff and nff
|
||||
if (!extension.length() || extension[0] != '.')return false;
|
||||
if (extension.length() == 4)
|
||||
{
|
||||
return !(extension[1] != 'n' && extension[1] != 'N' ||
|
||||
extension[2] != 'f' && extension[2] != 'F' ||
|
||||
extension[3] != 'f' && extension[3] != 'F');
|
||||
}
|
||||
else return !( extension.length() != 5 ||
|
||||
extension[1] != 'e' && extension[1] != 'E' ||
|
||||
extension[2] != 'n' && extension[2] != 'N' ||
|
||||
extension[3] != 'f' && extension[3] != 'F' ||
|
||||
extension[4] != 'f' && extension[4] != 'F');
|
||||
for( std::string::iterator it = extension.begin(); it != extension.end(); ++it)
|
||||
*it = tolower( *it);
|
||||
|
||||
if( extension == ".nff" || extension == ".enff")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -110,6 +105,122 @@ bool NFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|||
currentMesh.radius = radius; \
|
||||
currentMesh.center = center;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#define AI_NFF2_GET_NEXT_TOKEN() \
|
||||
do \
|
||||
{ \
|
||||
if (!GetNextLine(buffer,line)) \
|
||||
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read next token");break;} \
|
||||
SkipSpaces(line,&sz); \
|
||||
} \
|
||||
while(IsLineEnd(*sz))
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Loads the materail table for the NFF2 file format from an external file
|
||||
void NFFImporter::LoadNFF2MaterialTable(std::vector<ShadingInfo>& output,
|
||||
const std::string& path, IOSystem* pIOHandler)
|
||||
{
|
||||
boost::scoped_ptr<IOStream> file( pIOHandler->Open( path, "rb"));
|
||||
|
||||
// Check whether we can read from the file
|
||||
if( !file.get())
|
||||
{
|
||||
DefaultLogger::get()->error("NFF2: Unable to open material library " + path + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
// get the size of the file
|
||||
const unsigned int m = (unsigned int)file->FileSize();
|
||||
|
||||
// allocate storage and copy the contents of the file to a memory buffer
|
||||
// (terminate it with zero)
|
||||
std::vector<char> mBuffer2(m+1);
|
||||
file->Read(&mBuffer2[0],m,1);
|
||||
const char* buffer = &mBuffer2[0];
|
||||
mBuffer2[m] = '\0';
|
||||
|
||||
// First of all: remove all comments from the file
|
||||
CommentRemover::RemoveLineComments("//",&mBuffer2[0]);
|
||||
|
||||
// The file should start with the magic sequence "mat"
|
||||
if (!TokenMatch(buffer,"mat",3))
|
||||
{
|
||||
DefaultLogger::get()->error("NFF2: Not a valid material library " + path + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
ShadingInfo* curShader = NULL;
|
||||
|
||||
// No read the file line per line
|
||||
char line[4096];
|
||||
const char* sz;
|
||||
while (GetNextLine(buffer,line))
|
||||
{
|
||||
SkipSpaces(line,&sz);
|
||||
|
||||
// 'version' defines the version of the file format
|
||||
if (TokenMatch(sz,"version",7))
|
||||
{
|
||||
DefaultLogger::get()->info("NFF (Sense8) material library file format: " + std::string(sz));
|
||||
}
|
||||
// 'matdef' starts a new material in the file
|
||||
else if (TokenMatch(sz,"matdef",6))
|
||||
{
|
||||
// add a new material to the list
|
||||
output.push_back( ShadingInfo() );
|
||||
curShader = & output.back();
|
||||
|
||||
// parse the name of the material
|
||||
}
|
||||
else if (!TokenMatch(sz,"valid",5))
|
||||
{
|
||||
// check whether we have an active material at the moment
|
||||
if (!IsLineEnd(*sz))
|
||||
{
|
||||
if (!curShader)
|
||||
{
|
||||
DefaultLogger::get()->error(std::string("NFF2 material library: Found element ") +
|
||||
sz + "but there is no active material");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else continue;
|
||||
|
||||
// now read the material property and determine its type
|
||||
aiColor3D c;
|
||||
if (TokenMatch(sz,"ambient",7))
|
||||
{
|
||||
AI_NFF_PARSE_TRIPLE(c);
|
||||
curShader->ambient = c;
|
||||
}
|
||||
else if (TokenMatch(sz,"diffuse",7) || TokenMatch(sz,"ambientdiffuse",14) /* correct? */)
|
||||
{
|
||||
AI_NFF_PARSE_TRIPLE(c);
|
||||
curShader->diffuse = c;
|
||||
}
|
||||
else if (TokenMatch(sz,"specular",8))
|
||||
{
|
||||
AI_NFF_PARSE_TRIPLE(c);
|
||||
curShader->specular = c;
|
||||
}
|
||||
else if (TokenMatch(sz,"emission",8))
|
||||
{
|
||||
AI_NFF_PARSE_TRIPLE(c);
|
||||
curShader->emissive = c;
|
||||
}
|
||||
else if (TokenMatch(sz,"shininess",9))
|
||||
{
|
||||
AI_NFF_PARSE_FLOAT(curShader->shininess);
|
||||
}
|
||||
else if (TokenMatch(sz,"opacity",7))
|
||||
{
|
||||
AI_NFF_PARSE_FLOAT(curShader->opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void NFFImporter::InternReadFile( const std::string& pFile,
|
||||
|
@ -118,7 +229,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
|
||||
|
||||
// Check whether we can read from the file
|
||||
if( file.get() == NULL)
|
||||
if( !file.get())
|
||||
throw new ImportErrorException( "Failed to open NFF file " + pFile + ".");
|
||||
|
||||
unsigned int m = (unsigned int)file->FileSize();
|
||||
|
@ -142,7 +253,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
// camera parameters
|
||||
aiVector3D camPos, camUp(0.f,1.f,0.f), camLookAt(0.f,0.f,1.f);
|
||||
float angle;
|
||||
float angle = 45.f;
|
||||
aiVector2D resolution;
|
||||
|
||||
bool hasCam = false;
|
||||
|
@ -172,16 +283,24 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
// check whether this is the NFF2 file format
|
||||
if (TokenMatch(buffer,"nff",3))
|
||||
{
|
||||
const float qnan = std::numeric_limits<float>::quiet_NaN();
|
||||
const aiColor4D cQNAN = aiColor4D (qnan,0.f,0.f,1.f);
|
||||
const aiVector3D vQNAN = aiVector3D(qnan,0.f,0.f);
|
||||
|
||||
// another NFF file format ... just a raw parser has been implemented
|
||||
// no support for textures yet, I don't think it is worth the effort
|
||||
// no support for further details, I don't think it is worth the effort
|
||||
// http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/nff/nff2.html
|
||||
// http://www.netghost.narod.ru/gff/graphics/summary/sense8.htm
|
||||
|
||||
// First of all: remove all comments from the file
|
||||
CommentRemover::RemoveLineComments("//",&mBuffer2[0]);
|
||||
|
||||
while (GetNextLine(buffer,line))
|
||||
{
|
||||
sz = line;
|
||||
SkipSpaces(line,&sz);
|
||||
if (TokenMatch(sz,"version",7))
|
||||
{
|
||||
DefaultLogger::get()->info("NFF (alt.) file format: " + std::string(sz));
|
||||
DefaultLogger::get()->info("NFF (Sense8) file format: " + std::string(sz));
|
||||
}
|
||||
else if (TokenMatch(sz,"viewpos",7))
|
||||
{
|
||||
|
@ -193,79 +312,341 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
AI_NFF_PARSE_TRIPLE(camLookAt);
|
||||
hasCam = true;
|
||||
}
|
||||
else if (TokenMatch(sz,"//",2))
|
||||
// This starts a new object section
|
||||
else if (!IsSpaceOrNewLine(*sz))
|
||||
{
|
||||
// comment ...
|
||||
DefaultLogger::get()->info(sz);
|
||||
}
|
||||
else if (!IsSpace(*sz))
|
||||
{
|
||||
// must be a new object
|
||||
meshes.push_back(MeshInfo(PatchType_Simple));
|
||||
MeshInfo& mesh = meshes.back();
|
||||
unsigned int subMeshIdx = 0;
|
||||
|
||||
if (!GetNextLine(buffer,line))
|
||||
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read number of vertices");break;}
|
||||
// read the name of the object, skip all spaces
|
||||
// at the end of it.
|
||||
const char* sz3 = sz;
|
||||
while (!IsSpaceOrNewLine(*sz))++sz;
|
||||
std::string objectName = std::string(sz3,(unsigned int)(sz-sz3));
|
||||
|
||||
SkipSpaces(line,&sz);
|
||||
const unsigned int objStart = (unsigned int)meshes.size();
|
||||
|
||||
// There could be a material table in a separate file
|
||||
std::vector<ShadingInfo> materialTable;
|
||||
while (true)
|
||||
{
|
||||
AI_NFF2_GET_NEXT_TOKEN();
|
||||
|
||||
// material table - an external file
|
||||
if (TokenMatch(sz,"mtable",6))
|
||||
{
|
||||
SkipSpaces(&sz);
|
||||
sz3 = sz;
|
||||
while (!IsSpaceOrNewLine(*sz))++sz;
|
||||
const unsigned int diff = (unsigned int)(sz-sz3);
|
||||
if (!diff)DefaultLogger::get()->warn("NFF2: Found empty mtable token");
|
||||
else
|
||||
{
|
||||
// The material table has the file extension .mat.
|
||||
// If it is not there, we need to append it
|
||||
std::string path = std::string(sz3,diff);
|
||||
if(std::string::npos == path.find_last_of(".mat"))
|
||||
{
|
||||
path.append(".mat");
|
||||
}
|
||||
|
||||
// Now extract the working directory from the path to
|
||||
// this file and append the material library filename
|
||||
// to it.
|
||||
std::string::size_type s;
|
||||
if ((std::string::npos == (s = path.find_last_of('\\')) || !s) &&
|
||||
(std::string::npos == (s = path.find_last_of('/')) || !s) )
|
||||
{
|
||||
s = pFile.find_last_of('\\');
|
||||
if (std::string::npos == s)s = pFile.find_last_of('/');
|
||||
if (std::string::npos != s)
|
||||
{
|
||||
path = pFile.substr(0,s+1) + path;
|
||||
}
|
||||
}
|
||||
LoadNFF2MaterialTable(materialTable,path,pIOHandler);
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
// read the numbr of vertices
|
||||
unsigned int num = ::strtol10(sz,&sz);
|
||||
|
||||
std::vector<aiVector3D> tempPositions;
|
||||
std::vector<aiVector3D> outPositions;
|
||||
mesh.vertices.reserve(num*3);
|
||||
mesh.colors.reserve (num*3);
|
||||
tempPositions.reserve(num);
|
||||
// temporary storage
|
||||
std::vector<aiColor4D> tempColors;
|
||||
std::vector<aiVector3D> tempPositions,tempTextureCoords,tempNormals;
|
||||
|
||||
bool hasNormals = false,hasUVs = false,hasColor = false;
|
||||
|
||||
tempPositions.reserve (num);
|
||||
tempColors.reserve (num);
|
||||
tempNormals.reserve (num);
|
||||
tempTextureCoords.reserve (num);
|
||||
for (unsigned int i = 0; i < num; ++i)
|
||||
{
|
||||
if (!GetNextLine(buffer,line))
|
||||
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read vertices");break;}
|
||||
|
||||
sz = line;
|
||||
AI_NFF2_GET_NEXT_TOKEN();
|
||||
aiVector3D v;
|
||||
AI_NFF_PARSE_TRIPLE(v);
|
||||
tempPositions.push_back(v);
|
||||
}
|
||||
if (!GetNextLine(buffer,line))
|
||||
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read number of faces");break;}
|
||||
|
||||
if (!num)throw new ImportErrorException("NFF2: There are zero vertices");
|
||||
|
||||
SkipSpaces(line,&sz);
|
||||
num = ::strtol10(sz,&sz);
|
||||
mesh.faces.reserve(num);
|
||||
|
||||
for (unsigned int i = 0; i < num; ++i)
|
||||
{
|
||||
if (!GetNextLine(buffer,line))
|
||||
{DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read faces");break;}
|
||||
|
||||
SkipSpaces(line,&sz);
|
||||
unsigned int idx, numIdx = ::strtol10(sz,&sz);
|
||||
if (numIdx)
|
||||
// parse all other attributes in the line
|
||||
while (true)
|
||||
{
|
||||
mesh.faces.push_back(numIdx);
|
||||
for (unsigned int a = 0; a < numIdx;++a)
|
||||
SkipSpaces(&sz);
|
||||
if (IsLineEnd(*sz))break;
|
||||
|
||||
// color definition
|
||||
if (TokenMatch(sz,"0x",2))
|
||||
{
|
||||
SkipSpaces(sz,&sz);
|
||||
idx = ::strtol10(sz,&sz);
|
||||
if (idx >= (unsigned int)tempPositions.size())
|
||||
{
|
||||
DefaultLogger::get()->error("NFF2: Index overflow");
|
||||
idx = 0;
|
||||
}
|
||||
mesh.vertices.push_back(tempPositions[idx]);
|
||||
hasColor = true;
|
||||
register unsigned int numIdx = ::strtol16(sz,&sz);
|
||||
aiColor4D clr;
|
||||
clr.a = 1.f;
|
||||
|
||||
// 0xRRGGBB
|
||||
clr.r = ((numIdx >> 16u) & 0xff) / 255.f;
|
||||
clr.g = ((numIdx >> 8u) & 0xff) / 255.f;
|
||||
clr.b = ((numIdx) & 0xff) / 255.f;
|
||||
tempColors.push_back(clr);
|
||||
}
|
||||
// normal vector
|
||||
else if (TokenMatch(sz,"norm",4))
|
||||
{
|
||||
hasNormals = true;
|
||||
AI_NFF_PARSE_TRIPLE(v);
|
||||
tempNormals.push_back(v);
|
||||
}
|
||||
// UV coordinate
|
||||
else if (TokenMatch(sz,"uv",2))
|
||||
{
|
||||
hasUVs = true;
|
||||
AI_NFF_PARSE_FLOAT(v.x);
|
||||
AI_NFF_PARSE_FLOAT(v.y);
|
||||
v.z = 0.f;
|
||||
tempTextureCoords.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
SkipSpaces(sz,&sz);
|
||||
idx = ::strtol_cppstyle(sz,&sz);
|
||||
aiColor4D clr;
|
||||
clr.r = ((numIdx >> 8u) & 0xf) / 16.f;
|
||||
clr.g = ((numIdx >> 4u) & 0xf) / 16.f;
|
||||
clr.b = ((numIdx) & 0xf) / 16.f;
|
||||
clr.a = 1.f;
|
||||
for (unsigned int a = 0; a < numIdx;++a)
|
||||
mesh.colors.push_back(clr);
|
||||
// fill in dummies for all attributes that have not been set
|
||||
if (tempNormals.size() != tempPositions.size())
|
||||
tempNormals.push_back(vQNAN);
|
||||
|
||||
if (tempTextureCoords.size() != tempPositions.size())
|
||||
tempTextureCoords.push_back(vQNAN);
|
||||
|
||||
if (tempColors.size() != tempPositions.size())
|
||||
tempColors.push_back(cQNAN);
|
||||
}
|
||||
|
||||
AI_NFF2_GET_NEXT_TOKEN();
|
||||
if (!num)throw new ImportErrorException("NFF2: There are zero vertices");
|
||||
num = ::strtol10(sz,&sz);
|
||||
|
||||
std::vector<unsigned int> tempIdx;
|
||||
tempIdx.reserve(10);
|
||||
for (unsigned int i = 0; i < num; ++i)
|
||||
{
|
||||
AI_NFF2_GET_NEXT_TOKEN();
|
||||
SkipSpaces(line,&sz);
|
||||
unsigned int numIdx = ::strtol10(sz,&sz);
|
||||
|
||||
// read all faces indices
|
||||
if (numIdx)
|
||||
{
|
||||
// mesh.faces.push_back(numIdx);
|
||||
// tempIdx.erase(tempIdx.begin(),tempIdx.end());
|
||||
tempIdx.resize(numIdx);
|
||||
|
||||
for (unsigned int a = 0; a < numIdx;++a)
|
||||
{
|
||||
SkipSpaces(sz,&sz);
|
||||
m = ::strtol10(sz,&sz);
|
||||
if (m >= (unsigned int)tempPositions.size())
|
||||
{
|
||||
DefaultLogger::get()->error("NFF2: Vertex index overflow");
|
||||
m= 0;
|
||||
}
|
||||
// mesh.vertices.push_back (tempPositions[idx]);
|
||||
tempIdx[a] = m;
|
||||
}
|
||||
}
|
||||
|
||||
// build a temporary shader object for the face.
|
||||
ShadingInfo shader;
|
||||
unsigned int matIdx = 0;
|
||||
|
||||
// white material color - we have vertex colors
|
||||
shader.color = aiColor3D(1.f,1.f,1.f);
|
||||
aiColor4D c = aiColor4D(1.f,1.f,1.f,1.f);
|
||||
while (true)
|
||||
{
|
||||
SkipSpaces(sz,&sz);
|
||||
if(IsLineEnd(*sz))break;
|
||||
|
||||
// per-polygon colors
|
||||
if (TokenMatch(sz,"0x",2))
|
||||
{
|
||||
hasColor = true;
|
||||
const char* sz2 = sz;
|
||||
numIdx = ::strtol16(sz,&sz);
|
||||
const unsigned int diff = (unsigned int)(sz-sz2);
|
||||
|
||||
// 0xRRGGBB
|
||||
if (diff > 3)
|
||||
{
|
||||
c.r = ((numIdx >> 16u) & 0xff) / 255.f;
|
||||
c.g = ((numIdx >> 8u) & 0xff) / 255.f;
|
||||
c.b = ((numIdx) & 0xff) / 255.f;
|
||||
}
|
||||
// 0xRGB
|
||||
else
|
||||
{
|
||||
c.r = ((numIdx >> 8u) & 0xf) / 16.f;
|
||||
c.g = ((numIdx >> 4u) & 0xf) / 16.f;
|
||||
c.b = ((numIdx) & 0xf) / 16.f;
|
||||
}
|
||||
}
|
||||
// TODO - implement texture mapping here
|
||||
#if 0
|
||||
// mirror vertex texture coordinate?
|
||||
else if (TokenMatch(sz,"mirror",6))
|
||||
{
|
||||
}
|
||||
// texture coordinate scaling
|
||||
else if (TokenMatch(sz,"scale",5))
|
||||
{
|
||||
}
|
||||
// texture coordinate translation
|
||||
else if (TokenMatch(sz,"trans",5))
|
||||
{
|
||||
}
|
||||
// texture coordinate rotation angle
|
||||
else if (TokenMatch(sz,"rot",3))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
// texture file name for this polygon + mapping information
|
||||
else if ('_' == sz[0])
|
||||
{
|
||||
// get mapping information
|
||||
switch (sz[1])
|
||||
{
|
||||
case 'v':
|
||||
case 'V':
|
||||
|
||||
shader.shaded = false;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
case 'T':
|
||||
case 'u':
|
||||
case 'U':
|
||||
|
||||
DefaultLogger::get()->warn("Unsupported NFF2 texture attribute: trans");
|
||||
};
|
||||
if (!sz[1] || '_' != sz[2])
|
||||
{
|
||||
DefaultLogger::get()->warn("NFF2: Expected underscore after texture attributes");
|
||||
continue;
|
||||
}
|
||||
const char* sz2 = sz+3;
|
||||
while (!IsSpaceOrNewLine( *sz ))++sz;
|
||||
const unsigned int diff = (unsigned int)(sz-sz2);
|
||||
if (diff)shader.texFile = std::string(sz2,diff);
|
||||
}
|
||||
|
||||
// Two-sided material?
|
||||
else if (TokenMatch(sz,"both",4))
|
||||
{
|
||||
shader.twoSided = true;
|
||||
}
|
||||
|
||||
// Material ID?
|
||||
else if (!materialTable.empty() && TokenMatch(sz,"matid",5))
|
||||
{
|
||||
SkipSpaces(&sz);
|
||||
matIdx = ::strtol10(sz,&sz);
|
||||
if (matIdx >= materialTable.size())
|
||||
{
|
||||
DefaultLogger::get()->error("NFF2: Material index overflow.");
|
||||
matIdx = 0;
|
||||
}
|
||||
|
||||
// now combine our current shader with the shader we
|
||||
// read from the material table.
|
||||
ShadingInfo& mat = materialTable[matIdx];
|
||||
shader.ambient = mat.ambient;
|
||||
shader.diffuse = mat.diffuse;
|
||||
shader.emissive = mat.emissive;
|
||||
shader.opacity = mat.opacity;
|
||||
shader.specular = mat.specular;
|
||||
shader.shininess = mat.shininess;
|
||||
}
|
||||
else SkipToken(sz);
|
||||
}
|
||||
|
||||
// search the list of all shaders we have for this object whether
|
||||
// there is an identical one. In this case, we append our mesh
|
||||
// data to it.
|
||||
MeshInfo* mesh = NULL;
|
||||
for (std::vector<MeshInfo>::iterator it = meshes.begin() + objStart, end = meshes.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
if ((*it).shader == shader && (*it).matIndex == matIdx)
|
||||
{
|
||||
// we have one, we can append our data to it
|
||||
mesh = &(*it);
|
||||
}
|
||||
}
|
||||
if (!mesh)
|
||||
{
|
||||
meshes.push_back(MeshInfo(PatchType_Simple,false));
|
||||
mesh = &meshes.back();
|
||||
mesh->matIndex = matIdx;
|
||||
|
||||
// We need to add a new mesh to the list. We assign
|
||||
// an unique name to it to make sure the scene will
|
||||
// pass the validation step for the moment.
|
||||
// TODO: fix naming of objects in the scenegraph later
|
||||
if (objectName.length())
|
||||
{
|
||||
::strcpy(mesh->name,objectName.c_str());
|
||||
itoa10(&mesh->name[objectName.length()],30,subMeshIdx++);
|
||||
}
|
||||
|
||||
// copy the shader to the mesh.
|
||||
mesh->shader = shader;
|
||||
}
|
||||
|
||||
// fill the mesh with data
|
||||
if (!tempIdx.empty())
|
||||
{
|
||||
mesh->faces.push_back((unsigned int)tempIdx.size());
|
||||
for (std::vector<unsigned int>::const_iterator it = tempIdx.begin(), end = tempIdx.end();
|
||||
it != end;++it)
|
||||
{
|
||||
m = *it;
|
||||
|
||||
// copy colors -vertex color specifications override polygon color specifications
|
||||
if (hasColor)
|
||||
{
|
||||
const aiColor4D& clr = tempColors[m];
|
||||
mesh->colors.push_back((is_qnan( clr.r ) ? c : clr));
|
||||
}
|
||||
|
||||
// positions should always be there
|
||||
mesh->vertices.push_back (tempPositions[m]);
|
||||
|
||||
// copy normal vectors
|
||||
if (hasNormals)
|
||||
mesh->normals.push_back (tempNormals[m]);
|
||||
|
||||
// copy texture coordinates
|
||||
if (hasUVs)
|
||||
mesh->uvs.push_back (tempTextureCoords[m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!num)throw new ImportErrorException("NFF2: There are zero faces");
|
||||
}
|
||||
|
@ -375,12 +756,17 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
AI_NFF_PARSE_TRIPLE(s.color);
|
||||
|
||||
// read the other properties
|
||||
AI_NFF_PARSE_FLOAT(s.diffuse);
|
||||
AI_NFF_PARSE_FLOAT(s.specular);
|
||||
AI_NFF_PARSE_FLOAT(s.diffuse.r);
|
||||
AI_NFF_PARSE_FLOAT(s.specular.r);
|
||||
AI_NFF_PARSE_FLOAT(d); // skip shininess and transmittance
|
||||
AI_NFF_PARSE_FLOAT(d);
|
||||
AI_NFF_PARSE_FLOAT(s.refracti);
|
||||
|
||||
// NFF2 uses full colors here so we need to use them too
|
||||
// although NFF uses simple scaling factors
|
||||
s.diffuse.g = s.diffuse.b = s.diffuse.r;
|
||||
s.specular.g = s.specular.b = s.specular.r;
|
||||
|
||||
// if the next one is NOT a number we assume it is a texture file name
|
||||
// this feature is used by some NFF files on the internet and it has
|
||||
// been implemented as it can be really useful
|
||||
|
@ -436,14 +822,12 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
currentMesh = &meshes.back();
|
||||
currentMesh->shader = s;
|
||||
}
|
||||
|
||||
if (!currentMeshWithNormals)
|
||||
{
|
||||
meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
|
||||
currentMeshWithNormals = &meshesWithNormals.back();
|
||||
currentMeshWithNormals->shader = s;
|
||||
}
|
||||
|
||||
if (!currentMeshWithUVCoords)
|
||||
{
|
||||
meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
|
||||
|
@ -676,7 +1060,11 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
c->mLookAt = camLookAt - camPos;
|
||||
c->mPosition = camPos;
|
||||
c->mUp = camUp;
|
||||
c->mAspect = resolution.x / resolution.y;
|
||||
|
||||
// If the resolution is not specified in the file we
|
||||
// need to set 1.0 as aspect. The division would become
|
||||
// INF otherwise.
|
||||
c->mAspect = (!resolution.y ? 0.f : resolution.x / resolution.y);
|
||||
++ppcChildren;
|
||||
}
|
||||
|
||||
|
@ -715,7 +1103,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
mesh->mNumVertices = (unsigned int)src.vertices.size();
|
||||
mesh->mNumFaces = (unsigned int)src.faces.size();
|
||||
|
||||
// generate sub nodes for named meshes
|
||||
// Generate sub nodes for named meshes
|
||||
if (src.name[0])
|
||||
{
|
||||
aiNode* const node = *ppcChildren = new aiNode();
|
||||
|
@ -754,7 +1142,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
sizeof(aiColor4D)*mesh->mNumVertices);
|
||||
}
|
||||
|
||||
if (src.pType != PatchType_Simple)
|
||||
if (!src.normals.empty())
|
||||
{
|
||||
ai_assert(src.normals.size() == src.vertices.size());
|
||||
|
||||
|
@ -764,7 +1152,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
sizeof(aiVector3D)*mesh->mNumVertices);
|
||||
}
|
||||
|
||||
if (src.pType == PatchType_UVAndNormals)
|
||||
if (!src.uvs.empty())
|
||||
{
|
||||
ai_assert(src.uvs.size() == src.vertices.size());
|
||||
|
||||
|
@ -800,11 +1188,39 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
c = src.shader.color * src.shader.specular;
|
||||
pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
|
||||
|
||||
// NFF2 - default values for NFF
|
||||
pcMat->AddProperty(&src.shader.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
|
||||
pcMat->AddProperty(&src.shader.emissive,1,AI_MATKEY_COLOR_EMISSIVE);
|
||||
pcMat->AddProperty(&src.shader.opacity, 1,AI_MATKEY_OPACITY);
|
||||
|
||||
// setup the first texture layer, if existing
|
||||
if (src.shader.texFile.length())
|
||||
{
|
||||
s.Set(src.shader.texFile);
|
||||
pcMat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
}
|
||||
|
||||
// setup the name of the material
|
||||
if (src.shader.name.length())
|
||||
{
|
||||
s.Set(src.shader.texFile);
|
||||
pcMat->AddProperty(&s,AI_MATKEY_NAME);
|
||||
}
|
||||
|
||||
// setup some more material properties that are specific to NFF2
|
||||
int i;
|
||||
if (src.shader.twoSided)
|
||||
{
|
||||
i = 1;
|
||||
pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
|
||||
}
|
||||
i = (src.shader.shaded ? aiShadingMode_Gouraud : aiShadingMode_NoShading);
|
||||
if (src.shader.shininess)
|
||||
{
|
||||
i = aiShadingMode_Phong;
|
||||
pcMat->AddProperty(&src.shader.shininess,1,AI_MATKEY_SHININESS);
|
||||
}
|
||||
pcMat->AddProperty(&i,1,AI_MATKEY_SHADING_MODEL);
|
||||
}
|
||||
pScene->mRootNode = root;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** NFF (Neutral File Format) Importer class
|
||||
/** NFF (Neutral File Format) Importer class.
|
||||
*
|
||||
* The class implements both Eric Haynes NFF format and Sense8's NFF (NFF2) format.
|
||||
* Both are quite different and the loading code is somewhat dirty at
|
||||
* the moment. Sense8 should be moved to a separate loader.
|
||||
*/
|
||||
class NFFImporter : public BaseImporter
|
||||
{
|
||||
|
@ -90,23 +94,35 @@ protected:
|
|||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
// describes face material properties
|
||||
struct ShadingInfo
|
||||
{
|
||||
ShadingInfo()
|
||||
: color(0.6f,0.6f,0.6f)
|
||||
, diffuse (1.f)
|
||||
, specular (1.f)
|
||||
, ambient (0.1f)
|
||||
: color (0.6f,0.6f,0.6f)
|
||||
, diffuse (1.f,1.f,1.f)
|
||||
, specular (1.f,1.f,1.f)
|
||||
, ambient (0.f,0.f,0.f)
|
||||
, emissive (0.f,0.f,0.f)
|
||||
, refracti (1.f)
|
||||
, twoSided (false) // for NFF2
|
||||
, shaded (true) // for NFF2
|
||||
, opacity (1.f)
|
||||
, shininess (0.f)
|
||||
{}
|
||||
|
||||
aiColor3D color;
|
||||
float diffuse, specular, ambient, refracti;
|
||||
aiColor3D color,diffuse,specular,ambient,emissive;
|
||||
float refracti;
|
||||
|
||||
std::string texFile;
|
||||
|
||||
// For NFF2
|
||||
bool twoSided;
|
||||
bool shaded;
|
||||
float opacity, shininess;
|
||||
|
||||
std::string name;
|
||||
|
||||
// shininess is ignored for the moment
|
||||
bool operator == (const ShadingInfo& other) const
|
||||
{
|
||||
|
@ -115,7 +131,12 @@ private:
|
|||
specular == other.specular &&
|
||||
ambient == other.ambient &&
|
||||
refracti == other.refracti &&
|
||||
texFile == other.texFile;
|
||||
texFile == other.texFile &&
|
||||
twoSided == other.twoSided &&
|
||||
shaded == other.shaded;
|
||||
|
||||
// Some properties from NFF2 aren't compared by this operator.
|
||||
// Comparing MeshInfo::matIndex should do that.
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -143,8 +164,10 @@ private:
|
|||
struct MeshInfo
|
||||
{
|
||||
MeshInfo(PatchType _pType, bool bL = false)
|
||||
: pType(_pType)
|
||||
, bLocked(bL)
|
||||
: pType (_pType)
|
||||
, bLocked (bL)
|
||||
, matIndex (0)
|
||||
, radius (1.f,1.f,1.f)
|
||||
{
|
||||
name[0] = '\0'; // by default meshes are unnamed
|
||||
}
|
||||
|
@ -159,9 +182,25 @@ private:
|
|||
char name[128];
|
||||
|
||||
std::vector<aiVector3D> vertices, normals, uvs;
|
||||
std::vector<aiColor4D> colors; // for NFF2
|
||||
std::vector<unsigned int> faces;
|
||||
|
||||
// for NFF2
|
||||
std::vector<aiColor4D> colors;
|
||||
unsigned int matIndex;
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads the material table for the NFF2 file format from an
|
||||
* external file.
|
||||
*
|
||||
* @param output Receives the list of output meshes
|
||||
* @param path Path to the file (abs. or rel.)
|
||||
* @param pIOHandler IOSystem to be used to open the file
|
||||
*/
|
||||
void LoadNFF2MaterialTable(std::vector<ShadingInfo>& output,
|
||||
const std::string& path, IOSystem* pIOHandler);
|
||||
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -75,7 +75,7 @@ bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|||
|
||||
|
||||
return !(extension.length() != 4 || extension[0] != '.' ||
|
||||
extension[1] != 'o' && extension[1] != 'R' ||
|
||||
extension[1] != 'o' && extension[1] != 'O' ||
|
||||
extension[2] != 'f' && extension[2] != 'F' ||
|
||||
extension[3] != 'f' && extension[3] != 'F');
|
||||
}
|
||||
|
|
|
@ -148,4 +148,10 @@ AI_FORCE_INLINE bool TokenMatch(char*& in, const char* token, unsigned int len)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
// ---------------------------------------------------------------------------------
|
||||
AI_FORCE_INLINE void SkipToken(const char*& in)
|
||||
{
|
||||
SkipSpaces(&in);
|
||||
while (!IsSpaceOrNewLine(*in))++in;
|
||||
}
|
||||
#endif // ! AI_PARSING_UTILS_H_INC
|
||||
|
|
|
@ -44,6 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "BaseProcess.h"
|
||||
#include "../include/aiMesh.h"
|
||||
|
||||
class RemoveVCProcessTest;
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
|
@ -53,6 +55,7 @@ namespace Assimp
|
|||
class ASSIMP_API RemoveVCProcess : public BaseProcess
|
||||
{
|
||||
friend class Importer;
|
||||
friend class ::RemoveVCProcessTest;
|
||||
|
||||
protected:
|
||||
/** Constructor to be privately used by Importer */
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
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 Implements Assimp::SceneCombiner. This is a smart utility
|
||||
* class that can be used to combine several scenes, meshes, ...
|
||||
* in one.
|
||||
*/
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
#include "SceneCombiner.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Merges two scenes. Currently only used by the LWS loader.
|
||||
void SceneCombiner::MergeScenes(aiScene* dest,std::vector<aiScene*>& src,
|
||||
unsigned int flags)
|
||||
{
|
||||
ai_assert(NULL != dest);
|
||||
ai_assert(0 == dest->mNumTextures);
|
||||
ai_assert(0 == dest->mNumLights);
|
||||
ai_assert(0 == dest->mNumCameras);
|
||||
ai_assert(0 == dest->mNumMeshes);
|
||||
ai_assert(0 == dest->mNumMaterials);
|
||||
|
||||
if (src.empty())return;
|
||||
|
||||
// some iterators will be needed multiple times
|
||||
std::vector<aiScene*>::iterator begin = src.begin(),
|
||||
end = src.end(), cur;
|
||||
|
||||
// this helper array is used as lookup table several times
|
||||
std::vector<unsigned int> offset(src.size());
|
||||
std::vector<unsigned int>::iterator ofsbegin = offset.begin(),
|
||||
offend = offset.end(), ofscur;
|
||||
|
||||
unsigned int cnt;
|
||||
bool bNeedPrefix = false;
|
||||
|
||||
// First find out how large the respective output arrays must be
|
||||
for ( cur = begin; cur != end; ++cur)
|
||||
{
|
||||
dest->mNumTextures += (*cur)->mNumTextures;
|
||||
dest->mNumMaterials += (*cur)->mNumMaterials;
|
||||
dest->mNumMeshes += (*cur)->mNumMeshes;
|
||||
dest->mNumLights += (*cur)->mNumLights;
|
||||
dest->mNumCameras += (*cur)->mNumCameras;
|
||||
dest->mNumAnimations += (*cur)->mNumAnimations;
|
||||
|
||||
if ((*cur)->mNumAnimations > 0 ||
|
||||
(*cur)->mNumCameras > 0 ||
|
||||
(*cur)->mNumLights > 0)bNeedPrefix = true;
|
||||
}
|
||||
|
||||
// generate the output texture list + an offset table
|
||||
if (dest->mNumTextures)
|
||||
{
|
||||
aiTexture** pip = dest->mTextures = new aiTexture*[dest->mNumMaterials];
|
||||
for ( cur = begin, ofscur = ofsbegin,cnt = 0; cur != end; ++cur,++ofscur)
|
||||
{
|
||||
for (unsigned int i = 0; i < (*cur)->mNumTextures;++i,++pip)
|
||||
*pip = (*cur)->mTextures[i];
|
||||
|
||||
*ofscur = cnt;
|
||||
cnt += (*cur)->mNumTextures;
|
||||
}
|
||||
}
|
||||
|
||||
// generate the output material list + an offset table
|
||||
if (dest->mNumMaterials)
|
||||
{
|
||||
aiMaterial** pip = dest->mMaterials = new aiMaterial*[dest->mNumMaterials];
|
||||
for ( cur = begin, ofscur = ofsbegin,cnt = 0; cur != end; ++cur,++ofscur)
|
||||
{
|
||||
for (unsigned int i = 0; i < (*cur)->mNumMaterials;++i,++pip)
|
||||
{
|
||||
*pip = (*cur)->mMaterials[i];
|
||||
|
||||
if ((*cur)->mNumTextures != dest->mNumTextures)
|
||||
{
|
||||
// We need to update all texture indices of the mesh.
|
||||
// So we need to search for a material property like
|
||||
// that follows the following pattern: "$tex.file.<s>.<n>"
|
||||
// where s is the texture type (i.e. diffuse) and n is
|
||||
// the index of the texture.
|
||||
|
||||
for (unsigned int a = 0; a < (*pip)->mNumProperties;++a)
|
||||
{
|
||||
aiMaterialProperty* prop = (*pip)->mProperties[a];
|
||||
if (!strncmp(prop->mKey.data,"$tex.file",9))
|
||||
{
|
||||
// Check whether this texture is an embedded texture.
|
||||
// In this case the property looks like this: *<n>,
|
||||
// where n is the index of the texture.
|
||||
aiString& s = *((aiString*)prop->mData);
|
||||
if ('*' == s.data[0])
|
||||
{
|
||||
// Offset the index and write it back ..
|
||||
const unsigned int idx = strtol10(&s.data[1]) + *ofscur;
|
||||
itoa10(&s.data[1],sizeof(s.data)-1,idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ofscur = cnt;
|
||||
cnt += (*cur)->mNumMaterials;
|
||||
}
|
||||
}
|
||||
|
||||
// generate the output mesh list + again an offset table
|
||||
if (dest->mNumMeshes)
|
||||
{
|
||||
aiMesh** pip = dest->mMeshes = new aiMesh*[dest->mNumMeshes];
|
||||
for ( cur = begin, ofscur = ofsbegin,cnt = 0; cur != end; ++cur,++ofscur)
|
||||
{
|
||||
for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i,++pip)
|
||||
{
|
||||
*pip = (*cur)->mMeshes[i];
|
||||
|
||||
// update the material index of the mesh
|
||||
(*pip)->mMaterialIndex += *ofscur;
|
||||
}
|
||||
|
||||
// reuse the offset array - store now the mesh offset in it
|
||||
*ofscur = cnt;
|
||||
cnt += (*cur)->mNumMeshes;
|
||||
}
|
||||
}
|
||||
|
||||
// Now generate the output node graph. We need to make those
|
||||
// names in the graph that are referenced by anims or lights
|
||||
// or cameras unique. So we add a prefix to them ... $SC1_
|
||||
// First step for now: find out which nodes are referenced by
|
||||
// anim bones or cameras and add the prefix to their names.
|
||||
|
||||
if (bNeedPrefix)
|
||||
{
|
||||
for (cur = begin, cnt = 0; cur != end; ++cur)
|
||||
{
|
||||
char buffer[10];
|
||||
buffer[0] = '$';
|
||||
buffer[1] = 'S';
|
||||
buffer[2] = 'C';
|
||||
|
||||
char* sz = &buffer[itoa10(&buffer[3],sizeof(buffer)-3, cnt++)+2];
|
||||
*sz++ = '_';
|
||||
*sz++ = '\0';
|
||||
|
||||
// AddNodePrefixes((*cur)->mRootNode,buffer,*cur);
|
||||
/** CONTINUE WORK HERE **/
|
||||
}
|
||||
}
|
||||
|
||||
// now copy all cameras
|
||||
|
||||
// now delete all input scenes
|
||||
for (cur = begin; cur != end; ++cur)
|
||||
{
|
||||
aiScene* deleteMe = *cur;
|
||||
|
||||
// We need to delete the arrays before the destructor is called -
|
||||
// we are reusing the array members
|
||||
delete[] deleteMe->mMeshes; deleteMe->mMeshes = NULL;
|
||||
delete[] deleteMe->mCameras; deleteMe->mCameras = NULL;
|
||||
delete[] deleteMe->mLights; deleteMe->mLights = NULL;
|
||||
delete[] deleteMe->mMaterials; deleteMe->mMaterials = NULL;
|
||||
delete[] deleteMe->mAnimations; deleteMe->mAnimations = NULL;
|
||||
|
||||
delete[] deleteMe->mRootNode->mChildren;
|
||||
deleteMe->mRootNode->mChildren = NULL;
|
||||
|
||||
// Now we can safely delete the scene
|
||||
delete[] deleteMe;
|
||||
AI_DEBUG_INVALIDATE_PTR(*cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SceneCombiner::MergeMeshes(aiMesh* dest,std::vector<aiMesh*>& src,
|
||||
unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
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 Declares a helper class, "SceneCombiner" providing various
|
||||
* utilities to merge scenes.
|
||||
*/
|
||||
#ifndef AI_SCENE_COMBINER_H_INC
|
||||
#define AI_SCENE_COMBINER_H_INC
|
||||
|
||||
#include "../include/aiAssert.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Static helper class providing various utilities to merge two
|
||||
* scenes. It is intended as internal utility and NOT for use by
|
||||
* applications.
|
||||
*
|
||||
* The class is currently being used by various postprocessing steps
|
||||
* and loaders (ie. LWS).
|
||||
*/
|
||||
class ASSIMP_API SceneCombiner
|
||||
{
|
||||
// class cannot be instanced
|
||||
SceneCombiner() {}
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Merges two or more scenes.
|
||||
*
|
||||
* @param dest Destination scene. Must be empty.
|
||||
* @param src Non-empty list of scenes to be merged. The function
|
||||
* deletes the input scenes afterwards.
|
||||
* @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
|
||||
*/
|
||||
static void MergeScenes(aiScene* dest,std::vector<aiScene*>& src,
|
||||
unsigned int flags);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Merges two or more meshes
|
||||
*
|
||||
* @param dest Destination mesh. Must be empty.
|
||||
* @param src Non-empty list of meshes to be merged. The function
|
||||
* deletes the input meshes afterwards.
|
||||
* @param flags Currently no parameters
|
||||
*/
|
||||
static void MergeMeshes(aiMesh* dest,std::vector<aiMesh*>& src,
|
||||
unsigned int flags);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // !! AI_SCENE_COMBINER_H_INC
|
|
@ -55,7 +55,6 @@ using namespace Assimp;
|
|||
// Constructor to be privately used by Importer
|
||||
DeterminePTypeHelperProcess ::DeterminePTypeHelperProcess()
|
||||
{
|
||||
bSpeedFlag = false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -73,13 +72,6 @@ bool DeterminePTypeHelperProcess::IsActive( unsigned int pFlags) const
|
|||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// called as a request to the step to update its configuration
|
||||
void DeterminePTypeHelperProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
bSpeedFlag = (pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0) ? true : false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void DeterminePTypeHelperProcess::Execute( aiScene* pScene)
|
||||
|
@ -88,59 +80,6 @@ void DeterminePTypeHelperProcess::Execute( aiScene* pScene)
|
|||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
{
|
||||
aiMesh* mesh = pScene->mMeshes[i];
|
||||
|
||||
// if the speed flag is not set search whether there are any degenerated
|
||||
// primitives in the mesh
|
||||
if (false && !bSpeedFlag)
|
||||
{
|
||||
unsigned int deg = 0;
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
||||
{
|
||||
aiFace& face = mesh->mFaces[a];
|
||||
bool first = true;
|
||||
|
||||
// check whether the face contains degenerated entries
|
||||
for (register unsigned int i = 0; i < face.mNumIndices; ++i)
|
||||
{
|
||||
for (register unsigned int a = i+1; a < face.mNumIndices; ++a)
|
||||
{
|
||||
if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[a]])
|
||||
{
|
||||
// we have found a matching vertex position
|
||||
// remove the corresponding index from the array
|
||||
for (unsigned int m = a; m < face.mNumIndices-1; ++m)
|
||||
{
|
||||
face.mIndices[m] = face.mIndices[m+1];
|
||||
}
|
||||
--a;
|
||||
--face.mNumIndices;
|
||||
|
||||
// NOTE: we set the removed vertex index to an unique value
|
||||
// to make sure the developer gets notified when his
|
||||
// application attemps to access this data.
|
||||
face.mIndices[face.mNumIndices] = 0xdeadbeef;
|
||||
|
||||
if(first)
|
||||
{
|
||||
++deg;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (deg)
|
||||
{
|
||||
char s[64];
|
||||
#if defined(_MSC_VER)
|
||||
::_itoa(deg,s,10);
|
||||
#else
|
||||
snprintf(s, 64, "%d", deg); //itoa is not available under linux
|
||||
#endif
|
||||
DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives");
|
||||
}
|
||||
}
|
||||
|
||||
if (!mesh->mPrimitiveTypes)
|
||||
{
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
||||
|
@ -248,6 +187,8 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
|||
std::vector<aiMesh*> outMeshes;
|
||||
outMeshes.reserve(pScene->mNumMeshes<<1u);
|
||||
|
||||
bool bAnyChanges = false;
|
||||
|
||||
std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*5,0xffffffff);
|
||||
std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
|
@ -288,7 +229,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
|||
++meshIdx;
|
||||
continue;
|
||||
}
|
||||
|
||||
bAnyChanges = true;
|
||||
const unsigned int first = (unsigned int)outMeshes.size();
|
||||
|
||||
// reuse our current mesh arrays for the submesh
|
||||
|
@ -468,7 +409,12 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
|||
delete mesh;
|
||||
}
|
||||
|
||||
UpdateNodes(replaceMeshIndex,pScene->mRootNode);
|
||||
// If we added at least one mesh process all nodes in the node
|
||||
// graph and update their respective mesh indices.
|
||||
if (bAnyChanges)
|
||||
{
|
||||
UpdateNodes(replaceMeshIndex,pScene->mRootNode);
|
||||
}
|
||||
|
||||
if (outMeshes.size() != pScene->mNumMeshes)
|
||||
{
|
||||
|
|
|
@ -73,12 +73,8 @@ public:
|
|||
// -------------------------------------------------------------------
|
||||
void Execute( aiScene* pScene);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
private:
|
||||
|
||||
bool bSpeedFlag;
|
||||
};
|
||||
|
||||
#if (!defined AI_BUILD_NO_SORTBYPTYPE_PROCESS)
|
||||
|
|
|
@ -46,6 +46,63 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// itoa is not consistently available on all platforms so it is quite useful
|
||||
// to have a small replacement function here. No need to use a full sprintf()
|
||||
// if we just want to print a number ...
|
||||
// @param out Output buffer
|
||||
// @param max Maximum number of characters to be written, including '\0'
|
||||
// @param number Number to be written
|
||||
// @return Number of bytes written. Including '\0'.
|
||||
// ---------------------------------------------------------------------------
|
||||
inline unsigned int itoa10( char* out, unsigned int max, int32_t number)
|
||||
{
|
||||
ai_assert(NULL != out);
|
||||
|
||||
static const char lookup[] = {'0','1','2','3','4','5','6','7','8','9'};
|
||||
|
||||
// write the unary minus to indicate we have a negative number
|
||||
unsigned int written = 1u;
|
||||
if (number < 0 && written < max)
|
||||
{
|
||||
*out++ = '-';
|
||||
++written;
|
||||
}
|
||||
|
||||
// We begin with the largest number that is not zero.
|
||||
int32_t cur = 1000000000; // 2147483648
|
||||
bool mustPrint = false;
|
||||
while (cur > 0 && written <= max)
|
||||
{
|
||||
unsigned int digit = number / cur;
|
||||
if (digit > 0 || mustPrint || 1 == cur)
|
||||
{
|
||||
// print all future zero's from now
|
||||
mustPrint = true;
|
||||
*out++ = lookup[digit];
|
||||
|
||||
++written;
|
||||
number -= digit*10;
|
||||
}
|
||||
cur /= 10;
|
||||
}
|
||||
|
||||
// append a terminal zero
|
||||
*out++ = '\0';
|
||||
return written;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Secure template overload
|
||||
// The compiler should choose this function if he is able to determine the
|
||||
// size of the array automatically.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <unsigned int length>
|
||||
inline unsigned int itoa10( char(& out)[length], int32_t number)
|
||||
{
|
||||
return itoa10(out,length,number);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Helper function to do platform independent string comparison.
|
||||
*
|
||||
|
@ -76,6 +133,9 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
|
|||
#endif
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Case independent comparison of two std::strings
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
|
||||
{
|
||||
|
|
|
@ -271,7 +271,7 @@ void ValidateDSProcess::Execute( aiScene* pScene)
|
|||
if (pScene->mNumMaterials)
|
||||
{
|
||||
has = true;
|
||||
DoValidation(pScene->mCameras,pScene->mNumCameras,"mMaterials","mNumMaterials");
|
||||
DoValidation(pScene->mMaterials,pScene->mNumMaterials,"mMaterials","mNumMaterials");
|
||||
}
|
||||
else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
|
||||
{
|
||||
|
@ -292,7 +292,7 @@ void ValidateDSProcess::Validate( const aiLight* pLight)
|
|||
!pLight->mAttenuationLinear &&
|
||||
!pLight->mAttenuationQuadratic)
|
||||
{
|
||||
ReportError("aiLight::mAttenuationXXX - all are zero");
|
||||
ReportWarning("aiLight::mAttenuationXXX - all are zero");
|
||||
}
|
||||
|
||||
if (pLight->mAngleInnerCone > pLight->mAngleOuterCone)
|
||||
|
@ -301,7 +301,7 @@ void ValidateDSProcess::Validate( const aiLight* pLight)
|
|||
if (pLight->mColorDiffuse.IsBlack() && pLight->mColorAmbient.IsBlack()
|
||||
&& pLight->mColorSpecular.IsBlack())
|
||||
{
|
||||
ReportError("aiLight::mColorXXX - all are black and won't have any influence");
|
||||
ReportWarning("aiLight::mColorXXX - all are black and won't have any influence");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,12 +411,15 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
|||
abRefList[face.mIndices[a]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// check whether there are vertices that aren't referenced by a face
|
||||
bool b = false;
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
||||
{
|
||||
if (!abRefList[i])this->ReportError("aiMesh::mVertices[%i] is not referenced",i);
|
||||
if (!abRefList[i])b = true;
|
||||
}
|
||||
abRefList.clear();
|
||||
if (b)ReportWarning("There are unreferenced vertices");
|
||||
|
||||
// texture channel 2 may not be set if channel 1 is zero ...
|
||||
{
|
||||
|
@ -428,7 +431,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
|||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
if (pMesh->HasTextureCoords(i))
|
||||
{
|
||||
ReportError("Texture coordinate channel %i is existing, "
|
||||
ReportError("Texture coordinate channel %i exists "
|
||||
"although the previous channel was NULL.",i);
|
||||
}
|
||||
}
|
||||
|
@ -442,7 +445,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
|||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||
if (pMesh->HasVertexColors(i))
|
||||
{
|
||||
ReportError("Vertex color channel %i is existing, "
|
||||
ReportError("Vertex color channel %i is exists "
|
||||
"although the previous channel was NULL.",i);
|
||||
}
|
||||
}
|
||||
|
@ -589,11 +592,13 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
|
|||
this->ReportError("%s #%i is set, but there are only %i %s textures",
|
||||
szType,iIndex,iNumIndices,szType);
|
||||
}
|
||||
if (!iNumIndices)return;
|
||||
|
||||
// now check whether all UV indices are valid ...
|
||||
iLen = ::sprintf(szBaseBuf,"$tex.uvw.%s",szType);
|
||||
if (0 >= iLen)return;
|
||||
|
||||
|
||||
bool bNoSpecified = true;
|
||||
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
|
||||
{
|
||||
aiMaterialProperty* prop = pMaterial->mProperties[i];
|
||||
|
@ -607,6 +612,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
|
|||
{
|
||||
++sz;
|
||||
iIndex = strtol10(sz,NULL);
|
||||
bNoSpecified = false;
|
||||
|
||||
// ignore UV indices for texture channel that are not there ...
|
||||
if (iIndex >= iNumIndices)
|
||||
|
@ -616,13 +622,13 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
|
|||
|
||||
// check whether there is a mesh using this material
|
||||
// which has not enough UV channels ...
|
||||
for (unsigned int a = 0; a < this->mScene->mNumMeshes;++a)
|
||||
for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
|
||||
{
|
||||
aiMesh* mesh = this->mScene->mMeshes[a];
|
||||
if(mesh->mMaterialIndex == (unsigned int)iIndex)
|
||||
{
|
||||
int iChannels = 0;
|
||||
while (mesh->HasTextureCoords(iChannels++));
|
||||
while (mesh->HasTextureCoords(iChannels))++iChannels;
|
||||
if (iIndex >= iChannels)
|
||||
{
|
||||
this->ReportError("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
|
||||
|
@ -634,6 +640,24 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (bNoSpecified)
|
||||
{
|
||||
// Assume that all textures are using the first UV channel
|
||||
for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
|
||||
{
|
||||
aiMesh* mesh = this->mScene->mMeshes[a];
|
||||
if(mesh->mMaterialIndex == (unsigned int)iIndex)
|
||||
{
|
||||
if (!mesh->mTextureCoords[0])
|
||||
{
|
||||
// This is a special case ... it could be that the
|
||||
// original mesh format intended the use of a special
|
||||
// mapping here.
|
||||
ReportWarning("UV-mapped texture, but there are no UV coords");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
|
||||
|
|
|
@ -61,6 +61,7 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
|
|||
{
|
||||
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)
|
||||
{
|
||||
ai_assert(3 == pcFace->mNumIndices);
|
||||
iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
|
||||
iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
|
||||
iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]);
|
||||
|
|
|
@ -40,6 +40,8 @@ const float fast_atof_table[16] = { // we write [16] here instead of [] to work
|
|||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// convert a string in decimal format to a number
|
||||
// ------------------------------------------------------------------------------------
|
||||
inline unsigned int strtol10( const char* in, const char** out=0)
|
||||
{
|
||||
|
@ -57,6 +59,8 @@ inline unsigned int strtol10( const char* in, const char** out=0)
|
|||
return value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// convert a string in octal format to a number
|
||||
// ------------------------------------------------------------------------------------
|
||||
inline unsigned int strtol8( const char* in, const char** out=0)
|
||||
{
|
||||
|
@ -76,6 +80,7 @@ inline unsigned int strtol8( const char* in, const char** out=0)
|
|||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// convert a string in hex format to a number
|
||||
// ------------------------------------------------------------------------------------
|
||||
inline unsigned int strtol16( const char* in, const char** out=0)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
|
@ -101,8 +106,9 @@ inline unsigned int strtol16( const char* in, const char** out=0)
|
|||
return value;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------
|
||||
// convert just one hex digit
|
||||
// ------------------------------------------------------------------------------------
|
||||
inline unsigned int HexDigitToDecimal(char in)
|
||||
{
|
||||
unsigned int out = 0xffffffff;
|
||||
|
@ -121,6 +127,7 @@ inline unsigned int HexDigitToDecimal(char in)
|
|||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// signed variant of strtol10
|
||||
// ------------------------------------------------------------------------------------
|
||||
inline int strtol10s( const char* in, const char** out=0)
|
||||
{
|
||||
bool bNeg = false;
|
||||
|
@ -132,9 +139,11 @@ inline int strtol10s( const char* in, const char** out=0)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Parse a C++-like integer literal - hex and oct prefixes.
|
||||
// 0xNNNN - hex
|
||||
// 0NNN - oct
|
||||
// NNN - dec
|
||||
// ------------------------------------------------------------------------------------
|
||||
inline unsigned int strtol_cppstyle( const char* in, const char** out=0)
|
||||
{
|
||||
if ('0' == in[0])
|
||||
|
@ -145,7 +154,9 @@ inline unsigned int strtol_cppstyle( const char* in, const char** out=0)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// specal version of the function, providing higher accuracy
|
||||
// Special version of the function, providing higher accuracy
|
||||
// It is mainly used bx fast_atof to prevent ugly integer overflows.
|
||||
// ------------------------------------------------------------------------------------
|
||||
inline uint64_t strtol10_64( const char* in, const char** out=0)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
|
@ -168,6 +179,7 @@ inline uint64_t strtol10_64( const char* in, const char** out=0)
|
|||
//! Provides a fast function for converting a string into a float,
|
||||
//! about 6 times faster than atof in win32.
|
||||
// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
|
||||
// ------------------------------------------------------------------------------------
|
||||
inline const char* fast_atof_move( const char* c, float& out)
|
||||
{
|
||||
bool inv = false;
|
||||
|
|
|
@ -63,6 +63,10 @@ SOURCES = AssimpPCH.cpp \
|
|||
FindInvalidDataProcess.cpp \
|
||||
ACLoader.cpp \
|
||||
LWSLoader.cpp \
|
||||
BVHLoader.cpp \
|
||||
SceneCombiner.cpp \
|
||||
SkeletonMeshBuilder.cpp \
|
||||
FindDegenerates.cpp \
|
||||
XFileParser.cpp
|
||||
|
||||
OBJECTS = $(SOURCES:.cpp=.o)
|
||||
|
|
|
@ -63,7 +63,11 @@ SOURCES = AssimpPCH.cpp \
|
|||
FindInvalidDataProcess.cpp \
|
||||
ACLoader.cpp \
|
||||
LWSLoader.cpp \
|
||||
XFileParser.cpp
|
||||
XFileParser.cpp \
|
||||
SceneCombiner.cpp \
|
||||
FindDegenerates.cpp \
|
||||
SkeletonMeshBuilder.cpp \
|
||||
BVHLoader.cpp
|
||||
|
||||
OBJECTS = $(SOURCES:.cpp=.o)
|
||||
|
||||
|
|
|
@ -218,7 +218,25 @@ enum aiPostProcessSteps
|
|||
* especially useful for real-time rendering where point and line
|
||||
* primitives are often ignored or rendered separately.
|
||||
*/
|
||||
aiProcess_SortByPType = 0x8000
|
||||
aiProcess_SortByPType = 0x8000,
|
||||
|
||||
/** This step searches all meshes for degenerated primitives and
|
||||
* converts them to proper lines or points.
|
||||
*
|
||||
* A face is degenerated if one or more of its faces are identical.
|
||||
*/
|
||||
aiProcess_FindDegenerates = 0x10000,
|
||||
|
||||
|
||||
/** This step searches all meshes for invalid data, such as zeroed
|
||||
* normal vectors or invalid UV coords and removes them.
|
||||
*
|
||||
* This is especially useful for normals. If they are invalid, and
|
||||
* the step recognizes this, they will be removed and can later
|
||||
* be computed by one of the other steps.<br>
|
||||
* The step will also remove meshes that are infinitely small.
|
||||
*/
|
||||
aiProcess_FindInvalidData = 0x20000,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# viewpoint
|
||||
v
|
||||
from 0 3 10
|
||||
at 0 0 0
|
||||
up 0 1 0
|
||||
angle 60
|
||||
hither 0
|
||||
resolution 640 480
|
||||
|
||||
f 1 0 0 0.8 .8 20 0 1
|
||||
s -2 0.8 0 2
|
||||
|
||||
f 0 1 0 0.8 .8 20 0 1
|
||||
s 1 -1.5 1 2.2
|
||||
|
||||
f 0 0 1 0.8 .8 20 0 1
|
||||
s 3 3 -2 2
|
||||
|
||||
f 1 1 1 0.8 .8 20 0 1
|
||||
p 4
|
||||
-7 -1 -7
|
||||
-7 -1 7
|
||||
7 -1 7
|
||||
7 -1 -7
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
|||
mat // cokecan.mat, Materials for coke texture example
|
||||
version 3.0
|
||||
valid ambientdiffuse specular shininess opacity
|
||||
|
||||
matdef // #0 Shiny silver ( aluminum )
|
||||
ambientdiffuse 0.9 0.9 0.9
|
||||
specular 1.0 1.0 1.0
|
||||
shininess 128.0
|
||||
|
||||
matdef // #1 Semi-Transparent Green
|
||||
ambientdiffuse 0.0 1.0 0.0
|
||||
opacity 0.6
|
|
@ -0,0 +1,39 @@
|
|||
nff // cokecan.nff, A file designed to illustrate uv texturing
|
||||
version 3.0
|
||||
|
||||
Coke_Can
|
||||
mtable cokecan.mat
|
||||
|
||||
18 // Eighteen vertices
|
||||
|
||||
10.0 -37.0 0.0 uv 0.0 1.0 // #0 Start around top of can
|
||||
7.071 -37.0 7.071 uv 0.125 1.0 // #1
|
||||
0.0 -37.0 10.0 uv 0.25 1.0 // #2
|
||||
-7.071 -37.0 7.071 uv 0.375 1.0 // #3
|
||||
-10.0 -37.0 0.0 uv 0.5 1.0 // #4
|
||||
-7.071 -37.0 -7.071 uv 0.625 1.0 // #5
|
||||
0.0 -37.0 -10.0 uv 0.75 1.0 // #6
|
||||
7.071 -37.0 -7.071 uv 0.875 1.0 // #7
|
||||
10.0 -37.0 0.0 uv 1.0 1.0 // #8 ( Same as #0 except u value )
|
||||
|
||||
10.0 0.0 0.0 uv 0.0 0.0 // #9 Repeat around bottom of can
|
||||
7.071 0.0 7.071 uv 0.125 0.0 // #10
|
||||
0.0 0.0 10.0 uv 0.25 0.0 // #11
|
||||
-7.071 0.0 7.071 uv 0.375 0.0 // #12
|
||||
-10.0 0.0 0.0 uv 0.5 0.0 // #13
|
||||
-7.071 0.0 -7.071 uv 0.625 0.0 // #14
|
||||
0.0 0.0 -10.0 uv 0.75 0.0 // #15
|
||||
7.071 0.0 -7.071 uv 0.875 0.0 // #16
|
||||
10.0 0.0 0.0 uv 0.0 0.0 // #17 ( Same as #9 except u value )
|
||||
|
||||
10 // Ten polygons
|
||||
8 0 1 2 3 4 5 6 7 matid 0 // Top of can. Note lack of "both"
|
||||
8 9 10 11 12 13 14 15 16 matid 0 both // Bottom of can
|
||||
4 9 10 1 0 matid 0 both _V_cokelabl.tga // Vanilla texture on silver
|
||||
4 10 11 2 1 matid 0 both _S_cokelabl.tga // Shaded texture on silver
|
||||
4 11 12 3 2 matid 0 both _T_cokelabl.tga // Transparent texture on silver
|
||||
4 12 13 4 3 matid 0 both _U_cokelabl.tga // Shaded & Transparent on silver
|
||||
4 13 14 5 4 matid 1 both _V_cokelabl.tga // Vanilla texture on green
|
||||
4 14 15 6 5 matid 1 both _S_cokelabl.tga // Shaded texture on green
|
||||
4 15 16 7 6 matid 1 both _T_cokelabl.tga // Transparent texture on green
|
||||
4 16 17 8 7 matid 1 both _U_cokelabl.tga // Shaded & Transparent on green
|
|
@ -0,0 +1,4 @@
|
|||
teapot.nff, home4.nff - http://www.martinreddy.net/ukvrsig/wtk.html
|
||||
|
||||
cokecan.nff -www.vrupl.evl.uic.edu/Eng591_Pages/cokecan.nff
|
||||
TODO: License status to be confirmed
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,16 @@
|
|||
OFF
|
||||
353535235358 6 0
|
||||
-0.500000 -0.500000 0.500000
|
||||
0.500000 -0.500000 0.500000
|
||||
-0.500000 0.500000 0.500000
|
||||
0.500000 0.500000 0.500000
|
||||
-0.500000 0.500000 -0.500000
|
||||
0.500000 0.500000 -0.500000
|
||||
-0.500000 -0.500000 -0.500000
|
||||
0.500000 -0.500000 -0.500000
|
||||
4 0 1 3 2
|
||||
4 2 3 5 4
|
||||
4 4 5 7 6
|
||||
4 6 7 1 0
|
||||
4 1 7 5 3
|
||||
4 6 0 2 4
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
*********************************************************
|
||||
GENERAL
|
||||
*********************************************************
|
||||
|
||||
|
||||
The files in this directory are invalid ... some of them are empty,
|
||||
others have invalid vertices or faces, others are prepared to make
|
||||
assimp allocate a few hundreds gigs of memory ...
|
||||
|
||||
This test case is successful if the library (and the viewer) don't
|
||||
crash.
|
||||
|
||||
|
||||
*********************************************************
|
||||
FILES
|
||||
*********************************************************
|
||||
|
||||
OutOfMemory.off - the number of faces is invalid. There won't be
|
||||
enough memory so std::vector::reserve() will most likely fail.
|
||||
The exception should be caught in Importer.cpp.
|
||||
|
||||
empty.<x> - These files are completely empty. The corresponding
|
||||
loaders should not crash.
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include "utRemoveComponent.h"
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION (RemoveVCProcessTest);
|
||||
|
||||
void RemoveVCProcessTest :: setUp (void)
|
||||
{
|
||||
// construct the process
|
||||
piProcess = new RemoveVCProcess();
|
||||
pScene = new aiScene();
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest :: tearDown (void)
|
||||
{
|
||||
delete pScene;
|
||||
delete piProcess;
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testMeshRemove (void)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testAnimRemove (void)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testMaterialRemove (void)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testTextureRemove (void)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testCameraRemove (void)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testLightRemove (void)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testMeshComponentsRemoveA (void)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testMeshComponentsRemoveB (void)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoveVCProcessTest::testRemoveEverything (void)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef TESTLBW_H
|
||||
#define TESTLBW_H
|
||||
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include <aiScene.h>
|
||||
#include <RemoveVCProcess.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace Assimp;
|
||||
|
||||
class RemoveVCProcessTest : public CPPUNIT_NS :: TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE (RemoveVCProcessTest);
|
||||
CPPUNIT_TEST (testMeshRemove);
|
||||
CPPUNIT_TEST (testAnimRemove);
|
||||
CPPUNIT_TEST (testMaterialRemove);
|
||||
CPPUNIT_TEST (testTextureRemove);
|
||||
CPPUNIT_TEST (testCameraRemove);
|
||||
CPPUNIT_TEST (testLightRemove);
|
||||
CPPUNIT_TEST (testMeshComponentsRemoveA);
|
||||
CPPUNIT_TEST (testMeshComponentsRemoveB);
|
||||
CPPUNIT_TEST (testRemoveEverything);
|
||||
CPPUNIT_TEST_SUITE_END ();
|
||||
|
||||
public:
|
||||
void setUp (void);
|
||||
void tearDown (void);
|
||||
|
||||
protected:
|
||||
|
||||
void testMeshRemove (void);
|
||||
void testAnimRemove (void);
|
||||
void testMaterialRemove (void);
|
||||
void testTextureRemove (void);
|
||||
void testCameraRemove (void);
|
||||
void testLightRemove (void);
|
||||
|
||||
void testMeshComponentsRemoveA (void);
|
||||
void testMeshComponentsRemoveB (void);
|
||||
void testRemoveEverything (void);
|
||||
|
||||
private:
|
||||
|
||||
RemoveVCProcess* piProcess;
|
||||
aiScene* pScene;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -786,93 +786,97 @@ int CMaterialManager::CreateMaterial(
|
|||
|
||||
aiString szPath;
|
||||
|
||||
//
|
||||
// DIFFUSE TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath))
|
||||
if (pcSource->mTextureCoords[0])
|
||||
{
|
||||
LoadTexture(&pcMesh->piDiffuseTexture,&szPath);
|
||||
}
|
||||
|
||||
//
|
||||
// SPECULAR TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piSpecularTexture,&szPath);
|
||||
}
|
||||
|
||||
//
|
||||
// OPACITY TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piOpacityTexture,&szPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to find out whether the diffuse texture has any
|
||||
// non-opaque pixels. If we find a few, use it as opacity texture
|
||||
if (pcMesh->piDiffuseTexture && HasAlphaPixels(pcMesh->piDiffuseTexture))
|
||||
//
|
||||
// DIFFUSE TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath))
|
||||
{
|
||||
int iVal;
|
||||
LoadTexture(&pcMesh->piDiffuseTexture,&szPath);
|
||||
}
|
||||
|
||||
// NOTE: This special value is set by the tree view if the user
|
||||
// manually removes the alpha texture from the view ...
|
||||
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",&iVal))
|
||||
//
|
||||
// SPECULAR TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piSpecularTexture,&szPath);
|
||||
}
|
||||
|
||||
//
|
||||
// OPACITY TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piOpacityTexture,&szPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to find out whether the diffuse texture has any
|
||||
// non-opaque pixels. If we find a few, use it as opacity texture
|
||||
if (pcMesh->piDiffuseTexture && HasAlphaPixels(pcMesh->piDiffuseTexture))
|
||||
{
|
||||
pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture;
|
||||
pcMesh->piOpacityTexture->AddRef();
|
||||
int iVal;
|
||||
|
||||
// NOTE: This special value is set by the tree view if the user
|
||||
// manually removes the alpha texture from the view ...
|
||||
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",&iVal))
|
||||
{
|
||||
pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture;
|
||||
pcMesh->piOpacityTexture->AddRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// AMBIENT TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piAmbientTexture,&szPath);
|
||||
}
|
||||
//
|
||||
// AMBIENT TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piAmbientTexture,&szPath);
|
||||
}
|
||||
|
||||
//
|
||||
// EMISSIVE TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piEmissiveTexture,&szPath);
|
||||
}
|
||||
//
|
||||
// EMISSIVE TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piEmissiveTexture,&szPath);
|
||||
}
|
||||
|
||||
//
|
||||
// Shininess TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piShininessTexture,&szPath);
|
||||
}
|
||||
//
|
||||
// Shininess TEXTURE ------------------------------------------------
|
||||
//
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piShininessTexture,&szPath);
|
||||
}
|
||||
|
||||
//
|
||||
// NORMAL/HEIGHT MAP ------------------------------------------------
|
||||
//
|
||||
bool bHM = false;
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piNormalTexture,&szPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0),&szPath))
|
||||
//
|
||||
// NORMAL/HEIGHT MAP ------------------------------------------------
|
||||
//
|
||||
bool bHM = false;
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piNormalTexture,&szPath);
|
||||
}
|
||||
bHM = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0),&szPath))
|
||||
{
|
||||
LoadTexture(&pcMesh->piNormalTexture,&szPath);
|
||||
}
|
||||
bHM = true;
|
||||
}
|
||||
|
||||
// normal/height maps are sometimes mixed up. Try to detect the type
|
||||
// of the texture automatically
|
||||
if (pcMesh->piNormalTexture)
|
||||
{
|
||||
HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM);
|
||||
// normal/height maps are sometimes mixed up. Try to detect the type
|
||||
// of the texture automatically
|
||||
if (pcMesh->piNormalTexture)
|
||||
{
|
||||
HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM);
|
||||
}
|
||||
}
|
||||
|
||||
// check whether a global background texture is contained
|
||||
|
|
|
@ -135,7 +135,8 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
|
|||
aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space
|
||||
aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes
|
||||
aiProcess_ValidateDataStructure | aiProcess_ImproveCacheLocality
|
||||
| aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType); // validate the output data structure
|
||||
| aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType | aiProcess_FindDegenerates |
|
||||
aiProcess_FindInvalidData); // validate the output data structure
|
||||
|
||||
// get the end time of zje operation, calculate delta t
|
||||
double fEnd = (double)timeGetTime();
|
||||
|
|
|
@ -675,14 +675,6 @@
|
|||
RelativePath="..\..\test\unit\Main.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\test\unit\RemoveComponent.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\test\unit\RemoveComponent.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\test\unit\utFindInvalidData.cpp"
|
||||
>
|
||||
|
@ -763,6 +755,14 @@
|
|||
RelativePath="..\..\test\unit\utRemoveComments.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\test\unit\utRemoveComponent.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\test\unit\utRemoveComponent.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\test\unit\utRemoveRedundantMaterials.cpp"
|
||||
>
|
||||
|
|
|
@ -787,10 +787,6 @@
|
|||
RelativePath="..\..\code\DefaultLogger.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FaceEdgeAdjacency.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\fast_atof.h"
|
||||
>
|
||||
|
@ -839,6 +835,14 @@
|
|||
RelativePath="..\..\code\RemoveComments.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\SceneCombiner.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\SceneCombiner.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\SGSpatialSort.cpp"
|
||||
>
|
||||
|
@ -1370,6 +1374,14 @@
|
|||
RelativePath="..\..\code\ConvertToLHProcess.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindDegenerates.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindDegenerates.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FindInvalidDataProcess.cpp"
|
||||
>
|
||||
|
|
|
@ -763,10 +763,6 @@
|
|||
RelativePath="..\..\tools\assimp_view\MessageProc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\tools\assimp_view\no_materials.fx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\tools\assimp_view\Normals.cpp"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue