First half-working version of the ASE loader

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@46 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
aramis_acg
2008-05-28 21:05:05 +00:00
parent 9c4968da33
commit 74dfe61c1e
4 changed files with 531 additions and 137 deletions

View File

@@ -49,13 +49,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
#include "../include/DefaultLogger.h"
#include <boost/scoped_ptr.hpp>
using namespace Assimp;
using namespace Assimp::ASE;
#define LOGOUT_WARN(x)
#define LOGOUT_WARN(x) DefaultLogger::get()->warn(x);
// ------------------------------------------------------------------------------------------------
// 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;
// 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' &&
extension[3] != 'k' && extension[3] != 'K')return false;
@@ -105,6 +108,14 @@ void ASEImporter::InternReadFile(
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
// (terminate it with zero)
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.end();++i)
{
// need to generate proper vertex normals if necessary
this->GenerateNormals(*i);
// transform all vertices into worldspace
// 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
// we need to split them by materials, build valid vertex/face lists ...
this->BuildUniqueRepresentation(*i);
// need to generate proper vertex normals if necessary
this->GenerateNormals(*i);
// convert all meshes to aiMesh objects
this->ConvertMeshes(*i,pScene);
}
// buil final material indices (remove submaterials and make the final list)
@@ -206,6 +224,23 @@ void ASEImporter::BuildNodes(aiScene* pcScene)
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)
{
// allocate output storage
@@ -213,6 +248,7 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
std::vector<aiColor4D> mVertexColors;
std::vector<aiVector3D> mNormals;
std::vector<BoneVertex> mBoneVertices;
unsigned int iSize = mesh.mFaces.size() * 3;
mPositions.resize(iSize);
@@ -236,6 +272,11 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
{
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
unsigned int iCurrent = 0;
@@ -265,6 +306,16 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
{
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
(*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.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
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);
// 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
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->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
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)
{
p_pcOut->mVertices[iBase] = mesh.mPositions[mesh.mFaces[iIndex].mIndices[t]];
p_pcOut->mNormals[iBase++] = mesh.mNormals[mesh.mFaces[iIndex].mIndices[t]];
const uint32_t iIndex2 = 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[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
@@ -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[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