MDL

#16
[code=SomFileHelper.cpp]
/** @file Implementation of the Sword of Moonlight MDL/MDO helper routines */

#include "AssimpPCH.h"

#ifndef max
#define max(a, b) ‎  (((a) > (b)) ? (a) : (b))
#endif

// internal headers
#include "SomFileHelper.h"

using namespace Assimp;
using namespace Assimp_x;

namespace Assimp_x{ //! experimental

enum aiParameterType
{
aiParameterType_VERTEX ‎  = 0x1,

aiParameterType_NORMAL ‎  = 0x2,

aiParameterType_COLOR ‎  ‎  = 0x4,

//! or aiParameterType_TEXTURECOORD?
aiParameterType_TEXTURECOORDS = 0x8,

_aiParameterType_Force32Bit = 0x9fffffff
}; //! enum aiParameterType

enum aiFaceFeature
{
aiFaceFeature_NORMAL = 0x1,

aiFaceFeature_COLOR ‎  = 0x2,

_aiFaceFeature_Force32Bit = 0x9fffffff
}; //! enum aiFaceFeature

struct aiFace2 : public aiFace
{
/** Bitwise combination of the members of the #aiFaceFeature enum.
* aiFaceFeature_NORMAL: mIndices[0] is face normal index
* aiFaceFeature_COLOR: ‎  mIndices[1] is face color index
*/
unsigned int mFaceFeatures;

/** Bitwise combination of the members of the #aiParameterType enum.
* This specifies whether the corresponding index looks in the mIndices
* array when the bits are not set or into another aiFace2 when set.
*/
unsigned int mParameterModes; ‎ 

//! one parameter exists per corner per type
unsigned int mNumCorners;

//! offset between like parameter indices
unsigned int mStride;

/** first vertex index into mIndices.
* mIndices[0] is reserved for the face normal.
* Therefore if mVertices, mNormals, etc, is 0
* (and the corresponding mParameterModes bit is unset)
* the parameter data is taken not to exist.
*/
unsigned int mVertices;

//! tangents and bitangents overlap
unsigned int mNormals;

//! color channels overlap
unsigned int mColors;

//! uv channels overlap
unsigned int mTextureCoords;

//! overrides mesh mMaterialIndex member
unsigned int mMaterialIndex;

#ifdef __cplusplus

//! Default constructor
aiFace2()
{
mFaceFeatures = 0x00000000;
mParameterModes = 0x00000000;

mNumCorners = mStride = 0;

mVertices = mNormals = mColors = mTextureCoords = 0;

mMaterialIndex = 0;
}
#endif // __cplusplus
};

struct aiMesh2 : public aiMesh
{
//! tangents and bitangents overlap
unsigned int mNumNormals;

//! color channels overlap
unsigned int mNumColors;

//! uv channels overlap
unsigned int mNumTextureCoords;

C_STRUCT aiFace2* mFaces2;

/** Number of mFaces2 materials
* Used to pad aiScene::mNumMeshes
* so aiNode::mMeshes can reference
* both aiMeshes and aiMeshes2.
*/
unsigned int mNumMaterials;

/** Parameters shared across meshes
* If set this should be a mesh in the
* scene mMeshes2 member. To see how
* it works see GetPosition() below.
* Not meant to be recursive.
*/
C_STRUCT aiMesh2* mSharedParameters;

#define _AIMESH2_GETPARAMETER(Ps,Ns)\
\
if(mSharedParameters)\
{\
if(pIndex<mSharedParameters->mNum##Ns)\
{\
if(mSharedParameters->m##Ps==NULL) return false;\
\
*pOut = mSharedParameters->m##Ps[pIndex]; return true;\
}\
else pIndex-=mSharedParameters->mNum##Ns;\
}\
else if(m##Ps==NULL||pIndex>=mNum##Ns) return false;\
\
*pOut = m##Ps[pIndex]; return true;


bool GetPosition(unsigned int pIndex, aiVector3D* pOut)const
{ _AIMESH2_GETPARAMETER(Vertices,Vertices) }

bool GetNormal(unsigned int pIndex, aiVector3D* pOut)const
{ _AIMESH2_GETPARAMETER(Normals,Normals) }

bool GetTangent(unsigned int pIndex, aiVector3D* pOut)const
{ _AIMESH2_GETPARAMETER(Tangents,Normals) }

bool GetBitangent(unsigned int pIndex, aiVector3D* pOut)const
{ _AIMESH2_GETPARAMETER(Bitangents,Normals) }

bool GetVertexColor(unsigned int pChannel, unsigned int pIndex, aiColor4D* pOut)const
{
if(pChannel>=AI_MAX_NUMBER_OF_COLOR_SETS) return false;

_AIMESH2_GETPARAMETER(Colors[pChannel],Colors)
}

//! GetTextureCoords or GetTextureCoord?
bool GetTextureCoord(unsigned int pChannel, unsigned int pIndex, aiVector3D* pOut)const
{
if(pChannel>=AI_MAX_NUMBER_OF_TEXTURECOORDS) return false;

_AIMESH2_GETPARAMETER(TextureCoords[pChannel],TextureCoords)
}

#undef _AIMESH2_GETPARAMETER

/** Find face for shared parameter indices
* The shared faces are logically mapped to the parameter space
* but do not constitute part of the mesh. That is they are for
* referencing parameters only.
*/
aiFace2 *FindFace2(unsigned int pIndex)const
{
if(mSharedParameters)
{
if(pIndex<mSharedParameters->mNumFaces)
{
if(mSharedParameters->mFaces2==NULL) return NULL;

return mSharedParameters->mFaces2+pIndex;
}
else pIndex-=mSharedParameters->mNumFaces;
}
else if(pIndex>mNumFaces||!mFaces2==NULL) return NULL;

return mFaces2+pIndex;
}

#ifdef __cplusplus

//! Default constructor. Initializes all members to 0
aiMesh2()
{
mNumNormals = mNumColors = mNumTextureCoords = 0;

mFaces2 = NULL; mNumMaterials = 0;

mSharedParameters = NULL;
}

~aiMesh2()
{
if(mFaces2) delete [] mFaces2;
}
#endif // __cplusplus

#define _AIMESH2_HASPARAMETERS(TEST,F)\
\
if(TEST) return true; if(mSharedParameters==NULL) return false;\
\
return mSharedParameters->Has##F;

inline bool HasPositions()const
{ _AIMESH2_HASPARAMETERS(mVertices!=NULL&&mNumVertices>0,Positions()) }

//! instead of this use hasFaces2()
inline bool HasFaces()const{ return false; }

inline bool HasFaces2()const
{ _AIMESH2_HASPARAMETERS(mFaces2!=NULL&&mNumFaces>0,Faces2()) }

inline bool HasNormals()const
{ _AIMESH2_HASPARAMETERS(mNormals!=NULL&&mNumNormals>0,Normals()) }

inline bool HasTangentsAndBitangents()const
{ _AIMESH2_HASPARAMETERS(mTangents!=NULL&&mBitangents!=NULL&&mNumNormals>0,TangentsAndBitangents()) }

inline bool HasVertexColors(unsigned int pIndex)const
{
if(pIndex>=AI_MAX_NUMBER_OF_COLOR_SETS) return false;

_AIMESH2_HASPARAMETERS(mColors[pIndex]!=NULL&&mNumColors>0,VertexColors(pIndex))
}

inline bool HasTextureCoords(unsigned int pIndex)const
{
if(pIndex>=AI_MAX_NUMBER_OF_TEXTURECOORDS) return false;

_AIMESH2_HASPARAMETERS(mTextureCoords[pIndex]!=NULL&&mNumTextureCoords>0,TextureCoords(pIndex))
}

#undef _AIMESH2_HASPARAMETERS
}; ‎ 

#define AI_SCENE_FLAGS2_INCOMPLETE 0x1

struct aiScene2 : public aiScene
{
unsigned int mFlags2;

/** The array of meshes.
*
* Use the indices given in the aiNode structure to access
* this array. The array is mNumMeshes in size.
*/
C_STRUCT aiMesh2** mMeshes2;

/**Populates aiScene members of pScene with own data and deletes self
* Equivalent to PopulateSceneSublevel() when out is 'this'.
*/
aiScene *TransferSceneDownLevel(aiScene *out = NULL);

/*Populates aiScene base members reflecting aiScene2 members*/
bool PopulateSceneSubLevel()
{
return TransferSceneDownLevel(this)!=NULL?true:false;
}

#ifdef __cplusplus
/** Constructor */
aiScene2(aiScene *cp) : aiScene(*cp)
{
mFlags2 = 0x00000000; mMeshes2 = NULL;
}
#endif // __cplusplus
};

} //end namespace Assimp_x

class DownLevelProcess
{
struct ProcessMeshHelper2;

public:

static int ProcessMesh2(const aiMesh2 *pIn, aiMesh** pOut, int iMaxOut)
{
return ProcessMeshHelper2(pIn,pOut,iMaxOut);
}

private:

struct ProcessMeshHelper2
{
/** The input will be decomposed into separate
* materials upto iMaxOut count. Any remaining meshes
* will not be carried over.
*/
ProcessMeshHelper2(const aiMesh2 *pIn, aiMesh** pOut, int iMaxOut);

~ProcessMeshHelper2();

inline operator int(){ return iCompleted; }

protected:

struct Parameters
{
union
{
//! omitted indices are presently -1
unsigned int mIndices[5];

struct //! for sake of clarity
{
unsigned int mMaterial;
unsigned int mVertex;
unsigned int mNormal;
unsigned int mColor;
unsigned int mTextureCoords; //or mTextureCoord?
};
};

bool mIsUnique;
bool mIsAssigned;

unsigned int mNewIndex;

Parameters *mMoreByVertexIndex;

inline bool operator==(const Parameters &o)
{
return memcmp(mIndices,o.mIndices,5*sizeof(int))==0;
}
inline bool operator!=(const Parameters &o)
{
return memcmp(mIndices,o.mIndices,5*sizeof(int))!=0;
}

Parameters()
{
mMaterial = 0;

for(int i=1;i<5;i++) mIndices[i] = -1;

mIsUnique = mIsAssigned = false;

mNewIndex = -1;
}

};

struct Material
{
aiMesh *mAssignedSubMesh;

unsigned int mMaterialIndex;

unsigned int mNumFacesApplicable;

Material *mNextInLoop;

Material(unsigned int iMatIndex, Material *pNext = NULL)
{
mAssignedSubMesh = NULL;

mMaterialIndex = iMatIndex;

mNextInLoop = pNext?pNext:this;

mNumFacesApplicable = 0;
}
};

unsigned int mNumBuffered;

Parameters* mBuffer;

unsigned int mNumIndexed;

Parameters** mIndex;

Material* mMaterials; //STL might be safer

Material* GetMaterial(unsigned int iMatIndex)
{
if(mMaterials==NULL) return mMaterials = new Material(iMatIndex);

if(mMaterials->mMaterialIndex==iMatIndex) return mMaterials;

Material *pOut = mMaterials->mNextInLoop;

while(pOut!=mMaterials&&pOut->mMaterialIndex!=iMatIndex)
pOut = pOut->mNextInLoop;

if(pOut==mMaterials)
pOut = pOut->mNextInLoop = new Material(iMatIndex,mMaterials);

//order could be optimized for meshes with many materials
return mMaterials = pOut;
}

Parameters* AddParameters(Parameters *pParams)
{
//! do not add to index if position parameter is omitted
if((signed)pParams->mVertex==-1) return pParams;

for(Parameters *pIter=mIndex[pParams->mVertex];
pIter&&pIter->mIsUnique;pIter++)
{
if(pIter->mIsUnique==false) break; //reached duplicate so this is unique

if(*pParams==*pIter)
{
while(pIter->mMoreByVertexIndex&&
pIter->mMoreByVertexIndex->mIsUnique)
pIter = pIter->mMoreByVertexIndex;

ai_assert(pParams->mIsUnique==false);

pParams->mMoreByVertexIndex = pIter->mMoreByVertexIndex;

return pIter->mMoreByVertexIndex = pParams;
}
}

pParams->mIsUnique = true;

pParams->mMoreByVertexIndex = mIndex[pParams->mVertex];

return mIndex[pParams->mVertex] = pParams;
}

const aiMesh2* pInput;

aiMesh** pOutput;

int iMaxOutput; ‎ 
int iCompleted;
};
};

DownLevelProcess::
ProcessMeshHelper2::ProcessMeshHelper2(const aiMesh2 *pIn, aiMesh** pOut, int iMaxOut)
{
memset(this,0x00,sizeof(ProcessMeshHelper2));

if(pIn==NULL||pOut==NULL||iMaxOut<=0) return;

pInput = pIn; pOutput = pOut; iMaxOutput = iMaxOut;

mNumIndexed = pIn->mNumVertices; mNumBuffered = 0;

for(unsigned int i=0;i<pIn->mNumFaces;i++)
mNumBuffered+=pIn->mFaces2[i].mNumCorners;

if(pIn->mSharedParameters)
{
mNumIndexed+=pIn->mSharedParameters->mNumVertices;

for(unsigned int i=0;i<pIn->mSharedParameters->mNumFaces;i++)
mNumBuffered+=pIn->mSharedParameters->mFaces2[i].mNumCorners;
}

mBuffer = new ProcessMeshHelper2::Parameters[mNumBuffered];
mIndex = new ProcessMeshHelper2::Parameters*[mNumIndexed];

memset(mBuffer,0x00,mNumBuffered*sizeof(ProcessMeshHelper2::Parameters*));
memset(mIndex,0x00,mNumIndexed*sizeof(void*));

unsigned int iCurParameters = 0;

for(unsigned int i=0;i<pIn->mNumFaces;i++)
{
ProcessMeshHelper2::Parameters *pParams = mBuffer+iCurParameters;

const aiFace2* pFace = pIn->mFaces2+i; //! MATERIAL

GetMaterial(pFace->mMaterialIndex)->mNumFacesApplicable++;

int iNumCorners = pFace->mNumCorners;

for(unsigned int j=0;j<iNumCorners;j++)
pParams[j].mMaterial = pFace->mMaterialIndex;

#define _AI_SAFE_FINDFACE2(Ps)\
{ pFace = pIn->FindFace2(pFace->m##Ps); ai_assert(pFace&&pFace->mNumCorners==iNumCorners); }

pFace = pIn->mFaces2+i; //! VERTICES

if(pFace->mParameterModes&aiParameterType_VERTEX) _AI_SAFE_FINDFACE2(Vertices)

if(pFace->mVertices!=0) for(unsigned int j=0;j<iNumCorners;j++)
pParams[j].mVertex = pFace->mIndices[pFace->mVertices+pFace->mStride*j];

pFace = pIn->mFaces2+i; //! NORMALS

if(pFace->mParameterModes&aiParameterType_NORMAL) _AI_SAFE_FINDFACE2(Normals)

if(pFace->mFaceFeatures&aiFaceFeature_NORMAL)
for(unsigned int j=0;j<iNumCorners;j++) pParams[j].mNormal = pFace->mIndices[0];
else if(pFace->mNormals!=0) for(unsigned int j=0;j<iNumCorners;j++)
pParams[j].mNormal = pFace->mIndices[pFace->mNormals+pFace->mStride*j];

pFace = pIn->mFaces2+i; //! COLORS

if(pFace->mParameterModes&aiParameterType_COLOR) _AI_SAFE_FINDFACE2(Colors)

if(pFace->mParameterModes&aiParameterType_COLOR)
for(unsigned int j=0;j<iNumCorners;j++) pParams[j].mColor = pFace->mIndices[1];
else if(pFace->mColors!=0) for(unsigned int j=0;j<iNumCorners;j++)
pParams[j].mColor = pFace->mIndices[pFace->mColors+pFace->mStride*j];

pFace = pIn->mFaces2+i; //! TEXTURECOORDS

if(pFace->mParameterModes&aiParameterType_TEXTURECOORDS) _AI_SAFE_FINDFACE2(TextureCoords)

if(pFace->mTextureCoords!=0) for(unsigned int j=0;j<iNumCorners;j++)
pParams[j].mTextureCoords = pFace->mIndices[pFace->mTextureCoords+pFace->mStride*j];

#undef _AI_SAFE_FINDFACE2

for(unsigned int j=0;j<iNumCorners;j++) AddParameters(pParams+j);

iCurParameters+=iNumCorners;
}

if(mMaterials==NULL) GetMaterial(pIn->mMaterialIndex);

Material *pIter = mMaterials;

for(unsigned int i=0;i<iMaxOut;i++)
{
pIter->mAssignedSubMesh = pOut[i] = new aiMesh;

pOut[i]->mPrimitiveTypes = pIn->mPrimitiveTypes;

pOut[i]->mFaces = new aiFace[pIter->mNumFacesApplicable];

for(unsigned int j=0;j<AI_MAX_NUMBER_OF_COLOR_SETS;j++)
pOut[i]->mNumUVComponents[j] = pIn->mNumUVComponents[j];

for(unsigned int j=0;j<AI_MAX_NUMBER_OF_TEXTURECOORDS;j++)
pOut[i]->mNumUVComponents[j] = pIn->mNumUVComponents[j];

pOut[i]->mMaterialIndex = pIter->mMaterialIndex;

unsigned int iNumVertices = 0;

for(unsigned int j=0;j<mNumBuffered;j++)
if(mBuffer[j].mMaterial==pIter->mMaterialIndex&&
mBuffer[j].mIsUnique==true)
iNumVertices++;

if(pIn->HasPositions())
pOut[i]->mVertices = new aiVector3D[iNumVertices];
if(pIn->HasNormals())
pOut[i]->mNormals = new aiVector3D[iNumVertices];
if(pIn->HasTangentsAndBitangents())
{ pOut[i]->mTangents = new aiVector3D[iNumVertices];
pOut[i]->mBitangents = new aiVector3D[iNumVertices]; }

int iNumChs = pIn->GetNumColorChannels();

for(unsigned int j=0;j<iNumChs;j++)
pOut[i]->mColors[j] = new aiColor4D[iNumVertices];

iNumChs = pIn->GetNumUVChannels();

for(unsigned int j=0;j<iNumChs;j++)
pOut[i]->mTextureCoords[j] = new aiVector3D[iNumVertices];

if(pIter->mNextInLoop==mMaterials) break;
}

//! Break out the non-unique vertices
for(unsigned int j=0;j<mNumBuffered;j++)
if(mBuffer[j].mIsUnique==true&&
mBuffer[j].mMoreByVertexIndex!=NULL&&
mBuffer[j].mMoreByVertexIndex->mIsUnique==false)
mBuffer[j].mMoreByVertexIndex = NULL;

iCurParameters = 0;

for(unsigned int i=0;i<pIn->mNumFaces;i++)
{
const aiFace2* pFace = pIn->mFaces2+i;

aiMesh *pSubMesh = GetMaterial(pFace->mMaterialIndex)->mAssignedSubMesh;
aiFace* pNewFace = pSubMesh->mFaces+pSubMesh->mNumFaces;

ProcessMeshHelper2::Parameters *pParams = mBuffer+iCurParameters;

iCurParameters+=pFace->mNumCorners;

if((signed)pParams->mVertex==-1) continue;

pNewFace->mIndices = new unsigned int[pNewFace->mNumIndices];

for(unsigned int j=0;j<pFace->mNumCorners;j++)
{
Parameters *pCmp = mIndex[pParams[j].mVertex];

while(pCmp&&*pCmp!=pParams[j]) pCmp++; ai_assert(pCmp!=NULL);

if(pCmp->mIsAssigned==false)
{
int iThisVert = pSubMesh->mNumVertices++;

if(pSubMesh->mVertices)
ai_assert(pIn->GetPosition(pCmp->mVertex,pSubMesh->mVertices+iThisVert));
if(pSubMesh->mNormals)
ai_assert(pIn->GetNormal(pCmp->mNormal,pSubMesh->mNormals+iThisVert));
if(pSubMesh->mTangents)
ai_assert(pIn->GetTangent(pCmp->mNormal,pSubMesh->mTangents+iThisVert));
if(pSubMesh->mBitangents)
ai_assert(pIn->GetBitangent(pCmp->mNormal,pSubMesh->mBitangents+iThisVert));

int iNumChs = pIn->GetNumColorChannels();

for(unsigned int k=0;k<iNumChs;k++)
ai_assert(pIn->GetVertexColor(k,pCmp->mColor,pSubMesh->mColors[k]+iThisVert));

iNumChs = pIn->GetNumUVChannels();

for(unsigned int k=0;k<iNumChs;k++)
ai_assert(pIn->GetTextureCoord(k,pCmp->mTextureCoords,
pSubMesh->mTextureCoords[k]+iThisVert));
pCmp->mNewIndex = iThisVert;
pCmp->mIsAssigned = true;
}

pNewFace->mIndices[j] = pCmp->mNewIndex;
}

pNewFace->mNumIndices = pFace->mNumCorners;
pSubMesh->mNumFaces++;
}

while(pOut[iCompleted]&&++iCompleted<iMaxOut);
}

DownLevelProcess::
ProcessMeshHelper2::~ProcessMeshHelper2()
{
if(mBuffer) delete [] mBuffer;
if(mIndex) delete [] mIndex;

if(mMaterials==NULL) return;

Material *pIter = mMaterials->mNextInLoop;

while(pIter!=mMaterials)
{
Material *pDtor = pIter; pIter = pIter->mNextInLoop;

delete pDtor;
}

delete mMaterials;
}

aiScene *aiScene2::TransferSceneDownLevel(aiScene *out)
{
//TODO: validate mMeshes fitness / mMeshes2

unsigned int n = mNumMeshes; aiMesh2 **m2 = mMeshes2;

aiMesh** m = NULL; if(n) m = new aiMesh*[n];

memset(m,0x00,sizeof(void*)*n);

unsigned int *mats = NULL;

for(unsigned int i=0,j=0;i<n;i++) if(m2[i])
{
for(j=1;j<m2[i]->mNumMaterials;j++)

if(j>=n||mMeshes2[j]!=NULL) goto failure;

if(DownLevelProcess::ProcessMesh2(m2[i],m+i,j)==0)
goto failure;
}

goto success;

failure:

for(unsigned int i=0;i<n;i++) if(m[i]) delete m[i];

if(m) delete [] m; if(mats) delete [] mats;

return NULL;

success:

//! same as PopulateSceneSublevel()
if(out==this) return this;

if(out==NULL) out = new aiScene;

mNumMeshes = 0; mMeshes2 = NULL;

memcpy(out,this,sizeof(aiScene));
memcpy(this,0x00,sizeof(aiScene));

for(unsigned int i=0;i<n;i++) if(m2[i]) delete m2[i];

delete [] m2; delete this;

out->mMeshes = m; out->mNumMeshes = n;

return out;
}

SomFileHelper::SomFileHelper(const void *eof, aiScene *out)
{
pcEof = eof; pAssimp = out;

pAssimp2 = NULL; if(pAssimp==NULL) return;

pAssimp2 = new aiScene2(out);
}

SomFileHelper::~SomFileHelper()
{
if(pAssimp==NULL) return;

pAssimp2->TransferSceneDownLevel(pAssimp);
} ‎ 

bool SomFileHelper::detect(const MDL::Header_SOM *in)const
{
#ifdef NDEBUG
return false; //work in progress
#endif

ai_assert(pcEof!=NULL);

if(!in->num_parts)
{
if(pAssimp) throw new ImportErrorException("[Sword of Moonlight MDL] A MDL must contain at least one model");

return false;
}

if(!pAssimp) return true;

ai_assert(pAssimp2->mNumMeshes==0);

pAssimp2->mNumMeshes = 1+AI_BE(in->num_parts)*AI_BE(in->num_skins);

pAssimp2->mMeshes2 = new aiMesh2*[pAssimp2->mNumMeshes];

memset(pAssimp2->mMeshes2,0x00,sizeof(void*)*pAssimp2->mNumMeshes);

MaterialHelper *pMatDefault = new MaterialHelper;

const int iMode = (int)aiShadingMode_Gouraud;

pMatDefault->AddProperty<int>(&iMode,1,AI_MATKEY_SHADING_MODEL);

pAssimp2->mNumMaterials = max(AI_BE(in->num_skins),1);

pAssimp2->mMaterials = new aiMaterial*[pAssimp2->mNumMaterials];

for(unsigned int i=0;i<pAssimp2->mNumMaterials;i++)

pAssimp2->mMaterials[i] = pMatDefault;

return true; //TODO: flesh out
}

const int32_t *SomFileHelper::offset(const MDL::Header_SOM *in, int cc, int pt)const
{
return (const int32_t*)(in?(const char*)in+in->offset(cc,pt)*4:NULL);
}

bool SomFileHelper::unpack(const MDL::Header_SOM *in,
‎  const MDL::Packet_SOM **inout, int cc, int pt)const
{
ai_assert(pAssimp&&pcEof);

const MDL::Packet_SOM *p = *inout;

pAssimp2->mFlags2|=AI_SCENE_FLAGS2_INCOMPLETE;

unsigned int iPart = 1+pt*AI_BE(in->num_skins);

ai_assert(pAssimp2!=NULL&&pAssimp2->mNumMeshes>=iPart);

aiMesh2 *pPart = pAssimp2->mMeshes2[iPart];

if(pPart==NULL) switch(cc)
{
case 'face': case 'vert': case 'norm':

pPart = pAssimp2->mMeshes2[iPart] = new aiMesh2;

pPart->mPrimitiveTypes =
aiPrimitiveType_TRIANGLE|aiPrimitiveType_POLYGON;

pPart->mSharedParameters = pAssimp2->mMeshes2[0];

pPart->mNumMaterials = AI_BE(in->num_skins);


}

switch(cc)
{
case 'base': //! shared parameters block (uv components more or less)
{
int iShared = AI_BE(p->lo); if(iShared==0) return false; //block is empty

sizecheck((const char*)p+4+iShared*12); //! expected end of block

ai_assert(pAssimp2->mNumMeshes==0&&pAssimp2->mMeshes2!=NULL);

int iCurMaterial = AI_BE(p->hi); int iCurIndex = 0;

aiMesh2 *pShared = pAssimp2->mMeshes2[0] = new aiMesh2; //shared mesh

pShared->mNumMaterials = 1; pShared->mMaterialIndex = iCurMaterial;

pShared->mNumUVComponents[0] = 2;

pShared->mTextureCoords[0] = new aiVector3D[pShared->mNumTextureCoords=iShared*4];

for(int i=0;i<iShared;i++) if((++p)->hi==0)
{
aiFace2 *pFace2 = pShared->mFaces2+i;

pFace2->mMaterialIndex = iCurMaterial;

pFace2->mIndices = new unsigned int[pFace2->mNumIndices=5];

memset(pFace2->mIndices,0x00,5*sizeof(int));

pFace2->mNumCorners = 4; pFace2->mStride = 1;

pFace2->mTextureCoords = 1;

pShared->mTextureCoords[0][iCurIndex] = aiVector3D(p->s,p->t,0.0f); //lo

pFace2->mIndices[1] = iCurIndex++; p++;

pShared->mTextureCoords[0][iCurIndex] = aiVector3D(p->s,p->t,0.0f); //lo

//! Note that the hi 16bits here house potentially meaningful flags

pFace2->mIndices[2] = iCurIndex++; p++; ‎ 

pShared->mTextureCoords[0][iCurIndex] = aiVector3D(p->s,p->t,0.0f); //lo

pFace2->mIndices[3] = iCurIndex++;

pShared->mTextureCoords[0][iCurIndex] = aiVector3D(p->u,p->v,0.0f); //hi

pFace2->mIndices[4] = iCurIndex++;
}
else
{
DefaultLogger::get()->warn("Sword of Moonlight MDL shared texture mapping block not as expected. Block left incomplete");

return false;
}

break;
}
case 'face': //! face packets block
{
int iFaces = AI_BE(in->parts[pt].num_faces);

if(iFaces==0||p->lo==0) return false; //faces absent

pPart->mFaces2 = new aiFace2[pPart->mNumFaces=iFaces];

for(int i=0;i<iFaces;i++) if((++p+1)->hi==0)
{
aiFace2 *pFace2 = pPart->mFaces2+i;




//TODO: tomorrow.........................


}

break;
}
case 'vert': //! vertex packets block
{
int iVerts = AI_BE(in->parts[pt].num_verts);

if(iVerts==0) return false; //vertices absent

sizecheck((const char*)p+iVerts*8); //expected end of block

pPart->mVertices = new aiVector3D[pPart->mNumVertices=iVerts];

for(int i=0;i<iVerts;i++) if((p+1)->hi==0)
{
pPart->mVertices[i].x = (int16_t)AI_BE(p->lo);
pPart->mVertices[i].y = (int16_t)AI_BE(p->hi); p++;
pPart->mVertices[i].z = (int16_t)AI_BE(p->lo);
}
else
{
DefaultLogger::get()->warn("Sword of Moonlight MDL high 16bits of 2nd packet in vertex block non-zero. Block left incomplete");

return false;
}

break;
}
case 'norm': //! normal packets block
{
int iNorms = AI_BE(in->parts[pt].num_norms);

if(iNorms==0) return false; //normals absent

sizecheck((const char*)p+iNorms*8); //expected end of block

pPart->mNormals = new aiVector3D[pPart->mNumNormals=iNorms];

for(int i=0;i<iNorms;i++) if((p+1)->hi==0)
{
pPart->mNormals[i].x = (int16_t)AI_BE(p->lo);
pPart->mNormals[i].y = (int16_t)AI_BE(p->hi); p++;
pPart->mNormals[i].z = (int16_t)AI_BE(p->lo);
}
else
{
DefaultLogger::get()->warn("Sword of Moonlight MDL high 16bits of 2nd packet in normals block non-zero. Block left incomplete");

return false;
}

break;
}
case 'anim': //! reference frame (skeletal) animation block
{
if(in->num_anims==0||in->add_anims==0) return false; //animation absent

return false; //unimplemented thus far
}
case 'stop': //! stop-motion (deformer) animation block
{
if(in->num_stops==0||in->add_stops==0) return false; //animation absent

return false; //unimplemented thus far
}
default: return false;
}

pAssimp2->mFlags2&=~AI_SCENE_FLAGS2_INCOMPLETE;

*inout = p; return false;
}

static void TIMpixelmode2(aiTexel *inout, uint16_t pm2)
{
inout->r = (pm2&0x1F)*8; inout->g = ((pm2&0x3E0)>>8)*8;

inout->b = ((pm2&0x7C00)>>8)*8; inout->a = 0;
}

bool SomFileHelper::bitmap(const MDL::Header_SOM *in, const MDL::Bitmap_SOM **inout)const
{
ai_assert(pAssimp&&pcEof);

if(in->num_skins==0) return false;

const MDL::Bitmap_SOM *p = *inout;

if(p->id!=0x10)
{
DefaultLogger::get()->warn("Sword of Moonlight MDL texture appears not to be TIM bitmap format. Ignoring further texture data");

return false;
}

const MDL::Bitmap_SOM::BLOCK *clut = p->clut_block();
const MDL::Bitmap_SOM::BLOCK *data = p->data_block();

if(p->pmode<0x02&&clut==0)
{
DefaultLogger::get()->warn("Sword of Moonlight MDL texture appears to contain paletted data but is missing a color lookup table. Ignoring further texture data");

return false;
}

sizecheck((const char*)data+AI_BE(data->bnum));
sizecheck((const char*)data+2*AI_BE(data->w)*AI_BE(data->h)+12);

if(clut) sizecheck((const char*)clut+AI_BE(clut->bnum));
if(clut) sizecheck((const char*)clut+2*AI_BE(clut->w)*AI_BE(clut->h)+12);

if(pAssimp2->mNumTextures>=in->num_skins)
{
DefaultLogger::get()->warn("Sword of Moonlight MDL texture appears to have exceeded the ammount indicated by the header. Ignoring further texture data");

return false;
}

if(!pAssimp2->mNumTextures) pAssimp2->mTextures = new aiTexture*[in->num_skins];

aiTexture *q = pAssimp2->mTextures[pAssimp2->mNumTextures] = new aiTexture;

float fWidth = AI_BE(data->w);

switch(p->pmode)
{
case 0x00: fWidth*=4.0f; break;
case 0x01: fWidth*=2.0f; break;
case 0x02: ‎  ‎  ‎  ‎  ‎  ‎  ‎  break;
case 0x03:
case 0x04: fWidth = fWidth/3.0f*2.0f;
}

if(fWidth-int(fWidth)!=0.0f)
{
DefaultLogger::get()->warn("Sword of Moonlight MDL texture width appears not to comply with TIM Pixel mode specification. Ignoring further textures");

return false;
}

q->mWidth = (unsigned int)fWidth; q->mHeight = AI_BE(data->h);

aiTexel *d = q->pcData = new aiTexel[q->mWidth*q->mHeight];

if(p->pmode==0x04) DefaultLogger::get()->warn("Sword of Moonlight MDL texture appears to be \"mixed\" mode. Interpreting as 24bit color");

int h = AI_BE(data->h), w = AI_BE(data->w);

for(int i=0;i<h;i++) for(int j=0;j<w;j++)
{
uint16_t e = data->data[i*w+j]; AI_SWAP2(e);

switch(p->pmode)
{
case 0x00:

TIMpixelmode2(d++,clut->data[(e&&0x000F)>>0]);
TIMpixelmode2(d++,clut->data[(e&&0x00F0)>>4]);
TIMpixelmode2(d++,clut->data[(e&&0x0F00)>>8]);
TIMpixelmode2(d++,clut->data[(e&&0xF000)>>12]); break;

case 0x01:

TIMpixelmode2(d++,clut->data[(e&&0x00FF)>>0]);
TIMpixelmode2(d++,clut->data[(e&&0xFF00)>>8]); break;

case 0x02: TIMpixelmode2(d,e); break;

case 0x03: case 0x04:

d->r = e&0xFF; d->g = (e&0xFF00)>>8;

e = data->data[i*w+++j]; AI_SWAP2(e);

d->b = e&0xFF; d->a = 0;

++d->r = (e&0xFF00)>>8;

e = data->data[i*w+++j]; AI_SWAP2(e);

d->g = e&0xFF; d->b = (e&0xFF00)>>8;

d->a = 0; d++;
}
}

pAssimp2->mNumTextures++;

int next = sizeof(MDL::Bitmap_SOM)+data->bnum;

if(clut) next+=clut->bnum;

*(char**)inout+=next;

if(pAssimp2->mNumTextures>=in->num_skins) return false;

return true;
}
[/code]


EDITED: I was getting a maximum of something like 300000 characters (plus or minus a figure) so I was going to add the cpp file as an attachment but the second shot (minus just the license header) little did I know must've gone thru.

Let Todd decide if the character limit seems practical or not.
Reply



Messages In This Thread
MDL - by HolyDiver - 2010-04-02, 04:35 PM
Re: MDL - by HolyDiver - 2010-04-02, 07:17 PM
Re: MDL - by HolyDiver - 2010-04-05, 04:05 AM
Re: MDL - by Madison Lastrega - 2010-04-06, 06:28 AM
Re: MDL - by Madison Lastrega - 2010-04-06, 07:19 AM
Re: MDL - by HolyDiver - 2010-04-06, 06:56 PM
Re: MDL - by HolyDiver - 2010-04-06, 11:27 PM
Re: MDL - by Madison Lastrega - 2010-04-07, 05:17 PM
Re: MDL - by HolyDiver - 2010-04-07, 06:23 PM
Re: MDL - by HolyDiver - 2010-04-08, 03:18 AM
Re: MDL - by HolyDiver - 2010-04-08, 10:19 PM
Re: MDL - by Madison Lastrega - 2010-04-10, 05:15 AM
Re: MDL - by HolyDiver - 2010-04-10, 05:55 AM
Re: MDL - by Madison Lastrega - 2010-04-10, 07:22 PM
Re: MDL - by HolyDiver - 2010-04-10, 09:22 PM
Re: MDL - by HolyDiver - 2010-04-10, 09:24 PM
Re: MDL - by HolyDiver - 2010-04-20, 10:48 AM
Re: MDL - by HolyDiver - 2010-04-21, 01:45 PM
Re: MDL - by HolyDiver - 2010-05-03, 01:06 AM
Re: MDL - by HolyDiver - 2010-05-03, 07:59 PM
Re: MDL - by HolyDiver - 2010-05-04, 12:16 AM
Re: MDL - by HolyDiver - 2010-05-07, 07:27 AM
Re: MDL - by HolyDiver - 2010-05-10, 11:29 AM



Users browsing this thread:
6 Guest(s)