First half-working version of the ASE loader
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@46 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
9c4968da33
commit
74dfe61c1e
|
@ -49,13 +49,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "../include/aiMesh.h"
|
#include "../include/aiMesh.h"
|
||||||
#include "../include/aiScene.h"
|
#include "../include/aiScene.h"
|
||||||
#include "../include/aiAssert.h"
|
#include "../include/aiAssert.h"
|
||||||
|
#include "../include/DefaultLogger.h"
|
||||||
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
using namespace Assimp::ASE;
|
using namespace Assimp::ASE;
|
||||||
|
|
||||||
#define LOGOUT_WARN(x)
|
#define LOGOUT_WARN(x) DefaultLogger::get()->warn(x);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
|
@ -85,6 +86,8 @@ bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
||||||
if (extension[2] != 's' && extension[2] != 'S')return false;
|
if (extension[2] != 's' && extension[2] != 'S')return false;
|
||||||
|
|
||||||
// NOTE: Sometimes the extension .ASK is also used
|
// NOTE: Sometimes the extension .ASK is also used
|
||||||
|
// however, often it only contains static animation skeletons
|
||||||
|
// without the real animations.
|
||||||
if (extension[3] != 'e' && extension[3] != 'E' &&
|
if (extension[3] != 'e' && extension[3] != 'E' &&
|
||||||
extension[3] != 'k' && extension[3] != 'K')return false;
|
extension[3] != 'k' && extension[3] != 'K')return false;
|
||||||
|
|
||||||
|
@ -105,6 +108,14 @@ void ASEImporter::InternReadFile(
|
||||||
|
|
||||||
size_t fileSize = file->FileSize();
|
size_t fileSize = file->FileSize();
|
||||||
|
|
||||||
|
std::string::size_type pos = pFile.find_last_of('.');
|
||||||
|
std::string extension = pFile.substr( pos);
|
||||||
|
if(extension[3] == 'k' || extension[3] == 'K')
|
||||||
|
{
|
||||||
|
this->mIsAsk = true;
|
||||||
|
}
|
||||||
|
else this->mIsAsk = false;
|
||||||
|
|
||||||
// allocate storage and copy the contents of the file to a memory buffer
|
// allocate storage and copy the contents of the file to a memory buffer
|
||||||
// (terminate it with zero)
|
// (terminate it with zero)
|
||||||
this->mBuffer = new unsigned char[fileSize+1];
|
this->mBuffer = new unsigned char[fileSize+1];
|
||||||
|
@ -120,12 +131,19 @@ void ASEImporter::InternReadFile(
|
||||||
i = this->mParser->m_vMeshes.begin();
|
i = this->mParser->m_vMeshes.begin();
|
||||||
i != this->mParser->m_vMeshes.end();++i)
|
i != this->mParser->m_vMeshes.end();++i)
|
||||||
{
|
{
|
||||||
// need to generate proper vertex normals if necessary
|
// transform all vertices into worldspace
|
||||||
this->GenerateNormals(*i);
|
// world2obj transform is specified in the
|
||||||
|
// transformation matrix of a scenegraph node
|
||||||
|
this->TransformVertices(*i);
|
||||||
|
|
||||||
// now we need to create proper meshes from the import
|
// now we need to create proper meshes from the import
|
||||||
// we need to split them by materials, build valid vertex/face lists ...
|
// we need to split them by materials, build valid vertex/face lists ...
|
||||||
this->BuildUniqueRepresentation(*i);
|
this->BuildUniqueRepresentation(*i);
|
||||||
|
|
||||||
|
// need to generate proper vertex normals if necessary
|
||||||
|
this->GenerateNormals(*i);
|
||||||
|
|
||||||
|
// convert all meshes to aiMesh objects
|
||||||
this->ConvertMeshes(*i,pScene);
|
this->ConvertMeshes(*i,pScene);
|
||||||
}
|
}
|
||||||
// buil final material indices (remove submaterials and make the final list)
|
// buil final material indices (remove submaterials and make the final list)
|
||||||
|
@ -206,6 +224,23 @@ void ASEImporter::BuildNodes(aiScene* pcScene)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void ASEImporter::TransformVertices(ASE::Mesh& mesh)
|
||||||
|
{
|
||||||
|
// the matrix data is stored in column-major format,
|
||||||
|
// but we need row major
|
||||||
|
mesh.mTransform.Transpose();
|
||||||
|
|
||||||
|
aiMatrix4x4 m = mesh.mTransform;
|
||||||
|
m.Inverse();
|
||||||
|
|
||||||
|
for (std::vector<aiVector3D>::iterator
|
||||||
|
i = mesh.mPositions.begin();
|
||||||
|
i != mesh.mPositions.end();++i)
|
||||||
|
{
|
||||||
|
(*i) = m * (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
|
void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
|
||||||
{
|
{
|
||||||
// allocate output storage
|
// allocate output storage
|
||||||
|
@ -213,6 +248,7 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
|
||||||
std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||||
std::vector<aiColor4D> mVertexColors;
|
std::vector<aiColor4D> mVertexColors;
|
||||||
std::vector<aiVector3D> mNormals;
|
std::vector<aiVector3D> mNormals;
|
||||||
|
std::vector<BoneVertex> mBoneVertices;
|
||||||
|
|
||||||
unsigned int iSize = mesh.mFaces.size() * 3;
|
unsigned int iSize = mesh.mFaces.size() * 3;
|
||||||
mPositions.resize(iSize);
|
mPositions.resize(iSize);
|
||||||
|
@ -236,6 +272,11 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
|
||||||
{
|
{
|
||||||
mNormals.resize(iSize);
|
mNormals.resize(iSize);
|
||||||
}
|
}
|
||||||
|
// bone vertices. There is no need to change the bone list
|
||||||
|
if (!mesh.mBoneVertices.empty())
|
||||||
|
{
|
||||||
|
mBoneVertices.resize(iSize);
|
||||||
|
}
|
||||||
|
|
||||||
// iterate through all faces in the mesh
|
// iterate through all faces in the mesh
|
||||||
unsigned int iCurrent = 0;
|
unsigned int iCurrent = 0;
|
||||||
|
@ -265,6 +306,16 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
|
||||||
{
|
{
|
||||||
mNormals[iCurrent] = mesh.mNormals[(*i).mIndices[n]];
|
mNormals[iCurrent] = mesh.mNormals[(*i).mIndices[n]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle bone vertices
|
||||||
|
if ((*i).mIndices[n] < mesh.mBoneVertices.size())
|
||||||
|
{
|
||||||
|
// (sometimes this will cause bone verts to be duplicated
|
||||||
|
// however, I' quite sure Schrompf' JoinVerticesStep
|
||||||
|
// will fix that again ...)
|
||||||
|
mBoneVertices[iCurrent] = mesh.mBoneVertices[(*i).mIndices[n]];
|
||||||
|
}
|
||||||
|
|
||||||
// assign a new valid index to the face
|
// assign a new valid index to the face
|
||||||
(*i).mIndices[n] = iCurrent;
|
(*i).mIndices[n] = iCurrent;
|
||||||
}
|
}
|
||||||
|
@ -312,9 +363,21 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
|
||||||
mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
|
mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
|
||||||
mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
|
mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||||
mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
|
mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
|
||||||
mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
|
|
||||||
mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
|
mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||||
|
|
||||||
|
// shininess
|
||||||
|
if (0.0f != mat.mSpecularExponent && 0.0f != mat.mShininessStrength)
|
||||||
|
{
|
||||||
|
mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
|
||||||
|
mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
|
||||||
|
}
|
||||||
|
// if there is no shininess, we can disable phong lighting
|
||||||
|
else if (Dot3DS::Dot3DSFile::Metal == mat.mShading ||
|
||||||
|
Dot3DS::Dot3DSFile::Phong == mat.mShading)
|
||||||
|
{
|
||||||
|
mat.mShading = Dot3DS::Dot3DSFile::Gouraud;
|
||||||
|
}
|
||||||
|
|
||||||
// opacity
|
// opacity
|
||||||
mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
|
mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
|
||||||
|
|
||||||
|
@ -489,6 +552,13 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
|
||||||
p_pcOut->mNumVertices = aiSplit[p].size()*3;
|
p_pcOut->mNumVertices = aiSplit[p].size()*3;
|
||||||
p_pcOut->mNumFaces = aiSplit[p].size();
|
p_pcOut->mNumFaces = aiSplit[p].size();
|
||||||
|
|
||||||
|
// receive output vertex weights
|
||||||
|
std::vector<std::pair<unsigned int, float>>* avOutputBones;
|
||||||
|
if (!mesh.mBones.empty())
|
||||||
|
{
|
||||||
|
avOutputBones = new std::vector<std::pair<unsigned int, float>>[mesh.mBones.size()];
|
||||||
|
}
|
||||||
|
|
||||||
// allocate enough storage for faces
|
// allocate enough storage for faces
|
||||||
p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
|
p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
|
||||||
|
|
||||||
|
@ -507,8 +577,29 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
|
||||||
|
|
||||||
for (unsigned int t = 0; t < 3;++t)
|
for (unsigned int t = 0; t < 3;++t)
|
||||||
{
|
{
|
||||||
p_pcOut->mVertices[iBase] = mesh.mPositions[mesh.mFaces[iIndex].mIndices[t]];
|
const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t];
|
||||||
p_pcOut->mNormals[iBase++] = mesh.mNormals[mesh.mFaces[iIndex].mIndices[t]];
|
|
||||||
|
p_pcOut->mVertices[iBase] = mesh.mPositions[iIndex2];
|
||||||
|
p_pcOut->mNormals[iBase] = mesh.mNormals[iIndex2];
|
||||||
|
|
||||||
|
// convert bones, if existing
|
||||||
|
if (!mesh.mBones.empty())
|
||||||
|
{
|
||||||
|
// check whether there is a vertex weight that is using
|
||||||
|
// this vertex index ...
|
||||||
|
if (iIndex2 < mesh.mBoneVertices.size())
|
||||||
|
{
|
||||||
|
for (std::vector<std::pair<int,float>>::const_iterator
|
||||||
|
blubb = mesh.mBoneVertices[iIndex2].mBoneWeights.begin();
|
||||||
|
blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end();++blubb)
|
||||||
|
{
|
||||||
|
// NOTE: illegal cases have already been filtered out
|
||||||
|
avOutputBones[(*blubb).first].push_back(std::pair<unsigned int, float>(
|
||||||
|
iBase,(*blubb).second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++iBase;
|
||||||
}
|
}
|
||||||
p_pcOut->mFaces[q].mIndices[0] = iBase-2;
|
p_pcOut->mFaces[q].mIndices[0] = iBase-2;
|
||||||
p_pcOut->mFaces[q].mIndices[1] = iBase-1;
|
p_pcOut->mFaces[q].mIndices[1] = iBase-1;
|
||||||
|
@ -549,6 +640,38 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!mesh.mBones.empty())
|
||||||
|
{
|
||||||
|
p_pcOut->mNumBones = 0;
|
||||||
|
for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
|
||||||
|
if (!avOutputBones[mrspock].empty())p_pcOut->mNumBones++;
|
||||||
|
|
||||||
|
p_pcOut->mBones = new aiBone* [ p_pcOut->mNumBones ];
|
||||||
|
aiBone** pcBone = &p_pcOut->mBones[0];
|
||||||
|
for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
|
||||||
|
{
|
||||||
|
if (!avOutputBones[mrspock].empty())
|
||||||
|
{
|
||||||
|
// we will need this bone. add it to the output mesh and
|
||||||
|
// add all per-vertex weights
|
||||||
|
*pcBone = new aiBone();
|
||||||
|
(**pcBone).mName.Set(mesh.mBones[mrspock].mName);
|
||||||
|
|
||||||
|
(**pcBone).mNumWeights = avOutputBones[mrspock].size();
|
||||||
|
(**pcBone).mWeights = new aiVertexWeight[(**pcBone).mNumWeights];
|
||||||
|
|
||||||
|
for (unsigned int captainkirk = 0; captainkirk < (**pcBone).mNumWeights;++captainkirk)
|
||||||
|
{
|
||||||
|
const std::pair<unsigned int,float>& ref = avOutputBones[mrspock][captainkirk];
|
||||||
|
(**pcBone).mWeights[captainkirk].mVertexId = ref.first;
|
||||||
|
(**pcBone).mWeights[captainkirk].mWeight = ref.second;
|
||||||
|
}
|
||||||
|
++pcBone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// delete allocated storage
|
||||||
|
delete[] avOutputBones;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// delete storage
|
// delete storage
|
||||||
|
@ -619,6 +742,51 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
|
||||||
p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
|
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[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy vertex bones
|
||||||
|
if (!mesh.mBones.empty() && !mesh.mBoneVertices.empty())
|
||||||
|
{
|
||||||
|
std::vector<aiVertexWeight>* avBonesOut = new
|
||||||
|
std::vector<aiVertexWeight>[mesh.mBones.size()];
|
||||||
|
|
||||||
|
// find all vertex weights for this bone
|
||||||
|
unsigned int quak = 0;
|
||||||
|
for (std::vector<BoneVertex>::const_iterator
|
||||||
|
harrypotter = mesh.mBoneVertices.begin();
|
||||||
|
harrypotter != mesh.mBoneVertices.end();++harrypotter,++quak)
|
||||||
|
{
|
||||||
|
for (std::vector<std::pair<int,float>>::const_iterator
|
||||||
|
ronaldweasley = (*harrypotter).mBoneWeights.begin();
|
||||||
|
ronaldweasley != (*harrypotter).mBoneWeights.end();++ronaldweasley)
|
||||||
|
{
|
||||||
|
aiVertexWeight weight;
|
||||||
|
weight.mVertexId = quak;
|
||||||
|
weight.mWeight = (*ronaldweasley).second;
|
||||||
|
avBonesOut[(*ronaldweasley).first].push_back(weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now build a final bone list
|
||||||
|
p_pcOut->mNumBones = 0;
|
||||||
|
for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)
|
||||||
|
if (!avBonesOut[jfkennedy].empty())p_pcOut->mNumBones++;
|
||||||
|
|
||||||
|
p_pcOut->mBones = new aiBone*[p_pcOut->mNumBones];
|
||||||
|
aiBone** pcBone = &p_pcOut->mBones[0];
|
||||||
|
for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)
|
||||||
|
{
|
||||||
|
if (!avBonesOut[jfkennedy].empty())
|
||||||
|
{
|
||||||
|
*pcBone = new aiBone();
|
||||||
|
(**pcBone).mName.Set(mesh.mBones[jfkennedy].mName);
|
||||||
|
(**pcBone).mNumWeights = avBonesOut[jfkennedy].size();
|
||||||
|
(**pcBone).mWeights = new aiVertexWeight[(**pcBone).mNumWeights];
|
||||||
|
memcpy((**pcBone).mWeights,&avBonesOut[jfkennedy][0],
|
||||||
|
sizeof(aiVertexWeight) * (**pcBone).mNumWeights);
|
||||||
|
++pcBone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now build the output mesh list
|
// now build the output mesh list
|
||||||
|
|
|
@ -108,6 +108,13 @@ protected:
|
||||||
*/
|
*/
|
||||||
void BuildUniqueRepresentation(ASE::Mesh& mesh);
|
void BuildUniqueRepresentation(ASE::Mesh& mesh);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Transform all vertices with the inverse transformation
|
||||||
|
* matrix of the mesh
|
||||||
|
* \param mesh Mesh to work on
|
||||||
|
*/
|
||||||
|
void TransformVertices(ASE::Mesh& mesh);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Create one-material-per-mesh meshes ;-)
|
/** Create one-material-per-mesh meshes ;-)
|
||||||
* \param mesh Mesh to work with
|
* \param mesh Mesh to work with
|
||||||
|
@ -140,6 +147,9 @@ protected:
|
||||||
|
|
||||||
/** Buffer to hold the loaded file */
|
/** Buffer to hold the loaded file */
|
||||||
unsigned char* mBuffer;
|
unsigned char* mBuffer;
|
||||||
|
|
||||||
|
/** true if this is an .ask file */
|
||||||
|
bool mIsAsk;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -204,12 +204,7 @@ void Parser::Parse()
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ('\0' == *this->m_szFile)
|
if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -249,12 +244,7 @@ void Parser::ParseLV1SceneBlock()
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -310,12 +300,7 @@ void Parser::ParseLV1MaterialListBlock()
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -437,6 +422,13 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
|
||||||
this->ParseLV4MeshFloat(mat.mSpecularExponent);
|
this->ParseLV4MeshFloat(mat.mSpecularExponent);
|
||||||
mat.mSpecularExponent *= 15;
|
mat.mSpecularExponent *= 15;
|
||||||
}
|
}
|
||||||
|
// material shininess strength
|
||||||
|
if (0 == strncmp(this->m_szFile,"*MATERIAL_SHINESTRENGTH",23) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+23)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=24;
|
||||||
|
this->ParseLV4MeshFloat(mat.mShininessStrength);
|
||||||
|
}
|
||||||
// diffuse color map
|
// diffuse color map
|
||||||
if (0 == strncmp(this->m_szFile,"*MAP_DIFFUSE",12) &&
|
if (0 == strncmp(this->m_szFile,"*MAP_DIFFUSE",12) &&
|
||||||
IsSpaceOrNewLine(*(this->m_szFile+12)))
|
IsSpaceOrNewLine(*(this->m_szFile+12)))
|
||||||
|
@ -546,12 +538,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -649,12 +636,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -667,6 +649,47 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
bool Parser::ParseString(std::string& out,const char* szName)
|
||||||
|
{
|
||||||
|
char szBuffer[1024];
|
||||||
|
ai_assert(strlen(szName < 750));
|
||||||
|
|
||||||
|
// NOTE: The name could also be the texture in some cases
|
||||||
|
// be prepared that this might occur ...
|
||||||
|
if (!SkipSpaces(this->m_szFile,&this->m_szFile))
|
||||||
|
{
|
||||||
|
sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
|
||||||
|
this->LogWarning(szBuffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// there must be "
|
||||||
|
if ('\"' != *this->m_szFile)
|
||||||
|
{
|
||||||
|
sprintf(szBuffer,"Unable to parse %s block: String is expected "
|
||||||
|
"to be enclosed in double quotation marks",szName);
|
||||||
|
this->LogWarning(szBuffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
++this->m_szFile;
|
||||||
|
const char* sz = this->m_szFile;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if ('\"' == *sz)break;
|
||||||
|
else if ('\0' == sz)
|
||||||
|
{
|
||||||
|
sprintf(szBuffer,"Unable to parse %s block: String is expected to be "
|
||||||
|
"enclosed in double quotation marks but EOF was reached before a closing "
|
||||||
|
"quotation mark was found",szName);
|
||||||
|
this->LogWarning(szBuffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sz++;
|
||||||
|
}
|
||||||
|
out = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
|
||||||
|
this->m_szFile = sz;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
|
void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
|
||||||
{
|
{
|
||||||
int iDepth = 0;
|
int iDepth = 0;
|
||||||
|
@ -679,31 +702,22 @@ void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
|
||||||
IsSpaceOrNewLine(*(this->m_szFile+10)))
|
IsSpaceOrNewLine(*(this->m_szFile+10)))
|
||||||
{
|
{
|
||||||
this->m_szFile+=11;
|
this->m_szFile+=11;
|
||||||
|
if(!this->ParseString(mesh.mName,"*NODE_NAME"))
|
||||||
// NOTE: The name could also be the texture in some cases
|
|
||||||
// be prepared that this might occur ...
|
|
||||||
if (!SkipSpaces(this->m_szFile,&this->m_szFile))
|
|
||||||
BLUBB("Unable to parse *NODE_NAME block: Unexpected EOL")
|
|
||||||
|
|
||||||
// there must be "
|
|
||||||
if ('\"' != *this->m_szFile)
|
|
||||||
BLUBB("Unable to parse *NODE_NAME block: Name is expected to be enclosed in double quotation marks")
|
|
||||||
|
|
||||||
++this->m_szFile;
|
|
||||||
const char* sz = this->m_szFile;
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
if ('\"' == *sz)break;
|
this->SkipToNextToken();
|
||||||
else if ('\0' == sz)
|
continue;
|
||||||
{
|
}
|
||||||
BLUBB("Unable to parse *NODE_NAME block: Name is expected to be enclosed in double quotation marks \
|
}
|
||||||
but EOF was reached before a closing quotation mark was found")
|
// name of the parent of the node
|
||||||
}
|
if (0 == strncmp(this->m_szFile,"*NODE_PARENT" ,12) &&
|
||||||
sz++;
|
IsSpaceOrNewLine(*(this->m_szFile+12)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=13;
|
||||||
|
if(!this->ParseString(mesh.mParent,"*NODE_PARENT"))
|
||||||
|
{
|
||||||
|
this->SkipToNextToken();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.mName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
|
|
||||||
this->m_szFile = sz;
|
|
||||||
}
|
}
|
||||||
// transformation matrix of the node
|
// transformation matrix of the node
|
||||||
if (0 == strncmp(this->m_szFile,"*NODE_TM" ,8) &&
|
if (0 == strncmp(this->m_szFile,"*NODE_TM" ,8) &&
|
||||||
|
@ -719,16 +733,18 @@ void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
|
||||||
this->m_szFile+=6;
|
this->m_szFile+=6;
|
||||||
this->ParseLV2MeshBlock(mesh);
|
this->ParseLV2MeshBlock(mesh);
|
||||||
}
|
}
|
||||||
|
// mesh material index
|
||||||
|
else if (0 == strncmp(this->m_szFile,"*MATERIAL_REF" ,13) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+13)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=14;
|
||||||
|
this->ParseLV4MeshLong(mesh.iMaterialIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -780,12 +796,7 @@ void Parser::ParseLV2NodeTransformBlock(ASE::Mesh& mesh)
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -932,23 +943,28 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
|
||||||
this->ParseLV3MappingChannel(iIndex-1,mesh);
|
this->ParseLV3MappingChannel(iIndex-1,mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// mesh material index
|
// mesh animation keyframe. Not supported
|
||||||
else if (0 == strncmp(this->m_szFile,"*MATERIAL_REF" ,13) &&
|
else if (0 == strncmp(this->m_szFile,"*MESH_ANIMATION" ,15) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+15)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=16;
|
||||||
|
|
||||||
|
this->LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
|
||||||
|
"Keyframe animation is not supported by Assimp, this element "
|
||||||
|
"will be ignored");
|
||||||
|
}
|
||||||
|
// mesh animation keyframe. Not supported
|
||||||
|
else if (0 == strncmp(this->m_szFile,"*MESH_WEIGHTS" ,13) &&
|
||||||
IsSpaceOrNewLine(*(this->m_szFile+13)))
|
IsSpaceOrNewLine(*(this->m_szFile+13)))
|
||||||
{
|
{
|
||||||
this->m_szFile+=14;
|
this->m_szFile+=14;
|
||||||
this->ParseLV4MeshLong(mesh.iMaterialIndex);
|
this->ParseLV3MeshWeightsBlock(mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -961,6 +977,174 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
|
||||||
|
{
|
||||||
|
unsigned int iNumVertices = 0;
|
||||||
|
unsigned int iNumBones = 0;
|
||||||
|
int iDepth = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if ('*' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
// Number of bone vertices ...
|
||||||
|
if (0 == strncmp(this->m_szFile,"*MESH_NUMVERTEX" ,15) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+15)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=16;
|
||||||
|
this->ParseLV4MeshLong(iNumVertices);
|
||||||
|
}
|
||||||
|
// Number of bones
|
||||||
|
if (0 == strncmp(this->m_szFile,"*MESH_NUMBONE" ,13) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+13)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=14;
|
||||||
|
this->ParseLV4MeshLong(iNumBones);
|
||||||
|
}
|
||||||
|
// parse the list of bones
|
||||||
|
if (0 == strncmp(this->m_szFile,"*MESH_BONE_LIST" ,15) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+15)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=16;
|
||||||
|
this->SkipOpeningBracket();
|
||||||
|
this->ParseLV4MeshBones(iNumBones,mesh);
|
||||||
|
}
|
||||||
|
// parse the list of bones vertices
|
||||||
|
if (0 == strncmp(this->m_szFile,"*MESH_BONE_VERTEX_LIST" ,22) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+22)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=23;
|
||||||
|
this->SkipOpeningBracket();
|
||||||
|
this->ParseLV4MeshBonesVertices(iNumVertices,mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
|
if ('}' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
|
}
|
||||||
|
else if ('\0' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
// END OF FILE ... this is a level2 block, this can't be
|
||||||
|
BLUBB("Unable to finish parsing a lv2 *MESH_WEIGHTS block. Unexpected EOF")
|
||||||
|
}
|
||||||
|
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
|
||||||
|
++this->m_szFile;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
|
||||||
|
{
|
||||||
|
mesh.mBones.resize(iNumBones);
|
||||||
|
int iDepth = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if ('*' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
// Mesh bone with name ...
|
||||||
|
if (0 == strncmp(this->m_szFile,"*MESH_BONE_NAME" ,17) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+17)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=18;
|
||||||
|
|
||||||
|
// parse an index ...
|
||||||
|
if(SkipSpaces(this->m_szFile,&this->m_szFile))
|
||||||
|
{
|
||||||
|
unsigned int iIndex = strtol10(this->m_szFile,&this->m_szFile);
|
||||||
|
if (iIndex >= iNumBones)
|
||||||
|
{
|
||||||
|
iIndex = iNumBones-1;
|
||||||
|
this->LogWarning("Bone index is out of bounds. Using the largest valid "
|
||||||
|
"bone index instead");
|
||||||
|
}
|
||||||
|
if (!this->ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
|
||||||
|
{
|
||||||
|
this->SkipToNextToken();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
|
else if ('}' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
|
}
|
||||||
|
else if ('\0' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
// END OF FILE ... this is a level4 block, this can't be
|
||||||
|
BLUBB("Unable to finish parsing a lv4 *MESH_BONE_LIST block. Unexpected EOF")
|
||||||
|
}
|
||||||
|
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
|
||||||
|
++this->m_szFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh)
|
||||||
|
{
|
||||||
|
mesh.mBoneVertices.resize(iNumVertices);
|
||||||
|
int iDepth = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if ('*' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
// Mesh bone vertex
|
||||||
|
if (0 == strncmp(this->m_szFile,"*MESH_BONE_VERTEX" ,17) &&
|
||||||
|
IsSpaceOrNewLine(*(this->m_szFile+17)))
|
||||||
|
{
|
||||||
|
this->m_szFile+=18;
|
||||||
|
|
||||||
|
// read the vertex index
|
||||||
|
unsigned int iIndex = strtol10(this->m_szFile,&this->m_szFile);
|
||||||
|
if (iIndex >= mesh.mPositions.size())
|
||||||
|
{
|
||||||
|
iIndex = mesh.mPositions.size()-1;
|
||||||
|
this->LogWarning("Bone vertex index is out of bounds. Using the largest valid "
|
||||||
|
"bone vertex index instead");
|
||||||
|
}
|
||||||
|
|
||||||
|
// now there there are 3 normal floats, the
|
||||||
|
// should be identical to the vertex positions
|
||||||
|
// contained in the *VERTEX_LIST block. Well, we check this
|
||||||
|
// in debug builds to be sure ;-)
|
||||||
|
float afVert[3];
|
||||||
|
this->ParseLV4MeshFloatTriple(afVert);
|
||||||
|
|
||||||
|
std::pair<int,float> pairOut;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// first parse the bone index ...
|
||||||
|
if (!SkipSpaces(this->m_szFile,&this->m_szFile))break;
|
||||||
|
pairOut.first = strtol10(this->m_szFile,&this->m_szFile);
|
||||||
|
|
||||||
|
// then parse the vertex weight
|
||||||
|
if (!SkipSpaces(this->m_szFile,&this->m_szFile))break;
|
||||||
|
this->m_szFile = fast_atof_move(this->m_szFile,pairOut.second);
|
||||||
|
|
||||||
|
// -1 designates unused entries
|
||||||
|
if (-1 != pairOut.first)
|
||||||
|
{
|
||||||
|
mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
|
else if ('}' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
|
}
|
||||||
|
else if ('\0' == *this->m_szFile)
|
||||||
|
{
|
||||||
|
// END OF FILE ... this is a level4 block, this can't be
|
||||||
|
BLUBB("Unable to finish parsing a lv4 *MESH_BONE_VERTEX_LIST block. Unexpected EOF")
|
||||||
|
}
|
||||||
|
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
|
||||||
|
++this->m_szFile;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Parser::ParseLV3MeshVertexListBlock(
|
void Parser::ParseLV3MeshVertexListBlock(
|
||||||
unsigned int iNumVertices, ASE::Mesh& mesh)
|
unsigned int iNumVertices, ASE::Mesh& mesh)
|
||||||
{
|
{
|
||||||
|
@ -989,14 +1173,9 @@ void Parser::ParseLV3MeshVertexListBlock(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
else if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -1037,12 +1216,7 @@ void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -1091,12 +1265,7 @@ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -1143,12 +1312,7 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -1205,12 +1369,7 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -1253,12 +1412,7 @@ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -1304,12 +1458,7 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -1356,12 +1505,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
|
||||||
if ('{' == *this->m_szFile)iDepth++;
|
if ('{' == *this->m_szFile)iDepth++;
|
||||||
if ('}' == *this->m_szFile)
|
if ('}' == *this->m_szFile)
|
||||||
{
|
{
|
||||||
if (0 == --iDepth)
|
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
|
||||||
{
|
|
||||||
++this->m_szFile;
|
|
||||||
this->SkipToNextToken();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// seems we have reached the end of the file ...
|
// seems we have reached the end of the file ...
|
||||||
else if ('\0' == *this->m_szFile)
|
else if ('\0' == *this->m_szFile)
|
||||||
|
@ -1432,7 +1576,7 @@ __EARTHQUAKE_XXL:
|
||||||
if ('*' == *this->m_szFile)break;
|
if ('*' == *this->m_szFile)break;
|
||||||
if (IsLineEnd(*this->m_szFile))
|
if (IsLineEnd(*this->m_szFile))
|
||||||
{
|
{
|
||||||
this->iLineNumber++;
|
//this->iLineNumber++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->m_szFile++;
|
this->m_szFile++;
|
||||||
|
@ -1446,9 +1590,13 @@ __EARTHQUAKE_XXL:
|
||||||
BLUBB("Unable to parse *MESH_SMOOTHING Element: Unexpected EOL. Smoothing group(s) expected [#5]")
|
BLUBB("Unable to parse *MESH_SMOOTHING Element: Unexpected EOL. Smoothing group(s) expected [#5]")
|
||||||
|
|
||||||
// parse smoothing groups until we don_t anymore see commas
|
// parse smoothing groups until we don_t anymore see commas
|
||||||
|
// FIX: There needn't always be a value, sad but true
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
out.iSmoothGroup |= (1 << strtol10(this->m_szFile,&this->m_szFile));
|
if (*this->m_szFile < '9' && *this->m_szFile >= '0')
|
||||||
|
{
|
||||||
|
out.iSmoothGroup |= (1 << strtol10(this->m_szFile,&this->m_szFile));
|
||||||
|
}
|
||||||
SkipSpaces(this->m_szFile,&this->m_szFile);
|
SkipSpaces(this->m_szFile,&this->m_szFile);
|
||||||
if (',' != *this->m_szFile)
|
if (',' != *this->m_szFile)
|
||||||
{
|
{
|
||||||
|
@ -1465,7 +1613,7 @@ __EARTHQUAKE_XXL:
|
||||||
if ('*' == *this->m_szFile)break;
|
if ('*' == *this->m_szFile)break;
|
||||||
if (IsLineEnd(*this->m_szFile))
|
if (IsLineEnd(*this->m_szFile))
|
||||||
{
|
{
|
||||||
this->iLineNumber++;
|
//this->iLineNumber++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->m_szFile++;
|
this->m_szFile++;
|
||||||
|
@ -1478,7 +1626,7 @@ __EARTHQUAKE_XXL:
|
||||||
BLUBB("Unable to parse *MESH_MTLID Element: Unexpected EOL. Material index expected [#6]")
|
BLUBB("Unable to parse *MESH_MTLID Element: Unexpected EOL. Material index expected [#6]")
|
||||||
out.iMaterial = strtol10(this->m_szFile,&this->m_szFile);
|
out.iMaterial = strtol10(this->m_szFile,&this->m_szFile);
|
||||||
}
|
}
|
||||||
this->SkipToNextToken();
|
//this->SkipToNextToken();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1519,7 +1667,7 @@ void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
|
||||||
}
|
}
|
||||||
apOut[2] = strtol10(this->m_szFile,&this->m_szFile);
|
apOut[2] = strtol10(this->m_szFile,&this->m_szFile);
|
||||||
// go to the next valid sequence
|
// go to the next valid sequence
|
||||||
SkipSpacesAndLineEnd(this->m_szFile,&this->m_szFile);
|
//SkipSpacesAndLineEnd(this->m_szFile,&this->m_szFile);
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
|
void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
|
||||||
|
@ -1603,7 +1751,7 @@ void Parser::ParseLV4MeshFloatTriple(float* apOut)
|
||||||
// parse the third float
|
// parse the third float
|
||||||
this->m_szFile = fast_atof_move(this->m_szFile,apOut[2]);
|
this->m_szFile = fast_atof_move(this->m_szFile,apOut[2]);
|
||||||
// go to the next valid sequence
|
// go to the next valid sequence
|
||||||
this->SkipToNextToken();
|
//this->SkipToNextToken();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1621,7 +1769,7 @@ void Parser::ParseLV4MeshFloat(float& fOut)
|
||||||
// parse the first float
|
// parse the first float
|
||||||
this->m_szFile = fast_atof_move(this->m_szFile,fOut);
|
this->m_szFile = fast_atof_move(this->m_szFile,fOut);
|
||||||
// go to the next valid sequence
|
// go to the next valid sequence
|
||||||
this->SkipToNextToken();
|
//this->SkipToNextToken();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1639,6 +1787,6 @@ void Parser::ParseLV4MeshLong(unsigned int& iOut)
|
||||||
// parse the value
|
// parse the value
|
||||||
iOut = strtol10(this->m_szFile,&this->m_szFile);
|
iOut = strtol10(this->m_szFile,&this->m_szFile);
|
||||||
// go to the next valid sequence
|
// go to the next valid sequence
|
||||||
this->SkipToNextToken();
|
//this->SkipToNextToken();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
|
@ -125,6 +125,36 @@ struct Face : public Dot3DS::Face
|
||||||
unsigned int iFace;
|
unsigned int iFace;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** Helper structure to represent an ASE file bone */
|
||||||
|
struct Bone
|
||||||
|
{
|
||||||
|
//! Constructor
|
||||||
|
Bone()
|
||||||
|
{
|
||||||
|
static int iCnt = 0;
|
||||||
|
std::stringstream ss(mName);
|
||||||
|
ss << "%%_UNNAMED_" << iCnt++ << "_%%";
|
||||||
|
ss.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Name of the bone
|
||||||
|
std::string mName;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** Helper structure to represent an ASE file bone vertex */
|
||||||
|
struct BoneVertex
|
||||||
|
{
|
||||||
|
//! Bone and corresponding vertex weight.
|
||||||
|
//! -1 for unrequired bones ....
|
||||||
|
std::vector<std::pair<int,float> > mBoneWeights;
|
||||||
|
|
||||||
|
//! Position of the bone vertex.
|
||||||
|
//! MUST be identical to the vertex position
|
||||||
|
//aiVector3D mPosition;
|
||||||
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Helper structure to represent an ASE file mesh */
|
/** Helper structure to represent an ASE file mesh */
|
||||||
struct Mesh
|
struct Mesh
|
||||||
|
@ -135,6 +165,7 @@ struct Mesh
|
||||||
static int iCnt = 0;
|
static int iCnt = 0;
|
||||||
std::stringstream ss(mName);
|
std::stringstream ss(mName);
|
||||||
ss << "%%_UNNAMED_" << iCnt++ << "_%%";
|
ss << "%%_UNNAMED_" << iCnt++ << "_%%";
|
||||||
|
ss.flush();
|
||||||
|
|
||||||
// use 2 texture vertex components by default
|
// use 2 texture vertex components by default
|
||||||
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
|
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
|
||||||
|
@ -143,8 +174,14 @@ struct Mesh
|
||||||
// setup the default material index by default
|
// setup the default material index by default
|
||||||
iMaterialIndex = Face::DEFAULT_MATINDEX;
|
iMaterialIndex = Face::DEFAULT_MATINDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Name of the mesh
|
||||||
std::string mName;
|
std::string mName;
|
||||||
|
|
||||||
|
//! Name of the parent of the mesh
|
||||||
|
//! "" if there is no parent ...
|
||||||
|
std::string mParent;
|
||||||
|
|
||||||
//! vertex positions
|
//! vertex positions
|
||||||
std::vector<aiVector3D> mPositions;
|
std::vector<aiVector3D> mPositions;
|
||||||
|
|
||||||
|
@ -160,6 +197,12 @@ struct Mesh
|
||||||
//! List of normal vectors
|
//! List of normal vectors
|
||||||
std::vector<aiVector3D> mNormals;
|
std::vector<aiVector3D> mNormals;
|
||||||
|
|
||||||
|
//! List of all bone vertices
|
||||||
|
std::vector<BoneVertex> mBoneVertices;
|
||||||
|
|
||||||
|
//! List of all bones
|
||||||
|
std::vector<Bone> mBones;
|
||||||
|
|
||||||
//! Transformation matrix of the mesh
|
//! Transformation matrix of the mesh
|
||||||
aiMatrix4x4 mTransform;
|
aiMatrix4x4 mTransform;
|
||||||
|
|
||||||
|
@ -295,6 +338,23 @@ private:
|
||||||
//! \param mesh Mesh object to be filled
|
//! \param mesh Mesh object to be filled
|
||||||
void ParseLV3MeshNormalListBlock(Mesh& mesh);
|
void ParseLV3MeshNormalListBlock(Mesh& mesh);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
//! Parse a *MESH_WEIGHTSblock in a file
|
||||||
|
//! \param mesh Mesh object to be filled
|
||||||
|
void ParseLV3MeshWeightsBlock(Mesh& mesh);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
//! Parse the bone list of a file
|
||||||
|
//! \param mesh Mesh object to be filled
|
||||||
|
//! \param iNumBones Number of bones in the mesh
|
||||||
|
void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
//! Parse the bone vertices list of a file
|
||||||
|
//! \param mesh Mesh object to be filled
|
||||||
|
//! \param iNumVertices Number of vertices to be parsed
|
||||||
|
void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a *MESH_FACE block in a file
|
//! Parse a *MESH_FACE block in a file
|
||||||
//! \param out receive the face data
|
//! \param out receive the face data
|
||||||
|
@ -359,6 +419,14 @@ private:
|
||||||
//! \param szWarn Error message
|
//! \param szWarn Error message
|
||||||
void LogError(const char* szWarn);
|
void LogError(const char* szWarn);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
//! Parse a string, enclosed in double quotation marks
|
||||||
|
//! \param out Output string
|
||||||
|
//! \param szName Name of the enclosing element -> used in error
|
||||||
|
//! messages.
|
||||||
|
//! \return false if an error occured
|
||||||
|
bool Parser::ParseString(std::string& out,const char* szName);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Pointer to current data
|
//! Pointer to current data
|
||||||
|
|
Loading…
Reference in New Issue