Finished loading of MD2, MD3, MDL2, MDL3, MDL4, MDL5, MDL7, MDL. First WIP version of the SMD loader. Additionals checks added to the validation step.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@60 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
aramis_acg
2008-06-22 10:09:26 +00:00
parent 758e092449
commit b422d4e303
90 changed files with 7349 additions and 2105 deletions
+26 -23
View File
@@ -40,11 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file Implementation of the 3ds importer class */
// internal headers
#include "3DSLoader.h"
#include "MaterialSystem.h"
#include "TextureTransform.h"
#include "StringComparison.h"
#include "qnan.h"
// public ASSIMP headers
#include "../include/DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
@@ -52,7 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
#include <boost/scoped_ptr.hpp>
using namespace Assimp;
@@ -427,10 +430,12 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
a != (*i).mFaceMaterials.end();++a,++iNum)
{
// check range
if ((*a) >= this->mScene->mMaterials.size())
if ((*a) >= this->mScene->mMaterials.size())
{
// use the last material instead
aiSplit[this->mScene->mMaterials.size()-1].push_back(iNum);
DefaultLogger::get()->error("Face material index is out of range");
// use the last material instead
aiSplit[this->mScene->mMaterials.size()-1].push_back(iNum);
}
else aiSplit[*a].push_back(iNum);
}
@@ -450,15 +455,15 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
p_pcOut->mColors[0] = (aiColor4D*)new std::string((*i).mName);
avOutMeshes.push_back(p_pcOut);
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
if (bFirst)
{
p_pcOut->mColors[1] = (aiColor4D*)new aiMatrix4x4();
*((aiMatrix4x4*)p_pcOut->mColors[1]) = (*i).mMat;
bFirst = false;
}
#endif
// convert vertices
p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
@@ -519,16 +524,6 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
// apply texture coordinate scalings
TextureTransform::BakeScaleNOffset ( p_pcOut, &this->mScene->mMaterials[
p_pcOut->mMaterialIndex] );
// setup bitflags to indicate which texture coordinate
// channels are used
p_pcOut->mNumUVComponents[0] = 2;
if (p_pcOut->HasTextureCoords(1))
p_pcOut->mNumUVComponents[1] = 2;
if (p_pcOut->HasTextureCoords(2))
p_pcOut->mNumUVComponents[2] = 2;
if (p_pcOut->HasTextureCoords(3))
p_pcOut->mNumUVComponents[3] = 2;
}
}
}
@@ -579,6 +574,8 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
{
const unsigned int iIndex = iArray[i];
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
if (NULL != pcSOut->mMeshes[iIndex]->mColors[1])
{
pcOut->mTransformation = *((aiMatrix4x4*)
@@ -587,7 +584,7 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
delete (aiMatrix4x4*)pcSOut->mMeshes[iIndex]->mColors[1];
pcSOut->mMeshes[iIndex]->mColors[1] = NULL;
}
#endif
pcOut->mMeshes[i] = iIndex;
}
@@ -681,11 +678,17 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
pcNode->mMeshes[0] = i;
pcNode->mNumMeshes = 1;
std::string s;
std::stringstream ss(s);
ss << "UNNAMED[" << i << + "]";
pcNode->mName.Set(s);
char szBuffer[128];
int iLen;
#if _MSC_VER >= 1400
iLen = sprintf_s(szBuffer,"UNNAMED_%i",i);
#else
iLen = sprintf(szBuffer,"UNNAMED_%i",i);
#endif
ai_assert(0 < iLen);
::memcpy(pcNode->mName.data,szBuffer,iLen);
pcNode->mName.data[iLen] = '\0';
pcNode->mName.length = iLen;
// add the new child to the parent node
pcOut->mRootNode->mChildren[i] = pcNode;
+26 -30
View File
@@ -93,10 +93,22 @@ public:
//! From AutoDesk 3ds SDK
typedef enum
{
// translated to gouraud shading with wireframe active
Wire = 0,
// if this material is set, no vertex normals will
// be calculated for the model. Face normals + gouraud
Flat = 1,
// standard gouraud shading
Gouraud = 2,
// phong shading
Phong = 3,
// cooktorrance or anistropic phong shading ...
// the exact meaning is unknown, if you know it
// feel free to tell me ;-)
Metal = 4,
// required by the ASE loader
@@ -127,7 +139,8 @@ public:
CHUNK_PERCENTF = 0x0031, // float4 percentage
// **************************************************************
// Unknown and ignored
// Unknown and ignored. Possibly a chunk used by PROJ (
// Discreet 3DS max Project File)?
CHUNK_PRJ = 0xC23D,
// Unknown. Possibly a reference to an external .mli file?
@@ -387,9 +400,10 @@ struct Material
mTwoSided (false)
{
static int iCnt = 0;
std::stringstream ss;
ss << "$$_UNNAMED_" << iCnt++ << "_$$";
ss >> mName;
char szTemp[128];
sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
mName = szTemp;
}
//! Name of the material
@@ -442,9 +456,10 @@ struct Mesh
Mesh()
{
static int iCnt = 0;
std::stringstream ss;
ss << "$$_UNNAMED_" << iCnt++ << "_$$";
ss >> mName;
char szTemp[128];
sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
mName = szTemp;
}
//! Name of the mesh
@@ -481,9 +496,10 @@ struct Node
{
static int iCnt = 0;
std::stringstream ss;
ss << "$$_UNNAMED_" << iCnt++ << "_$$";
ss >> mName;
char szTemp[128];
sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
mName = szTemp;
mHierarchyPos = 0;
mHierarchyIndex = 0;
@@ -538,26 +554,6 @@ struct Scene
Node* pcRootNode;
};
// ---------------------------------------------------------------------------
inline bool is_qnan(float p_fIn)
{
// NOTE: Comparison against qnan is generally problematic
// because qnan == qnan is false AFAIK
union FTOINT
{
float fFloat;
int32_t iInt;
} one, two;
one.fFloat = std::numeric_limits<float>::quiet_NaN();
two.fFloat = p_fIn;
return (one.iInt == two.iInt);
}
// ---------------------------------------------------------------------------
inline bool is_not_qnan(float p_fIn)
{
return !is_qnan(p_fIn);
}
} // end of namespace Dot3DS
} // end of namespace Assimp
+21 -29
View File
@@ -40,11 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file Implementation of the 3ds importer class */
// internal headers
#include "3DSLoader.h"
#include "MaterialSystem.h"
#include "TextureTransform.h"
#include "StringComparison.h"
#include "qnan.h"
// public ASSIMP headers
#include "../include/DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
@@ -52,14 +56,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
// boost headers
#include <boost/scoped_ptr.hpp>
using namespace Assimp;
#define ASSIMP_3DS_WARN_CHUNK_OVERFLOW_MSG \
"WARNING: Size of chunk data plus size of " \
"subordinate chunks is larger than the size " \
"specified in the higher-level chunk header." \
#if (!defined ASSIMP_3DS_WARN_CHUNK_OVERFLOW_MSG)
# define ASSIMP_3DS_WARN_CHUNK_OVERFLOW_MSG \
"WARNING: Size of chunk data plus size of " \
"subordinate chunks is larger than the size " \
"specified in the top-level chunk header."
#endif
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
@@ -92,22 +99,6 @@ bool Dot3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) co
return false;
}
// ------------------------------------------------------------------------------------------------
// recursively delete a given node
void DeleteNodeRecursively (aiNode* p_piNode)
{
if (!p_piNode)return;
if (p_piNode->mChildren)
{
for (unsigned int i = 0 ; i < p_piNode->mNumChildren;++i)
{
DeleteNodeRecursively(p_piNode->mChildren[i]);
}
}
delete p_piNode;
return;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void Dot3DSImporter::InternReadFile(
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
@@ -125,7 +116,7 @@ void Dot3DSImporter::InternReadFile(
size_t fileSize = file->FileSize();
if( fileSize < 16)
{
throw new ImportErrorException( ".3ds File is too small.");
throw new ImportErrorException( "3DS File is too small.");
}
this->mScene = new Dot3DS::Scene();
@@ -780,8 +771,9 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
case Dot3DSFile::CHUNK_FACEMAT:
// at fist an asciiz with the material name
while (*sz++ != '\0')
while (*sz++)
{
// make sure we don't run over the end of the chunk
if (sz > pcCurNext-1)break;
}
@@ -800,7 +792,7 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
break;
}
}
if (iIndex == 0xFFFFFFFF)
if (0xFFFFFFFF == iIndex)
{
// this material is not known. Ignore this. We will later
// assign the default material to all faces using *this*
@@ -818,13 +810,14 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
// check range
if (iTemp >= mMesh.mFaceMaterials.size())
{
{
DefaultLogger::get()->error("Invalid face index in face material list");
mMesh.mFaceMaterials[mMesh.mFaceMaterials.size()-1] = iIndex;
}
}
else
{
{
mMesh.mFaceMaterials[iTemp] = iIndex;
}
}
this->mCurrent += sizeof(uint16_t);
}
@@ -959,8 +952,7 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
}
break;
#if (defined _DEBUG)
#if 0
case Dot3DSFile::CHUNK_TXTINFO:
// for debugging purposes. Read two bytes to determine the mapping type
+7 -1
View File
@@ -40,13 +40,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file Implementation of the ASE importer class */
// internal headers
#include "ASELoader.h"
#include "3DSSpatialSort.h"
#include "MaterialSystem.h"
#include "StringComparison.h"
#include "TextureTransform.h"
#include "fast_atof.h"
// utilities
#include "fast_atof.h"
#include "qnan.h"
// ASSIMP public headers
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiMesh.h"
+10 -2
View File
@@ -111,7 +111,7 @@ public:
// -------------------------------------------------------------------
/** Imports the given file and returns the imported data.
* If the import succeeds, ownership of the data is transferred to
* the caller. If the import failes, NULL is returned. The function
* the caller. If the import fails, NULL is returned. The function
* takes care that any partially constructed data is destroyed
* beforehand.
*
@@ -154,7 +154,15 @@ protected:
* an error. If it terminates normally, the data in aiScene is
* expected to be correct. Override this function to implement the
* actual importing.
*
* <br>
* The output scene must meet the following conditions:<br>
* - at least one mesh must be there<br>
* - at least a root node must be there<br>
* - at least one material must be there<br>
* - there may be no meshes with 0 vertices or faces<br>
* This won't be checked (except by the validation step), Assimp will
* crash if one of the conditions is not met!
*
* @param pFile Path of the file to be imported.
* @param pScene The scene object to hold the imported data.
* NULL is not a valid parameter.
+10 -6
View File
@@ -53,7 +53,7 @@ DefaultIOStream::~DefaultIOStream()
{
if (this->mFile)
{
fclose(this->mFile);
::fclose(this->mFile);
}
}
// ---------------------------------------------------------------------------
@@ -61,20 +61,24 @@ size_t DefaultIOStream::Read(void* pvBuffer,
size_t pSize,
size_t pCount)
{
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
if (!this->mFile)
return 0;
return fread(pvBuffer, pSize, pCount, this->mFile);
return ::fread(pvBuffer, pSize, pCount, this->mFile);
}
// ---------------------------------------------------------------------------
size_t DefaultIOStream::Write(const void* pvBuffer,
size_t pSize,
size_t pCount)
{
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
if (!this->mFile)return 0;
fseek(mFile, 0, SEEK_SET);
return fwrite(pvBuffer, pSize, pCount, this->mFile);
::fseek(mFile, 0, SEEK_SET);
return ::fwrite(pvBuffer, pSize, pCount, this->mFile);
}
// ---------------------------------------------------------------------------
aiReturn DefaultIOStream::Seek(size_t pOffset,
@@ -82,7 +86,7 @@ aiReturn DefaultIOStream::Seek(size_t pOffset,
{
if (!this->mFile)return AI_FAILURE;
return (0 == fseek(this->mFile, (long)pOffset,
return (0 == ::fseek(this->mFile, (long)pOffset,
(aiOrigin_CUR == pOrigin ? SEEK_CUR :
(aiOrigin_END == pOrigin ? SEEK_END : SEEK_SET)))
? AI_SUCCESS : AI_FAILURE);
@@ -92,7 +96,7 @@ size_t DefaultIOStream::Tell() const
{
if (!this->mFile)return 0;
return ftell(this->mFile);
return ::ftell(this->mFile);
}
// ---------------------------------------------------------------------------
size_t DefaultIOStream::FileSize() const
+3 -3
View File
@@ -65,11 +65,11 @@ DefaultIOSystem::~DefaultIOSystem()
// Tests for the existence of a file at the given path.
bool DefaultIOSystem::Exists( const std::string& pFile) const
{
FILE* file = fopen( pFile.c_str(), "rb");
FILE* file = ::fopen( pFile.c_str(), "rb");
if( !file)
return false;
fclose( file);
::fclose( file);
return true;
}
@@ -77,7 +77,7 @@ bool DefaultIOSystem::Exists( const std::string& pFile) const
// Open a new file with a given path.
IOStream* DefaultIOSystem::Open( const std::string& strFile, const std::string& strMode)
{
FILE* file = fopen( strFile.c_str(), strMode.c_str());
FILE* file = ::fopen( strFile.c_str(), strMode.c_str());
if( NULL == file)
return NULL;
+449
View File
@@ -0,0 +1,449 @@
/*
---------------------------------------------------------------------------
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 MDL importer class */
#include "MaterialSystem.h"
#include "HMPLoader.h"
#include "../include/DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
#include <boost/scoped_ptr.hpp>
using namespace Assimp;
extern float g_avNormals[162][3];
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
HMPImporter::HMPImporter()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
HMPImporter::~HMPImporter()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
{
// simple check of file extension is enough for the moment
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)
return false;
std::string extension = pFile.substr( pos);
if (extension.length() < 4)return false;
if (extension[0] != '.')return false;
if (extension[1] != 'h' && extension[1] != 'H')return false;
if (extension[2] != 'm' && extension[2] != 'M')return false;
if (extension[3] != 'p' && extension[3] != 'P')return false;
return true;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void HMPImporter::InternReadFile(
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file
if( file.get() == NULL)
{
throw new ImportErrorException( "Failed to open HMP file " + pFile + ".");
}
// check whether the ply file is large enough to contain
// at least the file header
size_t fileSize = file->FileSize();
if( fileSize < 50)
{
throw new ImportErrorException( ".hmp File is too small.");
}
// allocate storage and copy the contents of the file to a memory buffer
this->pScene = pScene;
this->pIOHandler = pIOHandler;
this->mBuffer = new unsigned char[fileSize+1];
file->Read( (void*)mBuffer, 1, fileSize);
this->iFileSize = (unsigned int)fileSize;
// determine the file subtype and call the appropriate member function
uint32_t iMagic = *((uint32_t*)this->mBuffer);
try {
// HMP4 format
if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_4 == iMagic)
{
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4");
this->InternReadFile_HMP4();
}
// HMP5 format
else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_5 == iMagic)
{
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5");
this->InternReadFile_HMP5();
}
// HMP7 format
else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_7 == iMagic)
{
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7");
this->InternReadFile_HMP7();
}
else
{
// we're definitely unable to load this file
throw new ImportErrorException( "Unknown HMP subformat " + pFile +
". Magic word is not known");
}
} catch (ImportErrorException* ex) {
delete[] this->mBuffer;
throw ex;
}
// delete the file buffer
delete[] this->mBuffer;
return;
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP4( )
{
throw new ImportErrorException("HMP4 is currently not supported");
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP5( )
{
throw new ImportErrorException("HMP4 is currently not supported");
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP7( )
{
if (120 > this->iFileSize)
{
throw new ImportErrorException("HMP7 file is too small (header size is "
"120 bytes, this file is smaller)");
}
// read the file header and skip everything to byte 84
const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)this->mBuffer;
const unsigned char* szCurrent = (const unsigned char*)(this->mBuffer+84);
if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y ||
pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f ||
!pcHeader->numframes)
{
throw new ImportErrorException("One or more of the values in the HMP7 "
"file header are invalid.");
}
// generate an output mesh
this->pScene->mNumMeshes = 1;
this->pScene->mMeshes = new aiMesh*[1];
aiMesh* pcMesh = this->pScene->mMeshes[0] = new aiMesh();
pcMesh->mMaterialIndex = 0;
pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
// we don't need to generate texture coordinates if
// we have no textures in the file ...
if (pcHeader->numskins)
{
pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts];
pcMesh->mNumUVComponents[0] = 2;
// now read the first skin and skip all others
this->ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent);
}
else
{
// generate a default material
const int iMode = (int)aiShadingMode_Gouraud;
MaterialHelper* pcHelper = new MaterialHelper();
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
aiColor3D clr;
clr.b = clr.g = clr.r = 0.7f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
// add the material to the scene
this->pScene->mNumMaterials = 1;
this->pScene->mMaterials = new aiMaterial*[1];
this->pScene->mMaterials[0] = pcHelper;
}
// goto offset 120, I don't know why ...
// (fixme) is this the frame header? I assume yes since it starts
// with 2.
szCurrent += 36;
this->SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
// now load all vertices from the file
aiVector3D* pcVertOut = pcMesh->mVertices;
aiVector3D* pcNorOut = pcMesh->mNormals;
const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent;
for (unsigned int y = 0; y < height;++y)
{
for (unsigned int x = 0; x < width;++x)
{
pcVertOut->x = x * pcHeader->ftrisize_x;
pcVertOut->y = y * pcHeader->ftrisize_y;
// FIXME: What exctly is the correct scaling factor to use?
// possibly pcHeader->scale_origin[2] in combination with a
// signed interpretation of src->z?
pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0];
pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1];
pcNorOut->z = 1.0f;
pcNorOut->Normalize();
++pcVertOut;++pcNorOut;++src;
}
}
// generate texture coordinates if necessary
if (pcHeader->numskins)
{
this->GenerateTextureCoords(width,height);
}
// now build a list of faces
const unsigned int iNumSquares = (width-1) * (height-1);
pcMesh->mNumFaces = iNumSquares << 1;
pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
pcMesh->mNumVertices = pcMesh->mNumFaces*3;
aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices];
aiVector3D* pcNormals = new aiVector3D[pcMesh->mNumVertices];
aiFace* pcFaceOut(pcMesh->mFaces);
pcVertOut = pcVertices;
pcNorOut = pcNormals;
aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL;
aiVector3D* pcUVOut(pcUVs);
unsigned int iCurrent = 0;
for (unsigned int y = 0; y < height-1;++y)
{
for (unsigned int x = 0; x < width-1;++x)
{
// first triangle of the square
pcFaceOut->mNumIndices = 3;
pcFaceOut->mIndices = new unsigned int[3];
*pcVertOut++ = pcMesh->mVertices[y*width+x];
*pcVertOut++ = pcMesh->mVertices[y*width+x+1];
*pcVertOut++ = pcMesh->mVertices[(y+1)*width+x];
*pcNorOut++ = pcMesh->mNormals[y*width+x];
*pcNorOut++ = pcMesh->mNormals[y*width+x+1];
*pcNorOut++ = pcMesh->mNormals[(y+1)*width+x];
if (pcMesh->mTextureCoords[0])
{
*pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x];
*pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
}
pcFaceOut->mIndices[2] = iCurrent++;
pcFaceOut->mIndices[1] = iCurrent++;
pcFaceOut->mIndices[0] = iCurrent++;
++pcFaceOut;
// second triangle of the square
pcFaceOut->mNumIndices = 3;
pcFaceOut->mIndices = new unsigned int[3];
*pcVertOut++ = pcMesh->mVertices[(y+1)*width+x];
*pcVertOut++ = pcMesh->mVertices[y*width+x+1];
*pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1];
*pcNorOut++ = pcMesh->mNormals[(y+1)*width+x];
*pcNorOut++ = pcMesh->mNormals[y*width+x+1];
*pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1];
if (pcMesh->mTextureCoords[0])
{
*pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
*pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1];
}
pcFaceOut->mIndices[2] = iCurrent++;
pcFaceOut->mIndices[1] = iCurrent++;
pcFaceOut->mIndices[0] = iCurrent++;
++pcFaceOut;
}
}
delete[] pcMesh->mVertices;
pcMesh->mVertices = pcVertices;
delete[] pcMesh->mNormals;
pcMesh->mNormals = pcNormals;
if (pcMesh->mTextureCoords[0])
{
delete[] pcMesh->mTextureCoords[0];
pcMesh->mTextureCoords[0] = pcUVs;
}
// there is no nodegraph in HMP files. Simply assign the one mesh
// (no, not the one ring) to the root node
this->pScene->mRootNode = new aiNode();
this->pScene->mRootNode->mName.Set("terrain_root");
this->pScene->mRootNode->mNumMeshes = 1;
this->pScene->mRootNode->mMeshes = new unsigned int[1];
this->pScene->mRootNode->mMeshes[0] = 0;
return;
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
const unsigned char** szCursorOut)
{
ai_assert(0 != iNumSkins && NULL != szCursor);
// read the type of the skin ...
// sometimes we need to skip 12 bytes here, I don't know why ...
uint32_t iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
if (0 == iType)
{
DefaultLogger::get()->warn("Skin type is 0. Skipping 12 bytes to "
"the next valid value, which seems to be the real skin type. "
"However, it is not known whether or not this is correct.");
szCursor += sizeof(uint32_t) * 2;
iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
if (0 == iType)
{
throw new ImportErrorException("Unable to read HMP7 skin chunk");
}
}
// read width and height
uint32_t iWidth = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
uint32_t iHeight = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
// allocate an output material
MaterialHelper* pcMat = new MaterialHelper();
// read the skin, this works exactly as for MDL7
this->ParseSkinLump_3DGS_MDL7(szCursor,&szCursor,
pcMat,iType,iWidth,iHeight);
// now we need to skip any other skins ...
for (unsigned int i = 1; i< iNumSkins;++i)
{
iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
iWidth = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
iHeight = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
this->SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,
iType,iWidth,iHeight);
this->SizeCheck(szCursor);
}
// setup the material ...
this->pScene->mNumMaterials = 1;
this->pScene->mMaterials = new aiMaterial*[1];
this->pScene->mMaterials[0] = pcMat;
*szCursorOut = szCursor;
return;
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::GenerateTextureCoords(
const unsigned int width, const unsigned int height)
{
ai_assert(NULL != this->pScene->mMeshes && NULL != this->pScene->mMeshes[0] &&
NULL != this->pScene->mMeshes[0]->mTextureCoords[0]);
aiVector3D* uv = this->pScene->mMeshes[0]->mTextureCoords[0];
const float fX = (1.0f / height) + (1.0f / height) / (height-1);
const float fY = (1.0f / width) + (1.0f / width) / (width-1);
for (unsigned int y = 0; y < height;++y)
{
for (unsigned int x = 0; x < width;++x)
{
uv->x = fX*x;
uv->y = 1.0f-fY*y;
++uv;
}
}
return;
}
+208
View File
@@ -0,0 +1,208 @@
/*
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 Definition of HMP importer class
//!
#ifndef AI_HMPLOADER_H_INCLUDED
#define AI_HMPLOADER_H_INCLUDED
#include "BaseImporter.h"
#include "../include/aiTypes.h"
#include "../include/aiTexture.h"
#include "../include/aiMaterial.h"
struct aiNode;
#include "MDLLoader.h"
namespace Assimp
{
class MaterialHelper;
#define AI_HMP_MAGIC_NUMBER_BE_4 'HMP4'
#define AI_HMP_MAGIC_NUMBER_LE_4 '4PMH'
#define AI_HMP_MAGIC_NUMBER_BE_5 'HMP5'
#define AI_HMP_MAGIC_NUMBER_LE_5 '5PMH'
#define AI_HMP_MAGIC_NUMBER_BE_7 'HMP7'
#define AI_HMP_MAGIC_NUMBER_LE_7 '7PMH'
namespace HMP
{
// ---------------------------------------------------------------------------
/** Data structure for the header of a HMP5 file.
* This is also used by HMP4 and HMP7, but with modifications
*/
struct Header_HMP5
{
int8_t ident[4]; // "HMP5"
int32_t version;
// ignored
float scale[3];
float scale_origin[3];
float boundingradius;
//! Size of one triangle in x direction
float ftrisize_x;
//! Size of one triangle in y direction
float ftrisize_y;
//! Number of vertices in x direction
float fnumverts_x;
//! Number of skins in the file
int32_t numskins;
// can ignore this?
int32_t skinwidth;
int32_t skinheight;
//!Number of vertices in the file
int32_t numverts;
// ignored and zero
int32_t numtris;
//! only one supported ...
int32_t numframes;
//! Always 0 ...
int32_t num_stverts;
int32_t flags;
float size;
};
// ---------------------------------------------------------------------------
/** Data structure for a terrain vertex in a HMP7 file
*/
struct Vertex_HMP7
{
uint16_t z;
int8_t normal_x,normal_y;
};
}; //! namespace HMP
// ---------------------------------------------------------------------------
/** Used to load 3D GameStudio HMP files (terrains)
*/
class HMPImporter : public MDLImporter
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
HMPImporter();
/** Destructor, private as well */
~HMPImporter();
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("*.hmp");
}
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
protected:
// -------------------------------------------------------------------
/** Import a HMP4 file
*/
void InternReadFile_HMP4( );
// -------------------------------------------------------------------
/** Import a HMP5 file
*/
void InternReadFile_HMP5( );
// -------------------------------------------------------------------
/** Import a HMP7 file
*/
void InternReadFile_HMP7( );
// -------------------------------------------------------------------
/** Generate planar texture coordinates for a terrain
* \param width Width of the terrain, in vertices
* \param height Height of the terrain, in vertices
*/
void GenerateTextureCoords(const unsigned int width,
const unsigned int height);
// -------------------------------------------------------------------
/** Read the first skin from the file and skip all others ...
* \param iNumSkins Number of skins in the file
* \param szCursor Position of the first skin (offset 84)
*/
void ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
const unsigned char** szCursorOut);
private:
};
}; // end of namespace Assimp
#endif // AI_HMPIMPORTER_H_INC
+87 -13
View File
@@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DefaultIOStream.h"
#include "DefaultIOSystem.h"
// Importers
#if (!defined AI_BUILD_NO_X_IMPORTER)
# include "XFileImporter.h"
#endif
@@ -81,18 +82,47 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if (!defined AI_BUILD_NO_OBJ_IMPORTER)
# include "ObjFileImporter.h"
#endif
#if (!defined AI_BUILD_NO_HMP_IMPORTER)
# include "HMPLoader.h"
#endif
#if (!defined AI_BUILD_NO_SMD_IMPORTER)
# include "SMDLoader.h"
#endif
#include "CalcTangentsProcess.h"
#include "JoinVerticesProcess.h"
#include "ConvertToLHProcess.h"
#include "TriangulateProcess.h"
#include "GenFaceNormalsProcess.h"
#include "GenVertexNormalsProcess.h"
#include "KillNormalsProcess.h"
#include "SplitLargeMeshes.h"
#include "PretransformVertices.h"
#include "LimitBoneWeightsProcess.h"
#include "ValidateDataStructure.h"
// PostProcess-Steps
#if (!defined AI_BUILD_NO_CALCTANGENTS_PROCESS)
# include "CalcTangentsProcess.h"
#endif
#if (!defined AI_BUILD_NO_JOINVERTICES_PROCESS)
# include "JoinVerticesProcess.h"
#endif
#if (!defined AI_BUILD_NO_CONVERTTOLH_PROCESS)
# include "ConvertToLHProcess.h"
#endif
#if (!defined AI_BUILD_NO_TRIANGULATE_PROCESS)
# include "TriangulateProcess.h"
#endif
#if (!defined AI_BUILD_NO_GENFACENORMALS_PROCESS)
# include "GenFaceNormalsProcess.h"
#endif
#if (!defined AI_BUILD_NO_GENVERTEXNORMALS_PROCESS)
# include "GenVertexNormalsProcess.h"
#endif
#if (!defined AI_BUILD_NO_KILLNORMALS_PROCESS)
# include "KillNormalsProcess.h"
#endif
#if (!defined AI_BUILD_NO_SPLITLARGEMESHES_PROCESS)
# include "SplitLargeMeshes.h"
#endif
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
# include "PretransformVertices.h"
#endif
#if (!defined AI_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
# include "LimitBoneWeightsProcess.h"
#endif
#if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS)
# include "ValidateDataStructure.h"
#endif
using namespace Assimp;
@@ -105,6 +135,7 @@ Importer::Importer() :
{
// allocate a default IO handler
mIOHandler = new DefaultIOSystem;
mIsDefaultHandler = true;
// add an instance of each worker class here
#if (!defined AI_BUILD_NO_X_IMPORTER)
@@ -134,20 +165,51 @@ Importer::Importer() :
#if (!defined AI_BUILD_NO_ASE_IMPORTER)
mImporter.push_back( new ASEImporter());
#endif
#if (!defined AI_BUILD_NO_HMP_IMPORTER)
mImporter.push_back( new HMPImporter());
#endif
#if (!defined AI_BUILD_NO_SMD_IMPORTER)
mImporter.push_back( new SMDImporter());
#endif
// add an instance of each post processing step here in the order of sequence it is executed
// add an instance of each post processing step here in the order
// of sequence it is executed
#if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS)
mPostProcessingSteps.push_back( new ValidateDSProcess());
#endif
#if (!defined AI_BUILD_NO_TRIANGULATE_PROCESS)
mPostProcessingSteps.push_back( new TriangulateProcess());
#endif
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
mPostProcessingSteps.push_back( new PretransformVertices());
#endif
#if (!defined AI_BUILD_NO_SPLITLARGEMESHES_PROCESS)
mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Triangle());
#endif
#if (!defined AI_BUILD_NO_KILLNORMALS_PROCESS)
mPostProcessingSteps.push_back( new KillNormalsProcess());
#endif
#if (!defined AI_BUILD_NO_GENFACENORMALS_PROCESS)
mPostProcessingSteps.push_back( new GenFaceNormalsProcess());
#endif
#if (!defined AI_BUILD_NO_GENVERTEXNORMALS_PROCESS)
mPostProcessingSteps.push_back( new GenVertexNormalsProcess());
#endif
#if (!defined AI_BUILD_NO_CALCTANGENTS_PROCESS)
mPostProcessingSteps.push_back( new CalcTangentsProcess());
#endif
#if (!defined AI_BUILD_NO_JOINVERTICES_PROCESS)
mPostProcessingSteps.push_back( new JoinVerticesProcess());
#endif
#if (!defined AI_BUILD_NO_SPLITLARGEMESHES_PROCESS)
mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Vertex());
#endif
#if (!defined AI_BUILD_NO_CONVERTTOLH_PROCESS)
mPostProcessingSteps.push_back( new ConvertToLHProcess());
#endif
#if (!defined AI_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
mPostProcessingSteps.push_back( new LimitBoneWeightsProcess());
#endif
}
// ------------------------------------------------------------------------------------------------
@@ -170,19 +232,31 @@ Importer::~Importer()
// Supplies a custom IO handler to the importer to open and access files.
void Importer::SetIOHandler( IOSystem* pIOHandler)
{
if (NULL == pIOHandler)
if (!pIOHandler)
{
delete mIOHandler;
mIOHandler = new DefaultIOSystem();
mIsDefaultHandler = true;
}
else if (mIOHandler != pIOHandler)
{
delete mIOHandler;
mIOHandler = pIOHandler;
mIsDefaultHandler = false;
}
return;
}
// ------------------------------------------------------------------------------------------------
IOSystem* Importer::GetIOHandler()
{
return mIOHandler;
}
// ------------------------------------------------------------------------------------------------
bool Importer::IsDefaultIOHandler()
{
return mIsDefaultHandler;
}
// ------------------------------------------------------------------------------------------------
// Validate post process step flags
bool ValidateFlags(unsigned int pFlags)
{
+62 -2
View File
@@ -1,20 +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.
----------------------------------------------------------------------
*/
/** Implementation of the LimitBoneWeightsProcess post processing step */
#include <vector>
#include <assert.h>
#include "LimitBoneWeightsProcess.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/DefaultLogger.h"
using namespace Assimp;
/*static*/ unsigned int LimitBoneWeightsProcess::mMaxWeights = AI_LMW_MAX_WEIGHTS;
extern "C" {
// ------------------------------------------------------------------------------------------------
aiReturn aiSetBoneWeightLimit(unsigned int pLimit)
{
if (0 == pLimit)
{
LimitBoneWeightsProcess::mMaxWeights = 0xFFFFFFFF;
return AI_FAILURE;
}
LimitBoneWeightsProcess::mMaxWeights = pLimit;
DefaultLogger::get()->debug("aiSetBoneWeightLimit() - bone weight limit was changed");
return AI_SUCCESS;
}
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
LimitBoneWeightsProcess::LimitBoneWeightsProcess()
{
// TODO: (thom) make this configurable from somewhere?
mMaxWeights = 4;
}
// ------------------------------------------------------------------------------------------------
+55 -1
View File
@@ -1,3 +1,43 @@
/*
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.
----------------------------------------------------------------------
*/
/** Defines a post processing step to limit the number of bones affecting a single vertex. */
#ifndef AI_LIMITBONEWEIGHTSPROCESS_H_INC
#define AI_LIMITBONEWEIGHTSPROCESS_H_INC
@@ -9,6 +49,18 @@ struct aiMesh;
namespace Assimp
{
// NOTE: If you change these limits, don't forget to change the
// corresponding values in all Assimp ports
// **********************************************************
// Java: PostProcessStep.java,
// PostProcessStep.DEFAULT_BONE_WEIGHT_LIMIT
// **********************************************************
#if (!defined AI_LMW_MAX_WEIGHTS)
# define AI_LMW_MAX_WEIGHTS 0x4
#endif // !! AI_LMW_MAX_WEIGHTS
// ---------------------------------------------------------------------------
/** This post processing step limits the number of bones affecting a vertex
* to a certain maximum value. If a vertex is affected by more than that number
@@ -58,12 +110,14 @@ protected:
float mWeight; ///< Weight of that bone on this vertex
Weight() { }
Weight( unsigned int pBone, float pWeight) { mBone = pBone; mWeight = pWeight; }
/** Comparision operator to sort bone weights by descending weight */
bool operator < (const Weight& pWeight) const { return mWeight > pWeight.mWeight; }
};
public:
/** Maximum number of bones influencing any single vertex. */
unsigned int mMaxWeights;
static unsigned int mMaxWeights;
};
} // end of namespace Assimp
+26 -24
View File
@@ -80,34 +80,33 @@ namespace MD2
// ---------------------------------------------------------------------------
/** \brief Data structure for the MD2 main header
*/
// ---------------------------------------------------------------------------
struct Header
{
int32_t magic;
int32_t version;
int32_t skinWidth;
int32_t skinHeight;
int32_t frameSize;
int32_t numSkins;
int32_t numVertices;
int32_t numTexCoords;
int32_t numTriangles;
int32_t numGlCommands;
int32_t numFrames;
int32_t offsetSkins;
int32_t offsetTexCoords;
int32_t offsetTriangles;
int32_t offsetFrames;
int32_t offsetGlCommands;
int32_t offsetEnd;
uint32_t magic;
uint32_t version;
uint32_t skinWidth;
uint32_t skinHeight;
uint32_t frameSize;
uint32_t numSkins;
uint32_t numVertices;
uint32_t numTexCoords;
uint32_t numTriangles;
uint32_t numGlCommands;
uint32_t numFrames;
uint32_t offsetSkins;
uint32_t offsetTexCoords;
uint32_t offsetTriangles;
uint32_t offsetFrames;
uint32_t offsetGlCommands;
uint32_t offsetEnd;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 OpenGl draw command
*/
// ---------------------------------------------------------------------------
struct GLCommand
{
float s, t;
@@ -117,7 +116,6 @@ struct GLCommand
// ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 triangle
*/
// ---------------------------------------------------------------------------
struct Triangle
{
uint16_t vertexIndices[3];
@@ -127,7 +125,6 @@ struct Triangle
// ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 vertex
*/
// ---------------------------------------------------------------------------
struct Vertex
{
uint8_t vertex[3];
@@ -137,7 +134,6 @@ struct Vertex
// ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 frame
*/
// ---------------------------------------------------------------------------
struct Frame
{
float scale[3];
@@ -149,7 +145,6 @@ struct Frame
// ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 texture coordinate
*/
// ---------------------------------------------------------------------------
struct TexCoord
{
int16_t s;
@@ -159,7 +154,6 @@ struct TexCoord
// ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 skin
*/
// ---------------------------------------------------------------------------
struct Skin
{
char name[AI_MD2_MAXQPATH]; /* texture file name */
@@ -171,6 +165,14 @@ struct Skin
#endif
#undef PACK_STRUCT
// ---------------------------------------------------------------------------
//! Lookup a normal vector from Quake's normal lookup table
//! \param index Input index (0-161)
//! \param vOut Receives the output normal
void LookupNormalIndex(uint8_t index,aiVector3D& vOut);
};
};
+150 -91
View File
@@ -42,40 +42,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the MD2 importer class */
#include "MD2Loader.h"
#include "MaterialSystem.h"
#include "MD2NormalTable.h"
#include "MD2NormalTable.h" // shouldn't be included by other units
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#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::MD2;
// helper macro to determine the size of an array
#if (!defined ARRAYSIZE)
# define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0])))
#endif
// ------------------------------------------------------------------------------------------------
inline bool is_qnan(float p_fIn)
// Helper function to lookup a normal in Quake 2's precalculated table
void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut)
{
// NOTE: Comparison against qnan is generally problematic
// because qnan == qnan is false AFAIK
union FTOINT
// make sure the normal index has a valid value
if (iNormalIndex >= ARRAYSIZE(g_avNormals))
{
float fFloat;
int32_t iInt;
} one, two;
one.fFloat = std::numeric_limits<float>::quiet_NaN();
two.fFloat = p_fIn;
DefaultLogger::get()->warn("Index overflow in MDL7 normal vector list (the "
" LUT has only 162 entries). ");
return (one.iInt == two.iInt);
}
// ------------------------------------------------------------------------------------------------
inline bool is_not_qnan(float p_fIn)
{
return !is_qnan(p_fIn);
iNormalIndex = ARRAYSIZE(g_avNormals) - 1;
}
vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex]));
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MD2Importer::MD2Importer()
@@ -99,12 +101,43 @@ bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
return false;
std::string extension = pFile.substr( pos);
// not brilliant but working ;-)
if( extension == ".md2" || extension == ".MD2" ||
extension == ".mD2" || extension == ".Md2")
return true;
if (extension.length() < 4)return false;
if (extension[0] != '.')return false;
if (extension[1] != 'm' && extension[1] != 'M')return false;
if (extension[2] != 'd' && extension[2] != 'D')return false;
if (extension[3] != '2')return false;
return false;
return true;
}
// ------------------------------------------------------------------------------------------------
// Validate the file header
void MD2Importer::ValidateHeader( )
{
/* to be validated:
int32_t offsetSkins;
int32_t offsetTexCoords;
int32_t offsetTriangles;
int32_t offsetFrames;
//int32_t offsetGlCommands;
int32_t offsetEnd;
*/
if (this->m_pcHeader->offsetSkins + this->m_pcHeader->numSkins * sizeof (MD2::Skin) >= this->fileSize ||
this->m_pcHeader->offsetTexCoords + this->m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= this->fileSize ||
this->m_pcHeader->offsetTriangles + this->m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= this->fileSize ||
this->m_pcHeader->offsetFrames + this->m_pcHeader->numFrames * sizeof (MD2::Frame) >= this->fileSize ||
this->m_pcHeader->offsetEnd > this->fileSize)
{
throw new ImportErrorException("Invalid MD2 header: some offsets are outside the file");
delete[] this->mBuffer;
}
if (this->m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports");
if ( this->m_pcHeader->numFrames > AI_MD2_MAX_FRAMES)
DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports");
if (this->m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports");
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
@@ -121,10 +154,10 @@ void MD2Importer::InternReadFile(
// check whether the md3 file is large enough to contain
// at least the file header
size_t fileSize = file->FileSize();
fileSize = (unsigned int)file->FileSize();
if( fileSize < sizeof(MD2::Header))
{
throw new ImportErrorException( ".md2 File is too small.");
throw new ImportErrorException( "md2 File is too small.");
}
// allocate storage and copy the contents of the file to a memory buffer
@@ -137,22 +170,26 @@ void MD2Importer::InternReadFile(
if (this->m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
this->m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md2 file: Magic bytes not found");
}
// check file format version
if (this->m_pcHeader->version != 8)
{
throw new ImportErrorException( "Unsupported md3 file version");
DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ...");
}
this->ValidateHeader();
// check some values whether they are valid
if (0 == this->m_pcHeader->numFrames)
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md2 file: NUM_FRAMES is 0");
}
if (this->m_pcHeader->offsetEnd > (int32_t)fileSize)
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md2 file: File is too small");
}
@@ -166,39 +203,35 @@ void MD2Importer::InternReadFile(
pScene->mMaterials[0] = new MaterialHelper();
pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh*[1];
pScene->mMeshes[0] = new aiMesh();
aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
// navigate to the begin of the frame data
const MD2::Frame* pcFrame = (const MD2::Frame*) ((unsigned char*)this->m_pcHeader +
this->m_pcHeader->offsetFrames);
const MD2::Frame* pcFrame = (const MD2::Frame*) (
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetFrames);
// navigate to the begin of the triangle data
MD2::Triangle* pcTriangles = (MD2::Triangle*) ((unsigned char*)this->m_pcHeader +
this->m_pcHeader->offsetTriangles);
MD2::Triangle* pcTriangles = (MD2::Triangle*) (
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetTriangles);
// navigate to the begin of the tex coords data
const MD2::TexCoord* pcTexCoords = (const MD2::TexCoord*) ((unsigned char*)this->m_pcHeader +
this->m_pcHeader->offsetTexCoords);
const MD2::TexCoord* pcTexCoords = (const MD2::TexCoord*) (
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetTexCoords);
// navigate to the begin of the vertex data
const MD2::Vertex* pcVerts = (const MD2::Vertex*) (pcFrame->vertices);
pScene->mMeshes[0]->mNumFaces = this->m_pcHeader->numTriangles;
pScene->mMeshes[0]->mFaces = new aiFace[this->m_pcHeader->numTriangles];
pcMesh->mNumFaces = this->m_pcHeader->numTriangles;
pcMesh->mFaces = new aiFace[this->m_pcHeader->numTriangles];
// temporary vectors for position/texture coordinates/normals
std::vector<aiVector3D> vPositions;
std::vector<aiVector3D> vTexCoords;
std::vector<aiVector3D> vNormals;
vPositions.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
vTexCoords.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D(
std::numeric_limits<float>::quiet_NaN(),
std::numeric_limits<float>::quiet_NaN(),0.0f));
vNormals.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
// allocate output storage
pcMesh->mNumVertices = (unsigned int)pcMesh->mNumFaces*3;
pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
// not sure whether there are MD2 files without texture coordinates
if (0 != this->m_pcHeader->numTexCoords && 0 != this->m_pcHeader->numSkins)
// NOTE: texture coordinates can be there without a texture,
// but a texture can't be there without a valid UV channel
if (this->m_pcHeader->numTexCoords && this->m_pcHeader->numSkins)
{
// navigate to the first texture associated with the mesh
const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)this->m_pcHeader +
@@ -216,12 +249,20 @@ void MD2Importer::InternReadFile(
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
aiString szString;
const size_t iLen = strlen(pcSkins->name);
memcpy(szString.data,pcSkins->name,iLen+1);
szString.length = iLen-1;
if (pcSkins->name[0])
{
aiString szString;
const size_t iLen = ::strlen(pcSkins->name);
::memcpy(szString.data,pcSkins->name,iLen);
szString.data[iLen] = '\0';
szString.length = iLen;
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else
{
DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped.");
}
}
else
{
@@ -237,13 +278,42 @@ void MD2Importer::InternReadFile(
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
}
// now read all triangles of the first frame, apply scaling and translation
unsigned int iCurrent = 0;
if (0 != this->m_pcHeader->numTexCoords)
if (this->m_pcHeader->numTexCoords)
{
// allocate storage for texture coordinates, too
pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mNumUVComponents[0] = 2;
// check whether the skin width or height are zero (this would
// cause a division through zero)
float fDivisorU;
if (!this->m_pcHeader->skinWidth)
{
DefaultLogger::get()->error("Skin width is zero but there are "
"valid absolute texture coordinates. Unable to compute "
"relative texture coordinates ranging from 0 to 1");
fDivisorU = 1.0f;
}
else fDivisorU = (float)this->m_pcHeader->skinWidth;
float fDivisorV;
if (!this->m_pcHeader->skinHeight)
{
DefaultLogger::get()->error("Skin height is zero but there are "
"valid absolute texture coordinates. Unable to compute "
"relative texture coordinates ranging from 0 to 1");
fDivisorV = 1.0f;
}
else fDivisorV = (float)this->m_pcHeader->skinHeight;
for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numTriangles;++i)
{
@@ -259,13 +329,16 @@ void MD2Importer::InternReadFile(
{
// validate vertex indices
if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices)
{
DefaultLogger::get()->error("Vertex index is outside the allowed range");
pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1;
}
// copy face indices
unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
// read x,y, and z component of the vertex
aiVector3D& vec = vPositions[iCurrent];
aiVector3D& vec = pcMesh->mVertices[iCurrent];
vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
vec.x += pcFrame->translate[0];
@@ -278,23 +351,28 @@ void MD2Importer::InternReadFile(
vec.y += pcFrame->translate[2];
// read the normal vector from the precalculated normal table
vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
int(pcVerts[iIndex].lightNormalIndex),
int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
std::swap ( vNormal.y,vNormal.z );
// validate texture coordinates
if (pcTriangles[iIndex].textureIndices[c] >= this->m_pcHeader->numTexCoords)
{
DefaultLogger::get()->error("UV index is outside the allowed range");
pcTriangles[iIndex].textureIndices[c] = this->m_pcHeader->numTexCoords-1;
}
aiVector3D* pcOut = &vTexCoords[iCurrent];
aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent];
float u,v;
u = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth;
v = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight;
pcOut->x = u;
pcOut->y = v;
// the texture coordinates are absolute values but we
// need relative values between 0 and 1
u = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / fDivisorU;
v = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / fDivisorV;
pcOut.x = u;
pcOut.y = 1.0f - v; // FIXME: Is this correct for MD2?
}
// FIX: flip the face order for use with OpenGL
pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2;
pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1;
pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0;
@@ -316,13 +394,16 @@ void MD2Importer::InternReadFile(
{
// validate vertex indices
if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices)
{
DefaultLogger::get()->error("Vertex index is outside the allowed range");
pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1;
}
// copy face indices
unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
// read x,y, and z component of the vertex
aiVector3D& vec = vPositions[iCurrent];
aiVector3D& vec = pcMesh->mVertices[iCurrent];
vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
vec.x += pcFrame->translate[0];
@@ -335,39 +416,17 @@ void MD2Importer::InternReadFile(
vec.y += pcFrame->translate[2];
// read the normal vector from the precalculated normal table
vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
int(pcVerts[iIndex].lightNormalIndex),
int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
aiVector3D* pcOut = &vTexCoords[iCurrent];
pcOut->x = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth;
pcOut->y = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight;
aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
std::swap ( vNormal.y,vNormal.z );
}
// FIX: flip the face order for use with OpenGL
pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2;
pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1;
pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0;
}
}
// allocate output storage
pScene->mMeshes[0]->mNumVertices = (unsigned int)vPositions.size();
pScene->mMeshes[0]->mVertices = new aiVector3D[vPositions.size()];
pScene->mMeshes[0]->mNormals = new aiVector3D[vPositions.size()];
pScene->mMeshes[0]->mTextureCoords[0] = new aiVector3D[vPositions.size()];
// memcpy() the data to the c-syle arrays
memcpy(pScene->mMeshes[0]->mVertices, &vPositions[0],
vPositions.size() * sizeof(aiVector3D));
memcpy(pScene->mMeshes[0]->mNormals, &vNormals[0],
vPositions.size() * sizeof(aiVector3D));
if (0 != this->m_pcHeader->numTexCoords)
{
memcpy(pScene->mMeshes[0]->mTextureCoords[0], &vTexCoords[0],
vPositions.size() * sizeof(aiVector3D));
}
// delete the file buffer and return
delete[] this->mBuffer;
return;
}
+9
View File
@@ -93,6 +93,12 @@ protected:
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
// -------------------------------------------------------------------
/** Validate the header of the file
*/
void ValidateHeader();
protected:
/** Header of the MD2 file */
@@ -100,6 +106,9 @@ protected:
/** Buffer to hold the loaded file */
const unsigned char* mBuffer;
/** Size of the file, in bytes */
unsigned int fileSize;
};
} // end of namespace Assimp
+23 -23
View File
@@ -89,10 +89,10 @@ namespace MD3
struct Header
{
//! magic number
int32_t IDENT;
uint32_t IDENT;
//! file format version
int32_t VERSION;
uint32_t VERSION;
//! original name in .pak archive
unsigned char NAME[ AI_MD3_MAXQPATH ];
@@ -101,28 +101,28 @@ struct Header
int32_t FLAGS;
//! number of frames in the file
int32_t NUM_FRAMES;
uint32_t NUM_FRAMES;
//! number of tags in the file
int32_t NUM_TAGS;
uint32_t NUM_TAGS;
//! number of surfaces in the file
int32_t NUM_SURFACES;
uint32_t NUM_SURFACES;
//! number of skins in the file
int32_t NUM_SKINS;
uint32_t NUM_SKINS;
//! offset of the first frame
int32_t OFS_FRAMES;
uint32_t OFS_FRAMES;
//! offset of the first tag
int32_t OFS_TAGS;
uint32_t OFS_TAGS;
//! offset of the first surface
int32_t OFS_SURFACES;
uint32_t OFS_SURFACES;
//! end of file
int32_t OFS_EOF;
uint32_t OFS_EOF;
} PACK_STRUCT;
@@ -162,29 +162,29 @@ struct Surface
int32_t FLAGS;
//! number of frames in the surface
int32_t NUM_FRAMES;
uint32_t NUM_FRAMES;
//! number of shaders in the surface
int32_t NUM_SHADER;
uint32_t NUM_SHADER;
//! number of vertices in the surface
int32_t NUM_VERTICES;
uint32_t NUM_VERTICES;
//! number of triangles in the surface
int32_t NUM_TRIANGLES;
uint32_t NUM_TRIANGLES;
//! offset to the triangle data
int32_t OFS_TRIANGLES;
uint32_t OFS_TRIANGLES;
//! offset to the shader data
int32_t OFS_SHADERS;
uint32_t OFS_SHADERS;
//! offset to the texture coordinate data
int32_t OFS_ST;
uint32_t OFS_ST;
//! offset to the vertex/normal data
int32_t OFS_XYZNORMAL;
uint32_t OFS_XYZNORMAL;
//! offset to the end of the Surface object
int32_t OFS_END;
@@ -200,7 +200,7 @@ struct Shader
unsigned char NAME[ AI_MD3_MAXQPATH ];
//! index of the shader
int32_t SHADER_INDEX;
uint32_t SHADER_INDEX;
} PACK_STRUCT;
@@ -211,7 +211,7 @@ struct Shader
struct Triangle
{
//! triangle indices
int32_t INDEXES[3];
uint32_t INDEXES[3];
} PACK_STRUCT;
@@ -236,7 +236,7 @@ struct Vertex
int16_t X,Y,Z;
//! encoded normal vector
int16_t NORMAL;
uint16_t NORMAL;
} PACK_STRUCT;
// reset packing to the original value
@@ -254,9 +254,9 @@ struct Vertex
* \note This has been taken from q3 source (misc_model.c)
*/
// ---------------------------------------------------------------------------
inline void LatLngNormalToVec3(int16_t p_iNormal, float* p_afOut)
inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut)
{
float lat = (float)(( p_iNormal >> 8 ) & 0xff);
float lat = (float)(( p_iNormal >> 8u ) & 0xff);
float lng = (float)(( p_iNormal & 0xff ));
lat *= 3.141926f/128.0f;
lng *= 3.141926f/128.0f;
+90 -39
View File
@@ -49,6 +49,7 @@ 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>
@@ -78,12 +79,48 @@ bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
return false;
std::string extension = pFile.substr( pos);
// not brilliant but working ;-)
if( extension == ".md3" || extension == ".MD3" ||
extension == ".mD3" || extension == ".Md3")
return true;
if (extension.length() < 4)return false;
if (extension[0] != '.')return false;
if (extension[1] != 'm' && extension[1] != 'M')return false;
if (extension[2] != 'd' && extension[2] != 'D')return false;
if (extension[3] != '3')return false;
return false;
return true;
}
// ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateHeaderOffsets()
{
if (this->m_pcHeader->OFS_FRAMES >= this->fileSize ||
this->m_pcHeader->OFS_SURFACES >= this->fileSize ||
this->m_pcHeader->OFS_EOF > this->fileSize)
{
delete[] this->mBuffer;
throw new ImportErrorException("Invalid MD3 header: some offsets are outside the file");
}
}
// ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf)
{
// calculate the relative offset of the surface
int32_t ofs = int32_t((const unsigned char*)pcSurf-this->mBuffer);
if (pcSurf->OFS_TRIANGLES + ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle) > this->fileSize ||
pcSurf->OFS_SHADERS + ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader) > this->fileSize ||
pcSurf->OFS_ST + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord) > this->fileSize ||
pcSurf->OFS_XYZNORMAL + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex) > this->fileSize)
{
delete[] this->mBuffer;
throw new ImportErrorException("Invalid MD3 surface header: some offsets are outside the file");
}
if (pcSurf->NUM_TRIANGLES > AI_MD3_MAX_TRIANGLES)
DefaultLogger::get()->warn("The model contains more triangles than Quake 3 supports");
if (pcSurf->NUM_SHADER > AI_MD3_MAX_SHADERS)
DefaultLogger::get()->warn("The model contains more shaders than Quake 3 supports");
if (pcSurf->NUM_VERTICES > AI_MD3_MAX_VERTS)
DefaultLogger::get()->warn("The model contains more vertices than Quake 3 supports");
if (pcSurf->NUM_FRAMES > AI_MD3_MAX_FRAMES)
DefaultLogger::get()->warn("The model contains more frames than Quake 3 supports");
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
@@ -100,7 +137,7 @@ void MD3Importer::InternReadFile(
// check whether the md3 file is large enough to contain
// at least the file header
size_t fileSize = file->FileSize();
fileSize = (unsigned int)file->FileSize();
if( fileSize < sizeof(MD3::Header))
{
throw new ImportErrorException( ".md3 File is too small.");
@@ -116,28 +153,28 @@ void MD3Importer::InternReadFile(
if (this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md3 file: Magic bytes not found");
}
// check file format version
if (this->m_pcHeader->VERSION > 15)
{
throw new ImportErrorException( "Unsupported md3 file version");
DefaultLogger::get()->warn( "Unsupported md3 file version. Continuing happily ...");
}
// check some values whether they are valid
if (0 == this->m_pcHeader->NUM_FRAMES)
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md3 file: NUM_FRAMES is 0");
}
if (0 == this->m_pcHeader->NUM_SURFACES)
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md3 file: NUM_SURFACES is 0");
}
if (this->m_pcHeader->OFS_EOF > (int32_t)fileSize)
{
throw new ImportErrorException( "Invalid md3 file: File is too small");
}
this->ValidateHeaderOffsets();
// now navigate to the list of surfaces
const MD3::Surface* pcSurfaces = (const MD3::Surface*)
@@ -150,11 +187,19 @@ void MD3Importer::InternReadFile(
pScene->mNumMaterials = this->m_pcHeader->NUM_SURFACES;
pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
// if an exception is thrown before the meshes are allocated ->
// otherwise the pointer value would be invalid and delete would crash
::memset(pScene->mMeshes,0,pScene->mNumMeshes*sizeof(aiMesh*));
::memset(pScene->mMaterials,0,pScene->mNumMaterials*sizeof(aiMaterial*));
unsigned int iNum = this->m_pcHeader->NUM_SURFACES;
unsigned int iNumMaterials = 0;
unsigned int iDefaultMatIndex = 0xFFFFFFFF;
while (iNum-- > 0)
{
// validate the surface
this->ValidateSurfaceHeaderOffsets(pcSurfaces);
// navigate to the vertex list of the surface
const MD3::Vertex* pcVertices = (const MD3::Vertex*)
(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
@@ -171,7 +216,6 @@ void MD3Importer::InternReadFile(
const MD3::Shader* pcShaders = (const MD3::Shader*)
(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
// if the submesh is empty ignore it
if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES)
{
@@ -185,14 +229,14 @@ void MD3Importer::InternReadFile(
aiMesh* pcMesh = pScene->mMeshes[iNum];
pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3;
pcMesh->mNumBones = 0;
pcMesh->mColors[0] = pcMesh->mColors[1] = pcMesh->mColors[2] = pcMesh->mColors[3] = NULL;
//pcMesh->mNumBones = 0;
//pcMesh->mColors[0] = pcMesh->mColors[1] = pcMesh->mColors[2] = pcMesh->mColors[3] = NULL;
pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES;
pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES];
pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mTextureCoords[1] = pcMesh->mTextureCoords[2] = pcMesh->mTextureCoords[3] = NULL;
//pcMesh->mTextureCoords[1] = pcMesh->mTextureCoords[2] = pcMesh->mTextureCoords[3] = NULL;
pcMesh->mNumUVComponents[0] = 2;
// fill in all triangles
@@ -221,6 +265,7 @@ void MD3Importer::InternReadFile(
pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[ pcTriangles->INDEXES[c]].V;
}
// FIX: flip the face ordering for use with OpenGL
pcMesh->mFaces[i].mIndices[0] = iTemp+2;
pcMesh->mFaces[i].mIndices[1] = iTemp+1;
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
@@ -233,11 +278,11 @@ void MD3Importer::InternReadFile(
// make a relative path.
// if the MD3's internal path itself and the given path are using
// the same directory remove it
const char* szEndDir1 = strrchr((const char*)this->m_pcHeader->NAME,'\\');
if (!szEndDir1)szEndDir1 = strrchr((const char*)this->m_pcHeader->NAME,'/');
const char* szEndDir1 = ::strrchr((const char*)this->m_pcHeader->NAME,'\\');
if (!szEndDir1)szEndDir1 = ::strrchr((const char*)this->m_pcHeader->NAME,'/');
const char* szEndDir2 = strrchr((const char*)pcShaders->NAME,'\\');
if (!szEndDir2)szEndDir2 = strrchr((const char*)pcShaders->NAME,'/');
const char* szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'\\');
if (!szEndDir2)szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'/');
if (szEndDir1 && szEndDir2)
{
@@ -276,7 +321,7 @@ void MD3Importer::InternReadFile(
aiString szOut;
if(AI_SUCCESS == aiGetMaterialString ( (aiMaterial*)pScene->mMaterials[p],
AI_MATKEY_TEXBLEND_DIFFUSE(0),&szOut))
AI_MATKEY_TEXTURE_DIFFUSE(0),&szOut))
{
if (0 == ASSIMP_stricmp(szOut.data,szEndDir2))
{
@@ -294,25 +339,35 @@ void MD3Importer::InternReadFile(
if (szEndDir2)
{
aiString szString;
const size_t iLen = strlen(szEndDir2);
memcpy(szString.data,szEndDir2,iLen+1);
szString.length = iLen-1;
if (szEndDir2[0])
{
aiString szString;
const size_t iLen = ::strlen(szEndDir2);
::memcpy(szString.data,szEndDir2,iLen);
szString.data[iLen] = '\0';
szString.length = iLen;
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else
{
DefaultLogger::get()->warn("Texture file name has zero length. "
"It will be skipped.");
}
}
int iMode = (int)aiShadingMode_Gouraud;
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
// add a small ambient color value - Quake 3 seems to have one
aiColor3D clr;
clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
pcMesh->mMaterialIndex = iNumMaterials++;
}
@@ -343,31 +398,27 @@ void MD3Importer::InternReadFile(
pcMesh->mMaterialIndex = iNumMaterials++;
}
}
// go to the next surface
pcSurfaces = (const MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
}
if (0 == pScene->mNumMeshes)
{
// cleanup before returning
delete pScene;
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md3 file: File contains no valid mesh");
}
pScene->mNumMaterials = iNumMaterials;
// now we need to generate an empty node graph
pScene->mRootNode = new aiNode();
pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{
pScene->mRootNode->mChildren[i] = new aiNode();
pScene->mRootNode->mChildren[i]->mParent = pScene->mRootNode;
pScene->mRootNode->mChildren[i]->mNumMeshes = 1;
pScene->mRootNode->mChildren[i]->mMeshes = new unsigned int[1];
pScene->mRootNode->mChildren[i]->mMeshes[0] = i;
}
pScene->mRootNode->mMeshes[i] = i;
// delete the file buffer and return
delete[] this->mBuffer;
return;
}
+10
View File
@@ -96,6 +96,13 @@ protected:
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
// -------------------------------------------------------------------
/** Validate offsets in the header
*/
void ValidateHeaderOffsets();
void ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurfHeader);
protected:
/** Header of the MD3 file */
@@ -103,6 +110,9 @@ protected:
/** Buffer to hold the loaded file */
const unsigned char* mBuffer;
/** Size of the file, in bytes */
unsigned int fileSize;
};
} // end of namespace Assimp
+1 -1
View File
@@ -109,7 +109,7 @@ void MD4Importer::InternReadFile(
size_t fileSize = file->FileSize();
if( fileSize < sizeof(MD4::Header))
{
throw new ImportErrorException( ".mdd File is too small.");
throw new ImportErrorException( ".md4 File is too small.");
}
return;
}
+351 -88
View File
@@ -43,8 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//! @file Definition of in-memory structures for the MDL file format.
//
// The specification has been taken from various sources on the internet.
// http://tfc.duke.free.fr/coding/mdl-specs-en.html
// - http://tfc.duke.free.fr/coding/mdl-specs-en.html
// - Conitec's MED SDK
// - Many quite long HEX-editor sessions
#ifndef AI_MDLFILEHELPER_H_INC
#define AI_MDLFILEHELPER_H_INC
@@ -67,15 +68,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# error Compiler not supported. Never do this again.
#endif
namespace Assimp
{
namespace MDL
{
namespace Assimp {
namespace MDL {
// magic bytes used in Quake 1 MDL meshes
#define AI_MDL_MAGIC_NUMBER_BE 'IDPO'
#define AI_MDL_MAGIC_NUMBER_LE 'OPDI'
// magic bytes used in GameStudio A<very low> MDL meshes
#define AI_MDL_MAGIC_NUMBER_BE_GS3 'MDL2'
#define AI_MDL_MAGIC_NUMBER_LE_GS3 '2LDM'
// magic bytes used in GameStudio A4 MDL meshes
#define AI_MDL_MAGIC_NUMBER_BE_GS4 'MDL3'
#define AI_MDL_MAGIC_NUMBER_LE_GS4 '3LDM'
@@ -96,7 +99,7 @@ namespace MDL
// common limitations for Quake1 meshes. The loader does not check them,
// but models should not exceed these limits.
// (however it warns) but models should not exceed these limits.
#if (!defined AI_MDL_VERSION)
# define AI_MDL_VERSION 6
#endif
@@ -113,11 +116,25 @@ namespace MDL
# define AI_MDL_MAX_TRIANGLES 2048
#endif
// helper macro that sets a pointer to NULL in debug builds
#if (!defined DEBUG_INVALIDATE_PTR)
# if (defined _DEBUG)
# define DEBUG_INVALIDATE_PTR(x) x = NULL;
# else
# define DEBUG_INVALIDATE_PTR(x)
# endif
#endif
// material key that is set for dummy materials that are
// just referencing another material
#if (!defined AI_MDL7_REFERRER_MATERIAL)
# define AI_MDL7_REFERRER_MATERIAL "&&&referrer&&&"
#endif
// ---------------------------------------------------------------------------
/** \struct Header
* \brief Data structure for the MDL main header
*/
// ---------------------------------------------------------------------------
struct Header
{
//! magic number: "IDPO"
@@ -157,12 +174,13 @@ struct Header
int32_t num_frames;
//! 0 = synchron, 1 = random . Ignored
//! (MDLn formats: number of texture coordinates)
int32_t synctype;
//! State flag
int32_t flags;
//! ???
//! Could be the total size of the file (and not a float)
float size;
} PACK_STRUCT;
@@ -171,7 +189,6 @@ struct Header
/** \struct Header_MDL7
* \brief Data structure for the MDL 7 main header
*/
// ---------------------------------------------------------------------------
struct Header_MDL7
{
//! magic number: "MDL7"
@@ -181,13 +198,13 @@ struct Header_MDL7
int32_t version;
//! Number of bones in file
int32_t bones_num;
uint32_t bones_num;
//! Number of groups in file
int32_t groups_num;
uint32_t groups_num;
//! Size of data in the file
int32_t data_size;
uint32_t data_size;
//! Ignored. Used to store entity specific information
int32_t entlump_size;
@@ -195,45 +212,77 @@ struct Header_MDL7
//! Ignored. Used to store MED related data
int32_t medlump_size;
// -------------------------------------------------------
// Sizes of some file parts
//! Size of the Bone_MDL7 data structure used in the file
uint16_t bone_stc_size;
//! Size of the Skin_MDL 7 data structure used in the file
uint16_t skin_stc_size;
//! Size of a single color (e.g. in a material)
uint16_t colorvalue_stc_size;
//! Size of the Material_MDL7 data structure used in the file
uint16_t material_stc_size;
//! Size of a texture coordinate set in the file
uint16_t skinpoint_stc_size;
//! Size of a triangle in the file
uint16_t triangle_stc_size;
//! Size of a normal vertex in the file
uint16_t mainvertex_stc_size;
//! Size of a per-frame animated vertex in the file
//! (this is not supported)
uint16_t framevertex_stc_size;
//! Size of a bone animation matrix
uint16_t bonetrans_stc_size;
//! Size of the Frame_MDL7 data structure used in the file
uint16_t frame_stc_size;
} PACK_STRUCT;
#define AI_MDL7_MAX_BONENAMESIZE 20
// ---------------------------------------------------------------------------
/** \struct Bone_MDL7
* \brief Bone in a MDL7 file
* \brief Data structure for a bone in a MDL7 file
*/
// ---------------------------------------------------------------------------
struct Bone_MDL7
{
//! Index of the parent bone of *this* bone. 0xffff means:
//! "hey, I have no parent, I'm an orphan"
uint16_t parent_index;
uint8_t _unused_[2]; //
uint8_t _unused_[2];
//! Relative position of the bone (relative to the
//! parent bone)
float x,y,z;
char name[AI_MDL7_MAX_BONENAMESIZE];
};
//! Optional name of the bone
char name[1 /* DUMMY SIZE */];
} PACK_STRUCT;
#define AI_MDL7_MAX_GROUPNAMESIZE 16
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS)
# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
#endif
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS)
# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS (16 + 32)
#endif
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE)
# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE (16)
#endif
#if (!defined AI_MDL7_MAX_GROUPNAMESIZE)
# define AI_MDL7_MAX_GROUPNAMESIZE 16
#endif // ! AI_MDL7_MAX_GROUPNAMESIZE
// ---------------------------------------------------------------------------
/** \struct Group_MDL7
* \brief Group in a MDL7 file
*/
// ---------------------------------------------------------------------------
struct Group_MDL7
{
//! = '1' -> triangle based Mesh
@@ -268,14 +317,14 @@ struct Group_MDL7
#define AI_MDL7_SKINTYPE_MATERIAL_ASCDEF 0x20
#define AI_MDL7_SKINTYPE_RGBFLAG 0x80
#define AI_MDL7_MAX_BONENAMESIZE 20
#if (!defined AI_MDL7_MAX_BONENAMESIZE)
# define AI_MDL7_MAX_BONENAMESIZE 20
#endif // !! AI_MDL7_MAX_BONENAMESIZE
// ---------------------------------------------------------------------------
/** \struct Deformer_MDL7
* \brief Deformer in a MDL7 file
*/
// ---------------------------------------------------------------------------
struct Deformer_MDL7
{
int8_t deformer_version; // 0
@@ -291,7 +340,6 @@ struct Deformer_MDL7
/** \struct DeformerElement_MDL7
* \brief Deformer element in a MDL7 file
*/
// ---------------------------------------------------------------------------
struct DeformerElement_MDL7
{
//! bei deformer_typ==0 (==bones) element_index == bone index
@@ -305,7 +353,6 @@ struct DeformerElement_MDL7
/** \struct DeformerWeight_MDL7
* \brief Deformer weight in a MDL7 file
*/
// ---------------------------------------------------------------------------
struct DeformerWeight_MDL7
{
//! for deformer_typ==0 (==bones) index == vertex index
@@ -313,27 +360,14 @@ struct DeformerWeight_MDL7
float weight;
} PACK_STRUCT;
// maximum length of texture file name
#define AI_MDL7_MAX_TEXNAMESIZE 0x10
// don't know why this was in the original headers ...
// to be removed in future versions
typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
// ---------------------------------------------------------------------------
/** \struct Skin_MDL7
* \brief Skin in a MDL7 file
/** \struct ColorValue_MDL7
* \brief Data structure for a color value in a MDL7 file
*/
// ---------------------------------------------------------------------------
struct Skin_MDL7
{
uint8_t typ;
int8_t _unused_[3];
int32_t width;
int32_t height;
char texture_name[AI_MDL7_MAX_TEXNAMESIZE];
} PACK_STRUCT;
struct ColorValue_MDL7
{
float r,g,b,a;
@@ -341,9 +375,8 @@ struct ColorValue_MDL7
// ---------------------------------------------------------------------------
/** \struct Material_MDL7
* \brief Material in a MDL7 file
* \brief Data structure for a Material in a MDL7 file
*/
// ---------------------------------------------------------------------------
struct Material_MDL7
{
//! Diffuse base color of the material
@@ -365,9 +398,8 @@ struct Material_MDL7
// ---------------------------------------------------------------------------
/** \struct Skin
* \brief Skin data structure #1
* \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4
*/
// ---------------------------------------------------------------------------
struct Skin
{
//! 0 = single (Skin), 1 = group (GroupSkin)
@@ -387,12 +419,40 @@ struct Skin
uint8_t *data;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Skin
* \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7
* \see Skin
*/
struct Skin_MDL5
{
int32_t size, width, height;
uint8_t *data;
} PACK_STRUCT;
// maximum length of texture file name
#if (!defined AI_MDL7_MAX_TEXNAMESIZE)
# define AI_MDL7_MAX_TEXNAMESIZE 0x10
#endif
// ---------------------------------------------------------------------------
/** \struct Skin_MDL7
* \brief Skin data structure #3 - used by MDL7 and HMP7
*/
struct Skin_MDL7
{
uint8_t typ;
int8_t _unused_[3];
int32_t width;
int32_t height;
char texture_name[AI_MDL7_MAX_TEXNAMESIZE];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct RGB565
* \brief Data structure for a RGB565 pixel in a texture
*/
struct RGB565
{
uint16_t r : 5;
@@ -400,6 +460,10 @@ struct RGB565
uint16_t b : 5;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct ARGB4
* \brief Data structure for a ARGB4444 pixel in a texture
*/
struct ARGB4
{
uint16_t a : 4;
@@ -412,7 +476,6 @@ struct ARGB4
/** \struct GroupSkin
* \brief Skin data structure #2 (group of pictures)
*/
// ---------------------------------------------------------------------------
struct GroupSkin
{
//! 0 = single (Skin), 1 = group (GroupSkin)
@@ -430,9 +493,8 @@ struct GroupSkin
// ---------------------------------------------------------------------------
/** \struct TexCoord
* \brief Texture coordinate data structure
* \brief Texture coordinate data structure used by the Quake1 MDL format
*/
// ---------------------------------------------------------------------------
struct TexCoord
{
//! Is the vertex on the noundary between front and back piece?
@@ -445,7 +507,10 @@ struct TexCoord
int32_t t;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct TexCoord_MDL3
* \brief Data structure for an UV coordinate in the 3DGS MDL3 format
*/
struct TexCoord_MDL3
{
//! position, horizontally in range 0..skinwidth-1
@@ -455,6 +520,10 @@ struct TexCoord_MDL3
int16_t v;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct TexCoord_MDL7
* \brief Data structure for an UV coordinate in the 3DGS MDL7 format
*/
struct TexCoord_MDL7
{
//! position, horizontally in range 0..1
@@ -464,32 +533,13 @@ struct TexCoord_MDL7
float v;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Triangle
* \brief Triangle data structure
/** \struct SkinSet_MDL7
* \brief Skin set data structure for the 3DGS MDL7 format
* MDL7 references UV coordinates per face via an index list.
* This allows the use of multiple skins per face with just one
* UV coordinate set.
*/
// ---------------------------------------------------------------------------
struct Triangle
{
//! 0 = backface, 1 = frontface
int32_t facesfront;
//! Vertex indices
int32_t vertex[3];
} PACK_STRUCT;
struct Triangle_MDL3
{
//! Index of 3 3D vertices in range 0..numverts
uint16_t index_xyz[3];
//! Index of 3 skin vertices in range 0..numskinverts
uint16_t index_uv[3];
} PACK_STRUCT;
struct SkinSet_MDL7
{
//! Index into the UV coordinate list
@@ -499,7 +549,36 @@ struct SkinSet_MDL7
int32_t material; // size 4
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Triangle
* \brief Triangle data structure for the Quake1 MDL format
*/
struct Triangle
{
//! 0 = backface, 1 = frontface
int32_t facesfront;
//! Vertex indices
int32_t vertex[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Triangle_MDL3
* \brief Triangle data structure for the 3DGS MDL3 format
*/
struct Triangle_MDL3
{
//! Index of 3 3D vertices in range 0..numverts
uint16_t index_xyz[3];
//! Index of 3 skin vertices in range 0..numskinverts
uint16_t index_uv[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Triangle_MDL7
* \brief Triangle data structure for the 3DGS MDL7 format
*/
struct Triangle_MDL7
{
//! Vertex indices
@@ -509,6 +588,15 @@ struct Triangle_MDL7
SkinSet_MDL7 skinsets[2];
} PACK_STRUCT;
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV)
# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
#endif
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX)
# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX (6+sizeof(SkinSet_MDL7))
#endif
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV)
# define AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV (6+2*sizeof(SkinSet_MDL7))
#endif
// Helper constants for Triangle::facesfront
#if (!defined AI_MDL_BACKFACE)
@@ -522,7 +610,6 @@ struct Triangle_MDL7
/** \struct Vertex
* \brief Vertex data structure
*/
// ---------------------------------------------------------------------------
struct Vertex
{
uint8_t v[3];
@@ -530,6 +617,7 @@ struct Vertex
} PACK_STRUCT;
// ---------------------------------------------------------------------------
struct Vertex_MDL4
{
uint16_t v[3];
@@ -544,13 +632,12 @@ struct Vertex_MDL4
/** \struct Vertex_MDL7
* \brief Vertex data structure used in MDL7 files
*/
// ---------------------------------------------------------------------------
struct Vertex_MDL7
{
float x,y,z;
uint16_t vertindex; // = bone index
union {
uint16_t norm162index;
uint8_t norm162index;
float norm[3];
};
} PACK_STRUCT;
@@ -560,7 +647,6 @@ struct Vertex_MDL7
/** \struct BoneTransform_MDL7
* \brief bone transformation matrix structure used in MDL7 files
*/
// ---------------------------------------------------------------------------
struct BoneTransform_MDL7
{
//! 4*3
@@ -582,7 +668,6 @@ struct BoneTransform_MDL7
/** \struct Frame_MDL7
* \brief Frame data structure used by MDL7 files
*/
// ---------------------------------------------------------------------------
struct Frame_MDL7
{
char frame_name[AI_MDL7_MAX_FRAMENAMESIZE];
@@ -595,7 +680,6 @@ struct Frame_MDL7
/** \struct SimpleFrame
* \brief Data structure for a simple frame
*/
// ---------------------------------------------------------------------------
struct SimpleFrame
{
//! Minimum vertex of the bounding box
@@ -615,7 +699,6 @@ struct SimpleFrame
/** \struct Frame
* \brief Model frame data structure
*/
// ---------------------------------------------------------------------------
struct Frame
{
//! 0 = simple frame, !0 = group frame
@@ -626,6 +709,7 @@ struct Frame
} PACK_STRUCT;
// ---------------------------------------------------------------------------
struct SimpleFrame_MDLn_SP
{
//! Minimum vertex of the bounding box
@@ -645,7 +729,6 @@ struct SimpleFrame_MDLn_SP
/** \struct GroupFrame
* \brief Data structure for a group of frames
*/
// ---------------------------------------------------------------------------
struct GroupFrame
{
//! 0 = simple frame, !0 = group frame
@@ -675,7 +758,6 @@ struct GroupFrame
/** \struct IntFace_MDL7
* \brief Internal data structure to temporarily represent a face
*/
// ---------------------------------------------------------------------------
struct IntFace_MDL7
{
// provide a constructor for our own convenience
@@ -700,7 +782,6 @@ struct IntFace_MDL7
* which has been created from two single materials along with the
* original material indices.
*/
// ---------------------------------------------------------------------------
struct IntMaterial_MDL7
{
// provide a constructor for our own convenience
@@ -717,6 +798,188 @@ struct IntMaterial_MDL7
unsigned int iOldMatIndices[2];
};
// ---------------------------------------------------------------------------
/** \struct IntBone_MDL7
* \brief Internal data structure to represent a bone in a MDL7 file with
* all of its animation channels assigned to it.
*/
struct IntBone_MDL7 : aiBone
{
//! Default constructor
IntBone_MDL7() : iParent (0xffff)
{
pkeyPositions.reserve(30);
pkeyScalings.reserve(30);
pkeyRotations.reserve(30);
}
//! Parent bone of the bone
uint64_t iParent;
//! Relative position of the bone
aiVector3D vPosition;
//! Array of position keys
std::vector<aiVectorKey> pkeyPositions;
//! Array of scaling keys
std::vector<aiVectorKey> pkeyScalings;
//! Array of rotation keys
std::vector<aiQuatKey> pkeyRotations;
};
// ---------------------------------------------------------------------------
//! Describes a MDL7 frame
struct IntFrameInfo_MDL7
{
//! Construction from an existing frame header
IntFrameInfo_MDL7(const MDL::Frame_MDL7* _pcFrame,unsigned int _iIndex)
: pcFrame(_pcFrame), iIndex(_iIndex)
{}
//! Index of the frame
unsigned int iIndex;
//! Points to the header of the frame
const MDL::Frame_MDL7* pcFrame;
};
// ---------------------------------------------------------------------------
//! Describes a MDL7 mesh group
struct IntGroupInfo_MDL7
{
//! Default constructor
IntGroupInfo_MDL7() :
iIndex(0),
pcGroup(NULL), pcGroupUVs(NULL),
pcGroupTris(NULL), pcGroupVerts(NULL)
{}
//! Construction from an existing group header
IntGroupInfo_MDL7(const MDL::Group_MDL7* _pcGroup,unsigned int _iIndex)
:
pcGroup(_pcGroup),iIndex(_iIndex)
{}
//! Index of the group
unsigned int iIndex;
//! Points to the header of the group
const MDL::Group_MDL7* pcGroup;
//! Points to the beginning of the uv coordinate section
const MDL::TexCoord_MDL7* pcGroupUVs;
//! Points to the beginning of the triangle section
const MDL::Triangle_MDL7* pcGroupTris;
//! Points to the beginning of the vertex section
const MDL::Vertex_MDL7* pcGroupVerts;
};
// ---------------------------------------------------------------------------
//! Holds the data that belongs to a MDL7 mesh group
struct IntGroupData_MDL7
{
IntGroupData_MDL7()
: pcFaces(NULL), bNeed2UV(false)
{}
//! Array of faces that belong to the group
MDL::IntFace_MDL7* pcFaces;
//! Array of vertex positions
std::vector<aiVector3D> vPositions;
//! Array of vertex normals
std::vector<aiVector3D> vNormals;
//! Array of bones indices
std::vector<unsigned int> aiBones;
//! First UV coordinate set
std::vector<aiVector3D> vTextureCoords1;
//! Optional second UV coordinate set
std::vector<aiVector3D> vTextureCoords2;
//! Specifies whether there are two texture
//! coordinate sets required
bool bNeed2UV;
};
// ---------------------------------------------------------------------------
//! Holds data from an MDL7 file that is shared by all mesh groups
struct IntSharedData_MDL7
{
//! Default constructor
IntSharedData_MDL7()
{
abNeedMaterials.reserve(10);
}
//! Destruction: properly delete all allocated resources
~IntSharedData_MDL7()
{
// kill all bones
if (this->apcOutBones)
{
for (unsigned int m = 0; m < iNum;++m)
delete this->apcOutBones[m];
delete[] this->apcOutBones;
}
}
//! Specifies which materials are used
std::vector<bool> abNeedMaterials;
//! List of all materials
std::vector<MaterialHelper*> pcMats;
//! List of all bones
IntBone_MDL7** apcOutBones;
//! number of bones
unsigned int iNum;
};
// ---------------------------------------------------------------------------
//! Contains input data for GenerateOutputMeshes_3DGS_MDL7
struct IntSplittedGroupData_MDL7
{
//! Construction from a given shared data set
IntSplittedGroupData_MDL7(IntSharedData_MDL7& _shared,
std::vector<aiMesh*>& _avOutList)
: shared(_shared), avOutList(_avOutList)
{
}
//! Destruction: properly delete all allocated resources
~IntSplittedGroupData_MDL7()
{
// kill all face lists
if(this->aiSplit)
{
for (unsigned int m = 0; m < shared.pcMats.size();++m)
delete this->aiSplit[m];
delete[] this->aiSplit;
}
}
//! Contains a list of all faces per material
std::vector<unsigned int>** aiSplit;
//! Shared data for all groups of the model
IntSharedData_MDL7& shared;
//! List of meshes
std::vector<aiMesh*>& avOutList;
};
};}; // end namespaces
#endif // !! AI_MDLFILEHELPER_H_INC
+1293 -1227
View File
File diff suppressed because it is too large Load Diff
+293 -94
View File
@@ -61,6 +61,11 @@ class MaterialHelper;
using namespace MDL;
#if (!defined VALIDATE_FILE_SIZE)
# define VALIDATE_FILE_SIZE(msg) this->SizeCheck(msg,__FILE__,__LINE__)
#endif
// ---------------------------------------------------------------------------
/** Used to load MDL files
*/
@@ -104,120 +109,57 @@ protected:
protected:
// -------------------------------------------------------------------
/** Import a quake 1 MDL file
/** Import a quake 1 MDL file (IDPO)
*/
void InternReadFile_Quake1( );
// -------------------------------------------------------------------
/** Import a GameStudio A4/A5 file
/** Import a GameStudio A4/A5 file (MDL 3,4,5)
*/
void InternReadFile_GameStudio( );
void InternReadFile_3DGS_MDL345( );
// -------------------------------------------------------------------
/** Import a GameStudio A7 file
/** Import a GameStudio A7 file (MDL 7)
*/
void InternReadFile_GameStudioA7( );
void InternReadFile_3DGS_MDL7( );
// -------------------------------------------------------------------
/** Import a CS:S/HL2 MDL file
/** Import a CS:S/HL2 MDL file (not fully implemented)
*/
void InternReadFile_HL2( );
// *******************************************************************
// Debugging/validation functions
// -------------------------------------------------------------------
/** Load a paletized texture from the file and convert it to 32bpp
/** Check whether a given position is inside the valid range
* Throw a new ImportErrorException if it is not
* \param szPos Cursor position
* \param szFile Name of the source file from which the function was called
* \param iLine Source code line from which the function was called
*/
void CreateTextureARGB8(const unsigned char* szData);
void SizeCheck(const void* szPos);
void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine);
// -------------------------------------------------------------------
/** Used to load textures from MDL3/4
* \param szData Input data
* \param iType Color data type
* \param piSkip Receive: Size to skip
*/
void CreateTextureARGB8_GS4(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip);
// -------------------------------------------------------------------
/** Used to load textures from MDL5
* \param szData Input data
* \param iType Color data type
* \param piSkip Receive: Size to skip
*/
void CreateTextureARGB8_GS5(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip);
// -------------------------------------------------------------------
/** Parse a skin lump in a MDL7 file with all of its features
* \param szCurrent Current data pointer
* \param szCurrentOut Output data pointer
* \param pcMats Material list for this group. To be filled ...
*/
void ParseSkinLump_GameStudioA7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
std::vector<MaterialHelper*>& pcMats);
// -------------------------------------------------------------------
/** Parse texture color data for MDL5, MDL6 and MDL7 formats
* \param szData Current data pointer
* \param iType type of the texture data. No DDS or external
* \param piSkip Receive the number of bytes to skip
* \param pcNew Must point to fully initialized data. Width and
* height must be set.
*/
void ParseTextureColorData(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip,
aiTexture* pcNew);
// -------------------------------------------------------------------
/** Validate the header data structure of a game studio MDL7 file
* \param pcHeader Input header to be validated
*/
void ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader);
void ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader);
// -------------------------------------------------------------------
/** Join two materials / skins. Setup UV source ... etc
* \param pcMat1 First input material
* \param pcMat2 Second input material
* \param pcMatOut Output material instance to be filled. Must be empty
/** Validate the header data structure of a Quake 1 model
* \param pcHeader Input header to be validated
*/
void JoinSkins_GameStudioA7(MaterialHelper* pcMat1,
MaterialHelper* pcMat2,
MaterialHelper* pcMatOut);
// -------------------------------------------------------------------
/** Generate the final output meshes for a7 models
* \param aiSplit Face-per-material list
* \param pcMats List of all materials
* \param avOutList Output: List of all meshes
* \param pcFaces List of all input faces
* \param vPositions List of all input vectors
* \param vNormals List of all input normal vectors
* \param vTextureCoords1 List of all input UV coords #1
* \param vTextureCoords2 List of all input UV coords #2
*/
void GenerateOutputMeshes_GameStudioA7(
const std::vector<unsigned int>** aiSplit,
const std::vector<MaterialHelper*>& pcMats,
std::vector<aiMesh*>& avOutList,
const MDL::IntFace_MDL7* pcFaces,
const std::vector<aiVector3D>& vPositions,
const std::vector<aiVector3D>& vNormals,
const std::vector<aiVector3D>& vTextureCoords1,
const std::vector<aiVector3D>& vTextureCoords2);
void ValidateHeader_Quake1(const MDL::Header* pcHeader);
// -------------------------------------------------------------------
/** Calculate absolute bone animation matrices for each bone
* \param pcBones Pointer to the bone section in the file
* \param apcOutBones Output bones array
*/
void CalculateAbsBoneAnimMatrices(const MDL::Bone_MDL7* pcBones,
aiBone** apcOutBones);
// *******************************************************************
// Material import
// -------------------------------------------------------------------
/** Try to load a palette from the current directory (colormap.lmp)
@@ -230,6 +172,262 @@ protected:
*/
void FreePalette(const unsigned char* pszColorMap);
// -------------------------------------------------------------------
/** Load a paletized texture from the file and convert it to 32bpp
*/
void CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData);
// -------------------------------------------------------------------
/** Used to load textures from MDL3/4
* \param szData Input data
* \param iType Color data type
* \param piSkip Receive: Size to skip, in bytes
*/
void CreateTexture_3DGS_MDL4(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip);
// -------------------------------------------------------------------
/** Used to load textures from MDL5
* \param szData Input data
* \param iType Color data type
* \param piSkip Receive: Size to skip, in bytes
*/
void CreateTexture_3DGS_MDL5(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip);
// -------------------------------------------------------------------
/** Checks whether a texture can be replaced with a single color
* This is useful for all file formats before MDL7 (all those
* that are not containing material colors separate from textures).
* MED seems to write dummy 8x8 monochrome images instead.
* \param pcTexture Input texture
* \return aiColor.r is set to qnan if the function fails and no
* color can be found.
*/
aiColor4D ReplaceTextureWithColor(const aiTexture* pcTexture);
// *******************************************************************
// Quake1, MDL 3,4,5 import
// -------------------------------------------------------------------
/** Converts the absolute texture coordinates in MDL5 files to
* relative in a range between 0 and 1
*/
void CalculateUVCoordinates_MDL5();
// -------------------------------------------------------------------
/** Read an UV coordinate from the file. If the file format is not
* MDL5, the function calculates relative texture coordinates
* \param vOut Receives the output UV coord
* \param pcSrc UV coordinate buffer
* \param UV coordinate index
*/
void ImportUVCoordinate_3DGS_MDL345( aiVector3D& vOut,
const MDL::TexCoord_MDL3* pcSrc,
unsigned int iIndex);
// -------------------------------------------------------------------
/** Setup the material properties for Quake and MDL<7 models.
* These formats don't support more than one material per mesh,
* therefore the method processes only ONE skin and removes
* all others.
*/
void SetupMaterialProperties_3DGS_MDL5_Quake1( );
// *******************************************************************
// MDL7 import
// -------------------------------------------------------------------
/** Parse a skin lump in a MDL7/HMP7 file with all of its features
* variant 1: Current cursor position is the beginning of the skin header
* \param szCurrent Current data pointer
* \param szCurrentOut Output data pointer
* \param pcMats Material list for this group. To be filled ...
*/
void ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
std::vector<MaterialHelper*>& pcMats);
// -------------------------------------------------------------------
/** Parse a skin lump in a MDL7/HMP7 file with all of its features
* variant 2: Current cursor position is the beginning of the skin data
* \param szCurrent Current data pointer
* \param szCurrentOut Output data pointer
* \param pcMatOut Output material
* \param iType header.typ
* \param iWidth header.width
* \param iHeight header.height
*/
void ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
MaterialHelper* pcMatOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight);
// -------------------------------------------------------------------
/** Skip a skin lump in a MDL7/HMP7 file
* \param szCurrent Current data pointer
* \param szCurrentOut Output data pointer. Points to the byte just
* behind the last byte of the skin.
* \param iType header.typ
* \param iWidth header.width
* \param iHeight header.height
*/
void SkipSkinLump_3DGS_MDL7(const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight);
// -------------------------------------------------------------------
/** Parse texture color data for MDL5, MDL6 and MDL7 formats
* \param szData Current data pointer
* \param iType type of the texture data. No DDS or external
* \param piSkip Receive the number of bytes to skip
* \param pcNew Must point to fully initialized data. Width and
* height must be set. If pcNew->pcData is set to 0xffffffff,
* piSkip will receive the size of the texture, in bytes, but no
* color data will be read.
*/
void ParseTextureColorData(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip,
aiTexture* pcNew);
// -------------------------------------------------------------------
/** Join two materials / skins. Setup UV source ... etc
* \param pcMat1 First input material
* \param pcMat2 Second input material
* \param pcMatOut Output material instance to be filled. Must be empty
*/
void JoinSkins_3DGS_MDL7(MaterialHelper* pcMat1,
MaterialHelper* pcMat2,
MaterialHelper* pcMatOut);
// -------------------------------------------------------------------
/** Add a bone transformation key to an animation
* \param iTrafo Index of the transformation (always==frame index?)
* No need to validate this index, it is always valid.
* \param pcBoneTransforms Bone transformation for this index
* \param apcOutBones Output bones array
*/
void AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
const MDL::BoneTransform_MDL7* pcBoneTransforms,
MDL::IntBone_MDL7** apcBonesOut);
// -------------------------------------------------------------------
/** Load the bone list of a MDL7 file
* \return If the bones could be loaded successfully, a valid
* array containing pointers to a temporary bone
* representation. NULL if the bones could not be loaded.
*/
MDL::IntBone_MDL7** LoadBones_3DGS_MDL7();
// -------------------------------------------------------------------
/** Load bone transformation keyframes from a file chunk
* \param groupInfo -> doc of data structure
* \param frame -> doc of data structure
* \param shared -> doc of data structure
*/
void ParseBoneTrafoKeys_3DGS_MDL7(
const MDL::IntGroupInfo_MDL7& groupInfo,
IntFrameInfo_MDL7& frame,
MDL::IntSharedData_MDL7& shared);
// -------------------------------------------------------------------
/** Calculate absolute bone animation matrices for each bone
* \param pcBones Pointer to the bone section in the file
* \param apcOutBones Output bones array
*/
void CalcAbsBoneMatrices_3DGS_MDL7(const MDL::Bone_MDL7* pcBones,
MDL::IntBone_MDL7** apcOutBones);
// -------------------------------------------------------------------
/** Add all bones to the nodegraph (as children of the root node)
* \param apcBonesOut List of bones
* \param pcParent Parent node. New nodes will be added to this node
* \param iParentIndex Index of the parent bone
*/
void AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut,
aiNode* pcParent,uint16_t iParentIndex);
// -------------------------------------------------------------------
/** Build output animations
* \param apcBonesOut List of bones
*/
void BuildOutputAnims_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut);
// -------------------------------------------------------------------
/** Handles materials that are just referencing another material
* There is no test file for this feature, but Conitec's doc
* say it is used.
*/
void HandleMaterialReferences_3DGS_MDL7();
// -------------------------------------------------------------------
/** Copies only the material that are referenced by at least one
* mesh to the final output material list. All other materials
* will be discarded.
* \param shared -> doc of data structure
*/
void CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared);
// -------------------------------------------------------------------
/** Process the frame section at the end of a group
* \param groupInfo -> doc of data structure
* \param shared -> doc of data structure
* \param szCurrent Pointer to the start of the frame section
* \param szCurrentOut Receives a pointer to the first byte of the
* next data section.
* \return false to read no further groups (a small workaround for
* some tiny and unsolved problems ... )
*/
bool ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
MDL::IntSharedData_MDL7& shared,
const unsigned char* szCurrent,
const unsigned char** szCurrentOut);
// -------------------------------------------------------------------
/** Sort all faces by their materials. If the mesh is using
* multiple materials per face (that are blended together) the function
* might create new materials.
* \param groupInfo -> doc of data structure
* \param groupData -> doc of data structure
* \param splittedGroupData -> doc of data structure
*/
void SortByMaterials_3DGS_MDL7(
const MDL::IntGroupInfo_MDL7& groupInfo,
MDL::IntGroupData_MDL7& groupData,
MDL::IntSplittedGroupData_MDL7& splittedGroupData);
// -------------------------------------------------------------------
/** Read all faces and vertices from a MDL7 group. The function fills
* preallocated memory buffers.
* \param groupInfo -> doc of data structure
* \param groupData -> doc of data structure
*/
void ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
MDL::IntGroupData_MDL7& groupData);
// -------------------------------------------------------------------
/** Generate the final output meshes for a7 models
* \param groupData -> doc of data structure
* \param splittedGroupData -> doc of data structure
*/
void GenerateOutputMeshes_3DGS_MDL7(
MDL::IntGroupData_MDL7& groupData,
MDL::IntSplittedGroupData_MDL7& splittedGroupData);
// -------------------------------------------------------------------
/** Try to determine whether the normals of the model are flipped
* Some MDL7 models seem to have flipped normals (and there is also
@@ -239,16 +437,13 @@ protected:
*/
void FlipNormals(aiMesh* pcMesh);
private:
/** Header of the MDL file */
const MDL::Header* m_pcHeader;
protected:
/** Buffer to hold the loaded file */
unsigned char* mBuffer;
/** For GameStudio MDL files: The number in the magic
word, either 3,4 or 5*/
/** For GameStudio MDL files: The number in the magic word, either 3,4 or 5
* (MDL7 doesn't need this, the format has a separate loader) */
unsigned int iGSFileVersion;
/** Output I/O handler. used to load external lmp files
@@ -258,6 +453,10 @@ private:
/** Output scene to be filled
*/
aiScene* pScene;
/** Size of the input file in bytes
*/
unsigned int iFileSize;
};
}; // end of namespace Assimp
+774
View File
@@ -0,0 +1,774 @@
/*
---------------------------------------------------------------------------
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 material part of the MDL importer class */
// internal headers
#include "MaterialSystem.h"
#include "MDLLoader.h"
#include "MDLDefaultColorMap.h"
#include "qnan.h"
// public ASSIMP headers
#include "../include/DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
{
// now try to find the color map in the current directory
IOStream* pcStream = this->pIOHandler->Open("colormap.lmp","rb");
const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
if(pcStream)
{
if (pcStream->FileSize() >= 768)
{
szColorMap = new unsigned char[256*3];
pcStream->Read(const_cast<unsigned char*>(szColorMap),256*3,1);
DefaultLogger::get()->info("Found valid colormap.lmp in directory. "
"It will be used to decode embedded textures in palletized formats.");
}
delete pcStream;
pcStream = NULL;
}
*pszColorMap = szColorMap;
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::FreePalette(const unsigned char* szColorMap)
{
if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
{
delete[] szColorMap;
}
return;
}
// ------------------------------------------------------------------------------------------------
aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture)
{
ai_assert(NULL != pcTexture);
aiColor4D clrOut;
clrOut.r = std::numeric_limits<float>::quiet_NaN();
if (!pcTexture->mHeight || !pcTexture->mWidth)return clrOut;
const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth;
const aiTexel* pcTexel = pcTexture->pcData+1;
const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels];
while (pcTexel != pcTexelEnd)
{
if (*pcTexel != *(pcTexel-1))
{
pcTexel = NULL;break;
}
++pcTexel;
}
if (pcTexel)
{
clrOut.r = pcTexture->pcData->r / 255.0f;
clrOut.g = pcTexture->pcData->g / 255.0f;
clrOut.b = pcTexture->pcData->b / 255.0f;
clrOut.a = pcTexture->pcData->a / 255.0f;
}
return clrOut;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData)
{
const MDL::Header* pcHeader = (const MDL::Header*)this->mBuffer;
VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth *
pcHeader->skinheight);
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
pcNew->mWidth = pcHeader->skinwidth;
pcNew->mHeight = pcHeader->skinheight;
pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
const unsigned char* szColorMap;
this->SearchPalette(&szColorMap);
// copy texture data
for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char val = szData[i];
const unsigned char* sz = &szColorMap[val*3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = *sz++;
pcNew->pcData[i].g = *sz++;
pcNew->pcData[i].b = *sz;
}
this->FreePalette(szColorMap);
// store the texture
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
this->pScene->mNumTextures++;
delete[] pc;
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip)
{
const MDL::Header* pcHeader = (const MDL::Header*)this->mBuffer;
ai_assert(NULL != piSkip);
if (iType == 1 || iType > 3)
{
DefaultLogger::get()->error("Unsupported texture file format");
return;
}
bool bNoRead = *piSkip == 0xffffffff;
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
pcNew->mWidth = pcHeader->skinwidth;
pcNew->mHeight = pcHeader->skinheight;
if (bNoRead)pcNew->pcData = (aiTexel*)0xffffffff;
this->ParseTextureColorData(szData,iType,piSkip,pcNew);
// store the texture
if (!bNoRead)
{
if (!this->pScene->mNumTextures)
{
this->pScene->mNumTextures = 1;
this->pScene->mTextures = new aiTexture*[1];
this->pScene->mTextures[0] = pcNew;
}
else
{
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
this->pScene->mNumTextures++;
delete[] pc;
}
}
else delete pcNew;
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::ParseTextureColorData(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip,
aiTexture* pcNew)
{
// allocate storage for the texture image
if ((aiTexel*)0xffffffff != pcNew->pcData)
pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
// R5G6B5 format (with or without MIPs)
// ****************************************************************
if (2 == iType || 10 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = (unsigned char)val.b << 3;
pcNew->pcData[i].g = (unsigned char)val.g << 2;
pcNew->pcData[i].b = (unsigned char)val.r << 3;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
*piSkip = i * 2;
// apply MIP maps
if (10 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// ARGB4 format (with or without MIPs)
// ****************************************************************
else if (3 == iType || 11 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
pcNew->pcData[i].a = (unsigned char)val.a << 4;
pcNew->pcData[i].r = (unsigned char)val.r << 4;
pcNew->pcData[i].g = (unsigned char)val.g << 4;
pcNew->pcData[i].b = (unsigned char)val.b << 4;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
*piSkip = i * 2;
// apply MIP maps
if (11 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// RGB8 format (with or without MIPs)
// ****************************************************************
else if (4 == iType || 12 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char* _szData = &szData[i*3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].b = *_szData++;
pcNew->pcData[i].g = *_szData++;
pcNew->pcData[i].r = *_szData;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
// apply MIP maps
*piSkip = i * 3;
if (12 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// ARGB8 format (with ir without MIPs)
// ****************************************************************
else if (5 == iType || 13 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char* _szData = &szData[i*4];
pcNew->pcData[i].b = *_szData++;
pcNew->pcData[i].g = *_szData++;
pcNew->pcData[i].r = *_szData++;
pcNew->pcData[i].a = *_szData;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
// apply MIP maps
*piSkip = i << 2;
if (13 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2;
}
}
// palletized 8 bit texture. As for Quake 1
// ****************************************************************
else if (0 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
const unsigned char* szColorMap;
this->SearchPalette(&szColorMap);
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char val = szData[i];
const unsigned char* sz = &szColorMap[val*3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = *sz++;
pcNew->pcData[i].g = *sz++;
pcNew->pcData[i].b = *sz;
}
this->FreePalette(szColorMap);
}
else i = pcNew->mWidth*pcNew->mHeight;
*piSkip = i;
// FIXME: Also support for MIP maps?
}
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip)
{
ai_assert(NULL != piSkip);
bool bNoRead = *piSkip == 0xffffffff;
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
VALIDATE_FILE_SIZE(szData+8);
// first read the size of the texture
pcNew->mWidth = *((uint32_t*)szData);
szData += sizeof(uint32_t);
pcNew->mHeight = *((uint32_t*)szData);
szData += sizeof(uint32_t);
if (bNoRead)pcNew->pcData = (aiTexel*)0xffffffff;
// this should not occur - at least the docs say it shouldn't
// however, you can easily try out what MED does if you have
// a model with a DDS texture and export it to MDL5 ...
// yes, you're right. It embedds the DDS texture ... :cry:
if (6 == iType)
{
// this is a compressed texture in DDS format
*piSkip = pcNew->mWidth;
VALIDATE_FILE_SIZE(szData + *piSkip);
if (!bNoRead)
{
// place a hint and let the application know that it's
// a DDS file
pcNew->mHeight = 0;
pcNew->achFormatHint[0] = 'd';
pcNew->achFormatHint[1] = 'd';
pcNew->achFormatHint[2] = 's';
pcNew->achFormatHint[3] = '\0';
pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
::memcpy(pcNew->pcData,szData,pcNew->mWidth);
}
}
else
{
// parse the color data of the texture
this->ParseTextureColorData(szData,iType,
piSkip,pcNew);
}
*piSkip += sizeof(uint32_t) * 2;
if (!bNoRead)
{
// store the texture
if (!this->pScene->mNumTextures)
{
this->pScene->mNumTextures = 1;
this->pScene->mTextures = new aiTexture*[1];
this->pScene->mTextures[0] = pcNew;
}
else
{
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
this->pScene->mNumTextures++;
delete[] pc;
}
}
else delete pcNew;
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
MaterialHelper* pcMatOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight)
{
aiTexture* pcNew = NULL;
// get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF);
if (0x1 == iMasked)
{
// ***** REFERENCE TO ANOTHER SKIN INDEX *****
// NOTE: Documentation - if you can call it a documentation, I prefer
// the expression "rubbish" - states it is currently unused. However,
// I don't know what ideas the terrible developers of Conitec will
// have tomorrow, so Im going to implement it.
int referrer = (int)iWidth;
pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL);
}
else if (0x6 == iMasked)
{
// ***** EMBEDDED DDS FILE *****
if (1 != iHeight)
{
DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
"but texture height is not equal to 1, which is not supported by MED");
}
pcNew = new aiTexture();
pcNew->mHeight = 0;
pcNew->mWidth = iWidth;
pcNew->achFormatHint[0] = 'd';
pcNew->achFormatHint[1] = 'd';
pcNew->achFormatHint[2] = 's';
pcNew->achFormatHint[3] = '\0';
pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
szCurrent += iWidth;
}
if (0x7 == iMasked)
{
// ***** REFERENCE TO EXTERNAL FILE *****
if (1 != iHeight)
{
DefaultLogger::get()->warn("Found a reference to an external texture, "
"but texture height is not equal to 1, which is not supported by MED");
}
aiString szFile;
const size_t iLen = strlen((const char*)szCurrent);
size_t iLen2 = iLen+1;
iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
memcpy(szFile.data,(const char*)szCurrent,iLen2);
szFile.length = iLen;
szCurrent += iLen2;
// place this as diffuse texture
pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else if (iMasked || !iType || (iType && iWidth && iHeight))
{
// ***** STANDARD COLOR TEXTURE *****
pcNew = new aiTexture();
if (!iHeight || !iWidth)
{
DefaultLogger::get()->warn("Found embedded texture, but its width "
"an height are both 0. Is this a joke?");
// generate an empty chess pattern
pcNew->mWidth = pcNew->mHeight = 8;
pcNew->pcData = new aiTexel[64];
for (unsigned int x = 0; x < 8;++x)
{
for (unsigned int y = 0; y < 8;++y)
{
bool bSet = false;
if (0 == x % 2 && 0 != y % 2 ||
0 != x % 2 && 0 == y % 2)bSet = true;
aiTexel* pc = &pcNew->pcData[y * 8 + x];
if (bSet)pc->r = pc->b = pc->g = 0xFF;
else pc->r = pc->b = pc->g = 0;
pc->a = 0xFF;
}
}
}
else
{
// it is a standard color texture. Fill in width and height
// and call the same function we used for loading MDL5 files
pcNew->mWidth = iWidth;
pcNew->mHeight = iHeight;
unsigned int iSkip = 0;
this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
// skip length of texture data
szCurrent += iSkip;
}
}
// sometimes there are MDL7 files which have a monochrome
// texture instead of material colors ... posssible they have
// been converted to MDL7 from other formats, such as MDL5
aiColor4D clrTexture = this->ReplaceTextureWithColor(pcNew);
// check whether a material definition is contained in the skin
if (iType & AI_MDL7_SKINTYPE_MATERIAL)
{
const MDL::Material_MDL7* pcMatIn = (const MDL::Material_MDL7*)szCurrent;
szCurrent = (unsigned char*)(pcMatIn+1);
VALIDATE_FILE_SIZE(szCurrent);
aiColor3D clrTemp;
#define COLOR_MULTIPLY_RGB() \
if (is_not_qnan(clrTexture.r)) \
{ \
clrTemp.r *= clrTexture.r; \
clrTemp.g *= clrTexture.g; \
clrTemp.b *= clrTexture.b; \
}
// read diffuse color
clrTemp.r = pcMatIn->Diffuse.r;
clrTemp.g = pcMatIn->Diffuse.g;
clrTemp.b = pcMatIn->Diffuse.b;
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
// read specular color
clrTemp.r = pcMatIn->Specular.r;
clrTemp.g = pcMatIn->Specular.g;
clrTemp.b = pcMatIn->Specular.b;
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
// read ambient color
clrTemp.r = pcMatIn->Ambient.r;
clrTemp.g = pcMatIn->Ambient.g;
clrTemp.b = pcMatIn->Ambient.b;
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
// read emissive color
clrTemp.r = pcMatIn->Emissive.r;
clrTemp.g = pcMatIn->Emissive.g;
clrTemp.b = pcMatIn->Emissive.b;
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
// FIX: Take the opacity from the ambient color
// the doc says something else, but it is fact that MED exports the
// opacity like this .... ARRRGGHH!
clrTemp.r = pcMatIn->Ambient.a;
if (is_not_qnan(clrTexture.r))clrTemp.r *= clrTexture.a;
pcMatOut->AddProperty<float>(&clrTemp.r,1,AI_MATKEY_OPACITY);
// read phong power
int iShadingMode = (int)aiShadingMode_Gouraud;
if (0.0f != pcMatIn->Power)
{
iShadingMode = (int)aiShadingMode_Phong;
pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
}
pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
}
else if (is_not_qnan(clrTexture.r))
{
pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE);
pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR);
}
// if the texture could be replaced by a single material color
// we don't need the texture anymore
if (is_not_qnan(clrTexture.r))
{
delete pcNew;
pcNew = NULL;
}
// if an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ...
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
{
VALIDATE_FILE_SIZE(szCurrent);
int32_t iMe = *((int32_t*)szCurrent);
szCurrent += sizeof(char) * iMe + sizeof(int32_t);
VALIDATE_FILE_SIZE(szCurrent);
}
// if an embedded texture has been loaded setup the corresponding
// data structures in the aiScene instance
if (pcNew && this->pScene->mNumTextures <= 999)
{
// place this as diffuse texture
char szCurrent[5];
::sprintf(szCurrent,"*%i",this->pScene->mNumTextures);
aiString szFile;
const size_t iLen = strlen((const char*)szCurrent);
size_t iLen2 = iLen+1;
iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
::memcpy(szFile.data,(const char*)szCurrent,iLen2);
szFile.length = iLen;
pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
// store the texture
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
this->pScene->mNumTextures++;
delete[] pc;
}
VALIDATE_FILE_SIZE(szCurrent);
*szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::SkipSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight)
{
// get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF);
if (0x6 == iMasked)
{
szCurrent += iWidth;
}
if (0x7 == iMasked)
{
const size_t iLen = ::strlen((const char*)szCurrent);
szCurrent += iLen+1;
}
else if (iMasked || !iType)
{
if (iMasked || !iType || (iType && iWidth && iHeight))
{
// ParseTextureColorData(..., aiTexture::pcData == 0xffffffff) will simply
// return the size of the color data in bytes in iSkip
unsigned int iSkip = 0;
aiTexture tex;
tex.pcData = reinterpret_cast<aiTexel*>(0xffffffff);
tex.mHeight = iHeight;
tex.mWidth = iWidth;
this->ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex);
// skip length of texture data
szCurrent += iSkip;
}
}
// check whether a material definition is contained in the skin
if (iType & AI_MDL7_SKINTYPE_MATERIAL)
{
const MDL::Material_MDL7* pcMatIn = (const MDL::Material_MDL7*)szCurrent;
szCurrent = (unsigned char*)(pcMatIn+1);
}
// if an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ...
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
{
int32_t iMe = *((int32_t*)szCurrent);
szCurrent += sizeof(char) * iMe + sizeof(int32_t);
}
*szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
std::vector<MaterialHelper*>& pcMats)
{
ai_assert(NULL != szCurrent);
ai_assert(NULL != szCurrentOut);
*szCurrentOut = szCurrent;
const MDL::Skin_MDL7* pcSkin = (const MDL::Skin_MDL7*)szCurrent;
szCurrent += 12;
// allocate an output material
MaterialHelper* pcMatOut = new MaterialHelper();
pcMats.push_back(pcMatOut);
// skip length of file name
szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
this->ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut,
pcSkin->typ,pcSkin->width,pcSkin->height);
// place the name of the skin in the material
const size_t iLen = strlen(pcSkin->texture_name);
if (0 != iLen)
{
aiString szFile;
memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
szFile.length = iLen;
pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
}
return;
}
+1
View File
@@ -465,6 +465,7 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
};
char szKey[256];
if (iIndex > 100)return AI_FAILURE;
// get the path to the texture
#if _MSC_VER >= 1400
+2 -1
View File
@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp
{
// ---------------------------------------------------------------------------
/** Internal material helper class. Can be used to fill an aiMaterial
structure easily. */
@@ -209,4 +210,4 @@ inline aiReturn MaterialHelper::AddProperty<int> (const int* pInput,
}
#endif //!! AI_MATERIALSYSTEM_H_INC
#endif //!! AI_MATERIALSYSTEM_H_INC
+115
View File
@@ -0,0 +1,115 @@
/*
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 helper functions for text parsing */
#ifndef AI_PARSING_UTILS_H_INC
#define AI_PARSING_UTILS_H_INC
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool IsSpace( const char_t in)
{
return (in == (char_t)' ' || in == (char_t)'\t');
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool IsLineEnd( const char_t in)
{
return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool IsSpaceOrNewLine( const char_t in)
{
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipSpaces( const char_t* in, const char_t** out)
{
while (*in == (char_t)' ' || *in == (char_t)'\t')in++;
*out = in;
return !IsLineEnd<char_t>(*in);
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipSpaces( const char_t** inout)
{
return SkipSpaces<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipLine( const char_t* in, const char_t** out)
{
while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++;
if (*in == (char_t)'\0')
{
*out = in;
return false;
}
in++;
*out = in;
return true;
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipLine( const char_t** inout)
{
return SkipLine<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline void SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
{
while (*in == (char_t)' ' || *in == (char_t)'\t' ||
*in == (char_t)'\r' || *in == (char_t)'\n')in++;
*out = in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipSpacesAndLineEnd( const char_t** inout)
{
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
}
#endif // ! AI_PARSING_UTILS_H_INC
+7
View File
@@ -120,6 +120,7 @@ void PLYImporter::InternReadFile(
this->mBuffer[1] != 'L' && this->mBuffer[1] != 'l' ||
this->mBuffer[2] != 'Y' && this->mBuffer[2] != 'y')
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Magic number \'ply\' is no there");
}
char* szMe = (char*)&this->mBuffer[3];
@@ -136,6 +137,7 @@ void PLYImporter::InternReadFile(
SkipLine(szMe,(const char**)&szMe);
if(!PLY::DOM::ParseInstance(szMe,&sPlyDom, (unsigned int)fileSize))
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#1)");
}
}
@@ -156,16 +158,19 @@ void PLYImporter::InternReadFile(
SkipLine(szMe,(const char**)&szMe);
if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE, (unsigned int)fileSize))
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#2)");
}
}
else
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Unknown file format");
}
}
else
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Missing format specification");
}
this->pcDOM = &sPlyDom;
@@ -193,6 +198,7 @@ void PLYImporter::InternReadFile(
{
if (avPositions.size() < 3)
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Not enough vertices to build "
"a face list. ");
}
@@ -230,6 +236,7 @@ void PLYImporter::InternReadFile(
if (avMeshes.empty())
{
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Unable to extract mesh data ");
}
+2 -42
View File
@@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <list>
#include <sstream>
#include "ParsingUtils.h"
#include "../include/aiTypes.h"
#include "../include/aiMesh.h"
#include "../include/aiAnim.h"
@@ -551,48 +553,6 @@ TYPE PLY::PropertyInstance::ConvertTo(
}
};
// ---------------------------------------------------------------------------------
inline bool IsSpace( const char in)
{
return (in == ' ' || in == '\t');
}
// ---------------------------------------------------------------------------------
inline bool IsLineEnd( const char in)
{
return (in == '\r' || in == '\n' || in == '\0');
}
// ---------------------------------------------------------------------------------
inline bool IsSpaceOrNewLine( const char in)
{
return IsSpace(in) || IsLineEnd(in);
}
// ---------------------------------------------------------------------------------
inline bool SkipSpaces( const char* in, const char** out)
{
while (*in == ' ' || *in == '\t')in++;
*out = in;
return !IsLineEnd(*in);
}
// ---------------------------------------------------------------------------------
inline bool SkipLine( const char* in, const char** out)
{
while (*in != '\r' && *in != '\n' && *in != '\0')in++;
if (*in == '\0')
{
*out = in;
return false;
}
in++;
*out = in;
return true;
}
// ---------------------------------------------------------------------------------
inline void SkipSpacesAndLineEnd( const char* in, const char** out)
{
while (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n')in++;
*out = in;
}
};
#endif // !! include guard
+1070
View File
File diff suppressed because it is too large Load Diff
+408
View File
@@ -0,0 +1,408 @@
/*
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 Definition of SMD importer class
//!
#ifndef AI_SMDLOADER_H_INCLUDED
#define AI_SMDLOADER_H_INCLUDED
#include "BaseImporter.h"
#include "ParsingUtils.h"
#include "../include/aiTypes.h"
#include "../include/aiTexture.h"
#include "../include/aiAnim.h"
#include "../include/aiMaterial.h"
struct aiNode;
#include <vector>
namespace Assimp {
class MaterialHelper;
namespace SMD {
// ---------------------------------------------------------------------------
/** Data structure for a vertex in a SMD file
*/
struct Vertex
{
Vertex() : iParentNode(0xffffffff)
{}
//! Vertex position, normal and texture coordinate
aiVector3D pos,nor,uv;
//! Vertex parent node
unsigned int iParentNode;
//! Links to bones: pair.first is the bone index,
//! pair.second is the vertex weight.
//! WARN: The remaining weight (to reach 1.0f) is assigned
//! to the parent node/bone
std::vector<std::pair<unsigned int, float> > aiBoneLinks;
};
// ---------------------------------------------------------------------------
/** Data structure for a face in a SMD file
*/
struct Face
{
Face() : iTexture(0x0)
{}
//! Texture index for the face
unsigned int iTexture;
//! The three vertices of the face
Vertex avVertices[3];
};
// ---------------------------------------------------------------------------
/** Data structure for a bone in a SMD file
*/
struct Bone
{
//! Default constructor
Bone() : iParent(0xffffffff), bIsUsed(false)
{
}
//! Destructor
~Bone()
{
}
//! Name of the bone
std::string mName;
//! Parent of the bone
uint32_t iParent;
//! Animation of the bone
struct Animation
{
//! Public default constructor
Animation()
{
asKeys.reserve(20);
}
//! Data structure for a matrix key
struct MatrixKey
{
//! Matrix at this time
aiMatrix4x4 matrix;
//! Absolute transformation matrix
aiMatrix4x4 matrixAbsolute;
//! Position
aiVector3D vPos;
//! Rotation (euler angles)
aiVector3D vRot;
//! Current time. may be negative, this
//! will be fixed later
double dTime;
};
//! Index of the key with the smallest time value
uint32_t iFirstTimeKey;
//! Array of matrix keys
std::vector<MatrixKey> asKeys;
} sAnim;
//! Offset matrix of the bone
aiMatrix4x4 mOffsetMatrix;
//! true if the bone is referenced by at least one mesh
bool bIsUsed;
};
}; //! namespace SMD
// ---------------------------------------------------------------------------
/** Used to load Half-life 1 and 2 SMD models
*/
class SMDImporter : public BaseImporter
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
SMDImporter();
/** Destructor, private as well */
~SMDImporter();
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("*.smd;*.vta");
}
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
protected:
// -------------------------------------------------------------------
/** Parse the SMD file and create the output scene
*/
void ParseFile();
// -------------------------------------------------------------------
/** Parse the triangles section of the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives a pointer to the heading line of
* the next section (or to EOF)
*/
void ParseTrianglesSection(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse the vertex animation section in VTA files
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives a pointer to the heading line of
* the next section (or to EOF)
*/
void ParseVASection(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse the nodes section of the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives a pointer to the heading line of
* the next section (or to EOF)
*/
void ParseNodesSection(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse the skeleton section of the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives a pointer to the heading line of
* the next section (or to EOF)
*/
void ParseSkeletonSection(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse a single triangle in the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives the output cursor position
*/
void ParseTriangle(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse a single vertex in the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives the output cursor position
* \param vertex Vertex to be filled
*/
void ParseVertex(const char* szCurrent,
const char** szCurrentOut, SMD::Vertex& vertex,
bool bVASection = false);
// -------------------------------------------------------------------
/** Get the index of a texture. If the texture was not yet known
* it will be added to the internal texture list.
* \param filename Name of the texture
* \return Value texture index
*/
unsigned int GetTextureIndex(const std::string& filename);
// -------------------------------------------------------------------
/** Computes absolute bone transformations
* All output transformations are in worldspace.
*/
void ComputeAbsoluteBoneTransformations();
// -------------------------------------------------------------------
/** Parse a line in the skeleton section
*/
void ParseSkeletonElement(const char* szCurrent,
const char** szCurrentOut,int iTime);
// -------------------------------------------------------------------
/** Parse a line in the nodes section
*/
void ParseNodeInfo(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse a floating-point value
*/
bool ParseFloat(const char* szCurrent,
const char** szCurrentOut, float& out);
// -------------------------------------------------------------------
/** Parse an unsigned integer. There may be no sign!
*/
bool ParseUnsignedInt(const char* szCurrent,
const char** szCurrentOut, uint32_t& out);
// -------------------------------------------------------------------
/** Parse a signed integer. Signs (+,-) are handled.
*/
bool ParseSignedInt(const char* szCurrent,
const char** szCurrentOut, int32_t& out);
// -------------------------------------------------------------------
/** Fix invalid time values in the file
*/
void FixTimeValues();
// -------------------------------------------------------------------
/** Add all children of a bone as subnodes to a node
* \param pcNode Parent node
* \param iParent Parent bone index
*/
void AddBoneChildren(aiNode* pcNode, uint32_t iParent);
// -------------------------------------------------------------------
/** Build output meshes/materials/nodes/animations
*/
void CreateOutputMeshes();
void CreateOutputNodes();
void CreateOutputAnimations();
void CreateOutputMaterials();
// -------------------------------------------------------------------
/** Print a log message together with the current line number
*/
void LogErrorNoThrow(const char* msg);
void LogWarning(const char* msg);
// -------------------------------------------------------------------
inline bool SkipLine( const char* in, const char** out)
{
::SkipLine(in,out);
++iLineNumber;
return true;
}
// -------------------------------------------------------------------
inline void SkipSpacesAndLineEnd( const char* in, const char** out)
{
::SkipSpacesAndLineEnd(in,out);
++iLineNumber;
}
private:
/** Buffer to hold the loaded file */
const char* mBuffer;
/** Output scene to be filled
*/
aiScene* pScene;
/** Size of the input file in bytes
*/
unsigned int iFileSize;
/** Array of textures found in the file
*/
std::vector<std::string> aszTextures;
/** Array of triangles found in the file
*/
std::vector<SMD::Face> asTriangles;
/** Array of bones found in the file
*/
std::vector<SMD::Bone> asBones;
/** Smallest frame index found in the skeleton
*/
int iSmallestFrame;
/** Length of the whole animation, in frames
*/
double dLengthOfAnim;
/** Do we have texture coordinates?
*/
bool bHasUVs;
/** Current line numer
*/
unsigned int iLineNumber;
};
}; // end of namespace Assimp
#endif // AI_SMDIMPORTER_H_INC
+8 -4
View File
@@ -54,8 +54,8 @@ namespace Assimp
class SplitLargeMeshesProcess_Triangle;
class SplitLargeMeshesProcess_Vertex;
// NOTE: If you change these limits, don't forget to also change the
// corresponding values in the Assimp ports
// NOTE: If you change these limits, don't forget to change the
// corresponding values in all Assimp ports
// **********************************************************
// Java: PostProcessStep.java,
@@ -64,10 +64,14 @@ class SplitLargeMeshesProcess_Vertex;
// **********************************************************
// default limit for vertices
#define AI_SLM_DEFAULT_MAX_VERTICES 1000000
#if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
#endif
// default limit for triangles
#define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
#if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
#endif
// ---------------------------------------------------------------------------
/** Postprocessing filter to split large meshes into submeshes
+65 -42
View File
@@ -55,8 +55,7 @@ namespace Assimp
void TextureTransform::PreProcessUVTransform(
Dot3DS::Texture& rcIn)
{
std::string s;
std::stringstream ss;
char szTemp[512];
int iField;
if (rcIn.mOffsetU)
@@ -66,10 +65,10 @@ void TextureTransform::PreProcessUVTransform(
if (aiTextureMapMode_Wrap == rcIn.mMapMode)
{
float fNew = rcIn.mOffsetU-(float)iField;
ss << "[wrap] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
"This can be optimized to " << fNew;
ss >> s;
DefaultLogger::get()->info(s);
sprintf(szTemp,"[wrap] Found texture coordinate U offset %f. "
"This can be optimized to %f",rcIn.mOffsetU,fNew);
DefaultLogger::get()->info(szTemp);
rcIn.mOffsetU = fNew;
}
else if (aiTextureMapMode_Mirror == rcIn.mMapMode)
@@ -77,18 +76,18 @@ void TextureTransform::PreProcessUVTransform(
if (0 != (iField % 2))iField--;
float fNew = rcIn.mOffsetU-(float)iField;
ss << "[mirror] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
"This can be optimized to " << fNew;
ss >> s;
DefaultLogger::get()->info(s);
sprintf(szTemp,"[mirror] Found texture coordinate U offset %f. "
"This can be optimized to %f",rcIn.mOffsetU,fNew);
DefaultLogger::get()->info(szTemp);
rcIn.mOffsetU = fNew;
}
else if (aiTextureMapMode_Clamp == rcIn.mMapMode)
{
ss << "[clamp] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
"This can be clamped to 1.0f";
ss >> s;
DefaultLogger::get()->info(s);
sprintf(szTemp,"[clamp] Found texture coordinate U offset %f. "
"This can be clamped to 1.0f",rcIn.mOffsetU);
DefaultLogger::get()->info(szTemp);
rcIn.mOffsetU = 1.0f;
}
}
@@ -100,10 +99,10 @@ void TextureTransform::PreProcessUVTransform(
if (aiTextureMapMode_Wrap == rcIn.mMapMode)
{
float fNew = rcIn.mOffsetV-(float)iField;
ss << "[wrap] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
"This can be optimized to " << fNew;
ss >> s;
DefaultLogger::get()->info(s);
sprintf(szTemp,"[wrap] Found texture coordinate V offset %f. "
"This can be optimized to %f",rcIn.mOffsetV,fNew);
DefaultLogger::get()->info(szTemp);
rcIn.mOffsetV = fNew;
}
else if (aiTextureMapMode_Mirror == rcIn.mMapMode)
@@ -111,18 +110,18 @@ void TextureTransform::PreProcessUVTransform(
if (0 != (iField % 2))iField--;
float fNew = rcIn.mOffsetV-(float)iField;
ss << "[mirror] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
"This can be optimized to " << fNew;
ss >> s;
DefaultLogger::get()->info(s);
sprintf(szTemp,"[mirror] Found texture coordinate V offset %f. "
"This can be optimized to %f",rcIn.mOffsetV,fNew);
DefaultLogger::get()->info(szTemp);
rcIn.mOffsetV = fNew;
}
else if (aiTextureMapMode_Clamp == rcIn.mMapMode)
{
ss << "[clamp] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
"This can be clamped to 1.0f";
ss >> s;
DefaultLogger::get()->info(s);
sprintf(szTemp,"[clamp] Found texture coordinate U offset %f. "
"This can be clamped to 1.0f",rcIn.mOffsetV);
DefaultLogger::get()->info(szTemp);
rcIn.mOffsetV = 1.0f;
}
}
@@ -132,9 +131,11 @@ void TextureTransform::PreProcessUVTransform(
if (iField = (int)(rcIn.mRotation / 3.141592654f))
{
float fNew = rcIn.mRotation-(float)iField*3.141592654f;
ss << "[wrap] Found texture coordinate rotation " << rcIn.mRotation << ". "
"This can be optimized to " << fNew;
DefaultLogger::get()->info(s);
sprintf(szTemp,"[wrap] Found texture coordinate rotation %f. "
"This can be optimized to %f",rcIn.mRotation,fNew);
DefaultLogger::get()->info(szTemp);
rcIn.mRotation = fNew;
}
}
@@ -300,10 +301,16 @@ void TextureTransform::BakeScaleNOffset(
// it is more efficient this way ...
if (!pcMesh->mTextureCoords[0])return;
if (1 == pcSrc->iBakeUVTransform)
if (0x1 == pcSrc->iBakeUVTransform)
{
char szTemp[512];
sprintf(szTemp,"Transforming existing UV channel. Source UV: %i"
int iLen;
#if _MSC_VER >= 1400
iLen = ::sprintf_s(szTemp,
#else
iLen = ::sprintf(szTemp,
#endif
"Transforming existing UV channel. Source UV: %i"
" OffsetU: %f"
" OffsetV: %f"
" ScaleU: %f"
@@ -314,7 +321,9 @@ void TextureTransform::BakeScaleNOffset(
pcSrc->pcSingleTexture->mScaleU,
pcSrc->pcSingleTexture->mScaleV,
pcSrc->pcSingleTexture->mRotation);
DefaultLogger::get()->info(std::string(szTemp));
ai_assert(0 < iLen);
DefaultLogger::get()->info(std::string(szTemp,iLen));
if (!pcSrc->pcSingleTexture->mRotation)
{
@@ -349,7 +358,7 @@ void TextureTransform::BakeScaleNOffset(
}
}
}
else if (2 == pcSrc->iBakeUVTransform)
else if (0x2 == pcSrc->iBakeUVTransform)
{
// first save all texture coordinate sets
aiVector3D* apvOriginalSets[AI_MAX_NUMBER_OF_TEXTURECOORDS];
@@ -367,13 +376,14 @@ void TextureTransform::BakeScaleNOffset(
// now we need to find all textures in the material
// which require scaling/offset operations
std::vector<STransformVecInfo> sOps;
AddToList(sOps,&pcSrc->sTexDiffuse);
AddToList(sOps,&pcSrc->sTexSpecular);
AddToList(sOps,&pcSrc->sTexEmissive);
AddToList(sOps,&pcSrc->sTexOpacity);
AddToList(sOps,&pcSrc->sTexBump);
AddToList(sOps,&pcSrc->sTexShininess);
AddToList(sOps,&pcSrc->sTexAmbient);
sOps.reserve(10);
TextureTransform::AddToList(sOps,&pcSrc->sTexDiffuse);
TextureTransform::AddToList(sOps,&pcSrc->sTexSpecular);
TextureTransform::AddToList(sOps,&pcSrc->sTexEmissive);
TextureTransform::AddToList(sOps,&pcSrc->sTexOpacity);
TextureTransform::AddToList(sOps,&pcSrc->sTexBump);
TextureTransform::AddToList(sOps,&pcSrc->sTexShininess);
TextureTransform::AddToList(sOps,&pcSrc->sTexAmbient);
// check the list and find out how many we won't be able
// to generate.
@@ -446,7 +456,13 @@ void TextureTransform::BakeScaleNOffset(
pcMesh->mTextureCoords[iNum] = _pvOut;
char szTemp[512];
sprintf(szTemp,"Generating additional UV channel. Source UV: %i"
int iLen;
#if _MSC_VER >= 1400
iLen = ::sprintf_s(szTemp,
#else
iLen = ::sprintf(szTemp,
#endif
"Generating additional UV channel. Source UV: %i"
" OffsetU: %f"
" OffsetV: %f"
" ScaleU: %f"
@@ -457,7 +473,8 @@ void TextureTransform::BakeScaleNOffset(
(**i).fScaleU,
(**i).fScaleV,
(**i).fRotation);
DefaultLogger::get()->info(std::string(szTemp));
ai_assert(0 < iLen);
DefaultLogger::get()->info(std::string(szTemp,iLen));
const aiVector3D* pvBase = _pvBase;
aiVector3D* pvOut = _pvOut;
@@ -516,6 +533,12 @@ void TextureTransform::BakeScaleNOffset(
if (apvOriginalSets[iNum])delete[] apvOriginalSets[iNum];
}
}
// setup bitflags to indicate which texture coordinate
// channels are used (this class works for 2d texture coordinates only)
unsigned int iIndex = 0;
while (pcMesh->HasTextureCoords(iIndex))pcMesh->mNumUVComponents[iIndex++] = 2;
return;
}
// ------------------------------------------------------------------------------------------------
+61 -2
View File
@@ -342,6 +342,8 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
void ValidateDSProcess::Validate( const aiMesh* pMesh,
const aiBone* pBone)
{
this->Validate(&pBone->mName);
// check whether all vertices affected by this bone are valid
for (unsigned int i = 0; i < pBone->mNumWeights;++i)
{
@@ -359,6 +361,8 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh,
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
{
this->Validate(&pAnimation->mName);
// validate all materials
if (pAnimation->mNumBones)
{
@@ -480,7 +484,7 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
// check whether there are material keys that are obviously not legal
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
{
aiMaterialProperty* prop = pMaterial->mProperties[i];
const aiMaterialProperty* prop = pMaterial->mProperties[i];
if (!prop)
{
this->ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)",
@@ -491,9 +495,39 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
this->ReportError("aiMaterial::mProperties[%i].mDataLength or "
"aiMaterial::mProperties[%i].mData is 0",i,i);
}
// check all predefined types
if (aiPTI_String == prop->mType)
{
if (prop->mDataLength < sizeof(aiString))
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain a string (%i, needed: %i)",
i,prop->mDataLength,sizeof(aiString));
}
this->Validate((const aiString*)prop->mData);
}
else if (aiPTI_Float == prop->mType)
{
if (prop->mDataLength < sizeof(float))
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain a float (%i, needed: %i)",
i,prop->mDataLength,sizeof(float));
}
}
else if (aiPTI_Integer == prop->mType)
{
if (prop->mDataLength < sizeof(int))
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain an integer (%i, needed: %i)",
i,prop->mDataLength,sizeof(int));
}
}
// TODO: check whether there is a key with an unknown name ...
}
// make some more specific tests
float fTemp;
int iShading;
if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading))
@@ -518,7 +552,6 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
};
}
// check whether there are invalid texture keys
SearchForInvalidTextures(pMaterial,"diffuse");
SearchForInvalidTextures(pMaterial,"specular");
@@ -563,6 +596,8 @@ void ValidateDSProcess::Validate( const aiTexture* pTexture)
void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
const aiBoneAnim* pBoneAnim)
{
this->Validate(&pBoneAnim->mBoneName);
// check whether there is a bone with this name ...
unsigned int i = 0;
for (; i < this->mScene->mNumMeshes;++i)
@@ -649,6 +684,8 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
if (pNode != this->mScene->mRootNode && !pNode->mParent)
this->ReportError("A node has no valid parent (aiNode::mParent is NULL)");
this->Validate(&pNode->mName);
// validate all meshes
if (pNode->mNumMeshes)
{
@@ -687,3 +724,25 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
}
}
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiString* pString)
{
if (pString->length > MAXLEN)
{
this->ReportError("aiString::length is too large (%i, maximum is %i)",
pString->length,MAXLEN);
}
const char* sz = pString->data;
while (true)
{
if ('\0' == *sz)
{
if (pString->length != (unsigned int)(sz-pString->data))
this->ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
break;
}
else if (sz >= &pString->data[MAXLEN])
this->ReportError("aiString::data is invalid. There is no terminal character");
++sz;
}
}
+7
View File
@@ -53,6 +53,7 @@ struct aiBoneAnim;
struct aiTexture;
struct aiMaterial;
struct aiNode;
struct aiString;
namespace Assimp
{
@@ -158,6 +159,12 @@ protected:
*/
void Validate( const aiNode* pNode);
// -------------------------------------------------------------------
/** Validates a string
* @param pString Input string
*/
void Validate( const aiString* pString);
private:
aiScene* mScene;
+115 -101
View File
@@ -579,174 +579,188 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
// texture, if there is one
if (1 == oldMat.mTextures.size())
{
if (oldMat.mTextures[0].length())
{
// if there is only one texture, assume it contains the
// diffuse color
aiString tex;
tex.Set( oldMat.mTextures[0]);
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
// if there is only one texture assume it contains the diffuse color
aiString tex;
tex.Set( oldMat.mTextures[0]);
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
}
}
else
{
{
// Otherwise ... try to search for typical strings in the
// texture's file name like 'bump' or 'diffuse'
unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0;
for( unsigned int b = 0; b < oldMat.mTextures.size(); b++)
{
{
std::string sz = oldMat.mTextures[b];
if (!sz.length())continue;
char key[256];
// find the file name
const size_t iLen = sz.length();
std::string::size_type s = sz.rfind('\\',iLen-1);
if (std::string::npos == s)
{
{
s = sz.rfind('/',iLen-1);
if (std::string::npos == s)s = 0;
}
}
// cut off the file extension
std::string::size_type sExt = sz.rfind('.',iLen-1);
if (std::string::npos != sExt)
{
{
sz[sExt] = '\0';
}
}
// bump map
std::string::size_type s2 = sz.find("bump",s);
if (std::string::npos == s2)
{
if (std::string::npos == (s2 = sz.find("BUMP",s)))
{
s2 = sz.find("BUMP",s);
if (std::string::npos == s2)
if (std::string::npos == (s2 = sz.find("Bump",s)))
{
s2 = sz.find("Bump",s);
if (std::string::npos == s2)
if (std::string::npos == (s2 = sz.find("height",s)))
{
s2 = sz.find("height",s);
if (std::string::npos == s2)
if (std::string::npos == (s2 = sz.find("HEIGHT",s)))
{
s2 = sz.find("HEIGHT",s);
if (std::string::npos == s2)
{
s2 = sz.find("Height",s);
}
}
}
}
}
}
if (std::string::npos != s2)
{
sprintf(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++);
}
{
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++);
#endif
}
else
{
{
// Normal map
std::string::size_type s2 = sz.find("normal",s);
if (std::string::npos == s2)
{
if (std::string::npos == (s2 = sz.find("NORMAL",s)))
{
s2 = sz.find("NORMAL",s);
if (std::string::npos == s2)
{
s2 = sz.find("nm",s); // not really unique
if (std::string::npos == s2)
if (std::string::npos == (s2 = sz.find("nm",s)))
{
if (std::string::npos == (s2 = sz.find("Normal",s)))
{
s2 = sz.find("Normal",s);
if (std::string::npos == s2)
{
s2 = sz.find("NM",s);
}
}
}
}
}
if (std::string::npos != s2)
{
sprintf(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
}
{
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
#endif
}
else
{
{
// specular color texture (not unique, too. Could
// also be the material's shininess)
std::string::size_type s2 = sz.find("spec",s);
if (std::string::npos == s2)
{
if (std::string::npos == (s2 = sz.find("Spec",s)))
{
s2 = sz.find("Spec",s);
if (std::string::npos == s2)
if (std::string::npos == (sz.find("SPEC",s)))
{
s2 = sz.find("SPEC",s);
if (std::string::npos == s2)
if (std::string::npos == (s2 = sz.find("Glanz",s)))
{
s2 = sz.find("Glanz",s);
if (std::string::npos == s2)
{
s2 = sz.find("glanz",s);
}
}
}
}
if (std::string::npos != s2)
{
sprintf(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
}
else
{
// ambient color texture
std::string::size_type s2 = sz.find("ambi",s);
if (std::string::npos == s2)
{
s2 = sz.find("AMBI",s);
if (std::string::npos == s2)
{
s2 = sz.find("umgebungsfarbe",s);
if (std::string::npos == s2)
{
s2 = sz.find("Ambi",s);
}
}
}
if (std::string::npos != s2)
{
sprintf(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
}
else
{
// emissive color texture
std::string::size_type s2 = sz.find("emissive",s);
if (std::string::npos == s2)
{
s2 = sz.find("EMISSIVE",s);
if (std::string::npos == s2)
{
// self illumination
s2 = sz.find("self",s);
if (std::string::npos == s2)
{
s2 = sz.find("Emissive",s);
}
}
}
if (std::string::npos != s2)
{
sprintf(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
}
else
{
// assume it is a diffuse texture
sprintf(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
}
}
}
}
if (std::string::npos != s2)
{
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
#endif
}
else
{
// ambient color texture
std::string::size_type s2 = sz.find("ambi",s);
if (std::string::npos == s2)
{
if (std::string::npos == (s2 = sz.find("AMBI",s)))
{
if (std::string::npos == (s2 = sz.find("env",s)))
{
s2 = sz.find("Ambi",s);
}
}
}
if (std::string::npos != s2)
{
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
#endif
}
else
{
// emissive color texture
std::string::size_type s2 = sz.find("emissive",s);
if (std::string::npos == s2)
{
s2 = sz.find("EMISSIVE",s);
if (std::string::npos == s2)
{
// self illumination
if (std::string::npos == (s2 = sz.find("self",s)))
{
s2 = sz.find("Emissive",s);
}
}
}
if (std::string::npos != s2)
{
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
#endif
}
else
{
// assume it is a diffuse texture
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
#endif
}
}
}
}
}
aiString tex;
tex.Set( oldMat.mTextures[b] );
mat->AddProperty( &tex, key);
}
}
}
pScene->mMaterials[pScene->mNumMaterials] = mat;
mImportedMats[oldMat.mName] = pScene->mNumMaterials;
pScene->mNumMaterials++;
+15 -8
View File
@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "XFileHelper.h"
#include "BaseImporter.h"
#include "fast_atof.h"
#include "../include/DefaultLogger.h"
#include <boost/format.hpp>
@@ -150,11 +151,11 @@ void XFileParser::ParseFile()
if( objectName == "}")
{
// whatever?
// os::Printer::log("} found in dataObject", ELL_WARNING);
DefaultLogger::get()->warn("} found in dataObject");
} else
{
// unknown format
//os::Printer::log("Unknown data object in animation of .x file", objectName.c_str(), ELL_WARNING);
DefaultLogger::get()->warn("Unknown data object in animation of .x file");
ParseUnknownDataObject();
}
}
@@ -248,7 +249,7 @@ void XFileParser::ParseDataObjectFrame( Node* pParent)
ParseDataObjectMesh( mesh);
} else
{
// os::Printer::log("Unknown data object in frame in x file", objectName.c_str(), ELL_WARNING);
DefaultLogger::get()->warn("Unknown data object in frame in x file");
ParseUnknownDataObject();
}
}
@@ -338,7 +339,7 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh)
ParseDataObjectSkinWeights( pMesh);
else
{
//os::Printer::log("Unknown data object in mesh in x file", objectName.c_str(), ELL_WARNING);
DefaultLogger::get()->warn("Unknown data object in mesh in x file");
ParseUnknownDataObject();
}
}
@@ -533,7 +534,7 @@ void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh)
// ignore
} else
{
// os::Printer::log("Unknown data object in material list in x file", objectName.c_str(), ELL_WARNING);
DefaultLogger::get()->warn("Unknown data object in material list in x file");
ParseUnknownDataObject();
}
}
@@ -571,7 +572,7 @@ void XFileParser::ParseDataObjectMaterial( Material* pMaterial)
pMaterial->mTextures.push_back( texname);
} else
{
// os::Printer::log("Unknown data object in material in .x file", objectName.c_str(), ELL_WARNING);
DefaultLogger::get()->warn("Unknown data object in material in x file");
ParseUnknownDataObject();
}
}
@@ -608,7 +609,7 @@ void XFileParser::ParseDataObjectAnimationSet()
ParseDataObjectAnimation( anim);
else
{
// os::Printer::log("Unknown data object in animation set in x file", objectName.c_str(), ELL_WARNING);
DefaultLogger::get()->warn("Unknown data object in animation set in x file");
ParseUnknownDataObject();
}
}
@@ -644,7 +645,7 @@ void XFileParser::ParseDataObjectAnimation( Animation* pAnim)
CheckForClosingBrace();
} else
{
//os::Printer::log("Unknown data object in animation in x file", objectName.c_str(), ELL_WARNING);
DefaultLogger::get()->warn("Unknown data object in animation in x file");
ParseUnknownDataObject();
}
}
@@ -748,6 +749,12 @@ void XFileParser::ParseDataObjectTextureFilename( std::string& pName)
readHeadOfDataObject();
GetNextTokenAsString( pName);
CheckForClosingBrace();
// FIX: some files (e.g. AnimationTest.x) have "" as texture file name
if (!pName.length())
{
DefaultLogger::get()->warn("Length of texture file name is zero. Skipping this texture.");
}
}
// ------------------------------------------------------------------------------------------------
+4 -5
View File
@@ -49,17 +49,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::MakeVerboseFormatProcess()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
{
// nothing to do here
}
// -------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void MakeVerboseFormatProcess::Execute( aiScene* pScene)
{
@@ -76,8 +76,7 @@ void MakeVerboseFormatProcess::Execute( aiScene* pScene)
else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do.");
}
// -------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
{
-8
View File
@@ -1,8 +0,0 @@
javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Importer"
javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Material"
javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Node"
javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Scene"
javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Mesh"
javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Texture"
javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Animation"
javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.PostProcessStep"
-720
View File
@@ -1,720 +0,0 @@
/*
---------------------------------------------------------------------------
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 JNI API for jAssimp */
#if (defined ASSIMP_JNI_EXPORT)
// include the header files generated by javah
#include "assimp_Importer.h"
#include "assimp_Animation.h"
#include "assimp_Node.h"
#include "assimp_Texture.h"
#include "assimp_Mesh.h"
#include "assimp_Material.h"
// include assimp
#include "../../include/aiTypes.h"
#include "../../include/aiMesh.h"
#include "../../include/aiAnim.h"
#include "../../include/aiScene.h"
#include "../../include/aiAssert.h"
#include "../../include/aiPostProcess.h"
#include "../../include/assimp.hpp"
#include "../../include/DefaultLogger.h"
#include "JNIEnvironment.h"
#include "JNILogger.h"
using namespace Assimp;
#include <list>
namespace Assimp {
namespace JNIBridge {
// used as error return code
#define AI_JNI_ERROR_RETURN 0xffffffff
// typedef for a jassimp context, used to uniquely identify
// the Importer object which belongs to a java Importer
typedef uint64_t JASSIMP_CONTEXT;
#if (defined _DEBUG)
typedef std::list< JASSIMP_CONTEXT > ImporterContextList;
static ImporterContextList g_listActiveContexts;
// ------------------------------------------------------------------------------------------------
/* Used in debug builds to validate a context
*/
bool jValidateContext (JASSIMP_CONTEXT context)
{
for (ImporterContextList::const_iterator
i = g_listActiveContexts.begin();
i != g_listActiveContexts.end();++i)
{
if (context == *i)return true;
}
DefaultLogger::get()->error("[jnibridge] Invalid context");
return false;
}
// ------------------------------------------------------------------------------------------------
/* Used in debug builds to validate a given scene
*/
bool jValidateScene (const aiScene* scene)
{
if (!scene)
{
DefaultLogger::get()->error("[jnibridge] No asset loaded at the moment");
return false;
}
return true;
}
#endif // ! ASSIMP_DEBUG
// ------------------------------------------------------------------------------------------------
/* Used in debug builds to validate a given scene
*/
Assimp::Importer* jGetValidImporterScenePair (JASSIMP_CONTEXT jvmcontext)
{
#if (defined _DEBUG)
if (!jValidateContext((JASSIMP_CONTEXT)jvmcontext))return NULL;
#endif // ! ASSIMP_DEBUG
// get the importer instance from the context
Assimp::Importer* pcImp = (Assimp::Importer*)jvmcontext;
#if (defined _DEBUG)
if (!jValidateScene(pcImp->GetScene()))return NULL;
#endif // ! ASSIMP_DEBUG
return pcImp;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Importer
* Method: _NativeInitContext
* Signature: ()I
*/
JNIEXPORT jlong JNICALL Java_assimp_Importer__1NativeInitContext
(JNIEnv * jvmenv, jobject jvmthis)
{
// 2^64-1 indicates error
JASSIMP_CONTEXT context = 0xffffffffffffffffL;
// create a new Importer instance
Assimp::Importer* pcImp = new Assimp::Importer();
context = (JASSIMP_CONTEXT)(uintptr_t)pcImp;
#if (defined _DEBUG)
g_listActiveContexts.push_back(context);
#endif // ! ASSIMP_DEBUG
// need to setup the logger
JNILogDispatcher* pcLogger;
if (DefaultLogger::isNullLogger())
{
pcLogger = new JNILogDispatcher();
DefaultLogger::set (pcLogger);
}
else
{
JNILogDispatcher* pcLogger = ( JNILogDispatcher* )DefaultLogger::get();
pcLogger->AddRef();
}
// setup the JNI environment ...
// simply setup the newest JNIEnv*
JNIEnvironment::Get()->AttachToCurrentThread(jvmenv);
return context;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Importer
* Method: _NativeFreeContext
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeFreeContext
(JNIEnv * jvmenv, jobject jvmthis, jlong jvmcontext)
{
#if (defined _DEBUG)
if (!jValidateContext((JASSIMP_CONTEXT)jvmcontext))return AI_JNI_ERROR_RETURN;
#endif // ! ASSIMP_DEBUG
// delete the Importer instance
Assimp::Importer* pcImp = (Assimp::Importer*)jvmcontext;
delete pcImp;
#if (defined _DEBUG)
g_listActiveContexts.remove(jvmcontext);
#endif // ! ASSIMP_DEBUG
JNIEnvironment::Get()->DetachFromCurrentThread();
return 0;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Importer
* Method: _NativeLoad
* Signature: (Ljava/lang/String;II)I
*/
JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad
(JNIEnv *jvmenv, jobject jvmthis, jstring jvmpath, jint jvmflags, jlong jvmcontext)
{
jint iRet = 0;
#if (defined _DEBUG)
if (!jValidateContext((JASSIMP_CONTEXT)jvmcontext))return AI_JNI_ERROR_RETURN;
#endif // ! ASSIMP_DEBUG
// get the path from the jstring
const char* szPath = JNU_GetStringNativeChars(jvmenv,jvmpath);
if (!szPath)
{
DefaultLogger::get()->error("[jnibridge] Unable to get path string from the java vm");
return AI_JNI_ERROR_RETURN;
}
// get the importer instance from the context
Assimp::Importer* pcImp = (Assimp::Importer*)jvmcontext;
// and load the file. The aiScene object itself remains accessible
// via Importer.GetScene().
if(NULL == pcImp->ReadFile(std::string(szPath),(unsigned int)jvmflags))
{
DefaultLogger::get()->error("[jnibridge] Unable to load asset");
// release the path again
free((void*)szPath);
return AI_JNI_ERROR_RETURN;
}
// release the path again
free((void*)szPath);
return iRet;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_PostProcessStep
* Method: _NativeSetVertexSplitLimit
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_assimp_PostProcessStep__1NativeSetVertexSplitLimit
(JNIEnv *jvmenv, jclass jvmthis, jint jvmlimit)
{
aiSetVertexSplitLimit(jvmlimit);
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_PostProcessStep
* Method: _NativeSetTriangleSplitLimit
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_assimp_PostProcessStep__1NativeSetTriangleSplitLimit
(JNIEnv *jvmenv, jclass jvmthis, jint jvmlimit)
{
aiSetTriangleSplitLimit(jvmlimit);
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Scene
* Method: _NativeGetNumMeshes
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMeshes
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
return (jint)pcImp->GetScene()->mNumMeshes;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Scene
* Method: _NativeGetNumAnimations
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumAnimations
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
return (jint)pcImp->GetScene()->mNumAnimations;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Scene
* Method: _NativeGetNumTextures
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumTextures
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
return (jint)pcImp->GetScene()->mNumTextures;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Scene
* Method: _NativeGetNumMaterials
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMaterials
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
return (jint)pcImp->GetScene()->mNumMaterials;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeGetPresenceFlags
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetPresenceFlags
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
aiMesh* pcMesh = pcImp->GetScene()->mMeshes[jvmindex];
// now build the flag list
jint iRet = 0;
if (pcMesh->HasPositions())
iRet |= assimp_Mesh_PF_POSITION;
if (pcMesh->HasBones())
iRet |= assimp_Mesh_PF_BONES;
if (pcMesh->HasNormals())
iRet |= assimp_Mesh_PF_NORMAL;
if (pcMesh->HasTangentsAndBitangents())
iRet |= assimp_Mesh_PF_TANGENTBITANGENT;
unsigned int i = 0;
while (pcMesh->HasTextureCoords(i))
iRet |= assimp_Mesh_PF_UVCOORD << i++;
i = 0;
while (pcMesh->HasVertexColors(i))
iRet |= assimp_Mesh_PF_VERTEXCOLOR << i++;
return iRet;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeGetNumVertices
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumVertices
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
return pcImp->GetScene()->mMeshes[jvmindex]->mNumVertices;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeGetNumFaces
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumFaces
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
return pcImp->GetScene()->mMeshes[jvmindex]->mNumFaces;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeGetNumBones
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumBones
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
return pcImp->GetScene()->mMeshes[jvmindex]->mNumBones;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeGetMaterialIndex
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetMaterialIndex
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
return pcImp->GetScene()->mMeshes[jvmindex]->mMaterialIndex;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeGetNumUVComponents
* Signature: (JJ[I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumUVComponents
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jintArray jvmout)
{
ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS == jvmenv->GetArrayLength(jvmout) );
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
const unsigned int* piArray = pcImp->GetScene()->mMeshes[jvmindex]->mNumUVComponents;
jint* pArray = jvmenv->GetIntArrayElements(jvmout,NULL);
if (NULL == pArray)return AI_JNI_ERROR_RETURN;
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
pArray[i] = piArray[i];
jvmenv->ReleaseIntArrayElements(jvmout,pArray,0);
return 0;
}
// ------------------------------------------------------------------------------------------------
void CpyVectorToFloatArray(jfloat* pDest, const aiVector3D* pSource, unsigned int iNum)
{
jfloat* pCursor = pDest;
const aiVector3D* const pvEnd = pSource + iNum;
while (pvEnd != pSource)
{
*pCursor++ = pSource->x;
*pCursor++ = pSource->y;
*pCursor++ = pSource->z;
++pSource;
}
return;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeMapVertices
* Signature: (JJ[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapVertices
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jfloatArray jvmout)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
aiMesh* pcMesh = (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices * 3);
const aiVector3D* pcData = pcMesh->mVertices;
// now copy the data to the java array
jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
// delete the original data
delete[] pcMesh->mVertices;
pcMesh->mVertices = NULL;
return 0;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeMapNormals
* Signature: (JJ[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapNormals
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jfloatArray jvmout)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
aiMesh* pcMesh = (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices * 3);
const aiVector3D* pcData = pcMesh->mNormals;
// now copy the data to the java array
jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
// delete the original data
delete[] pcMesh->mNormals;
pcMesh->mNormals = NULL;
return 0;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeMapTangents
* Signature: (JJ[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapTangents
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jfloatArray jvmout)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
aiMesh* pcMesh = (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices * 3);
const aiVector3D* pcData = pcMesh->mTangents;
// now copy the data to the java array
jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
// delete the original data
delete[] pcMesh->mNormals;
pcMesh->mNormals = NULL;
return 0;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeMapBitangents
* Signature: (JJ[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapBitangents
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jfloatArray jvmout)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
aiMesh* pcMesh = (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices * 3);
const aiVector3D* pcData = pcMesh->mBitangents;
// now copy the data to the java array
jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
// delete the original data
delete[] pcMesh->mBitangents;
pcMesh->mBitangents = NULL;
return 0;
}
// ------------------------------------------------------------------------------------------------
void CpyColorToFloatArray(jfloat* pDest, const aiColor4D* pSource, unsigned int iNum)
{
jfloat* pCursor = pDest;
const aiColor4D* const pvEnd = pSource + iNum;
while (pvEnd != pSource)
{
*pCursor++ = pSource->r;
*pCursor++ = pSource->g;
*pCursor++ = pSource->b;
*pCursor++ = pSource->a;
++pSource;
}
return;
}
// ------------------------------------------------------------------------------------------------
void CpyVectorToFloatArray(jfloat* pDest, const aiVector3D* pSource,
unsigned int iNum, unsigned int iNumComponents)
{
jfloat* pCursor = pDest;
const aiVector3D* const pvEnd = pSource + iNum;
while (pvEnd != pSource)
{
if (iNumComponents >= 1)*pCursor++ = pSource->x;
if (iNumComponents >= 2)*pCursor++ = pSource->y;
if (iNumComponents >= 3)*pCursor++ = pSource->z;
++pSource;
}
return;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeMapUVs
* Signature: (JJI[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapUVs
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex,
jint jvmchannel, jfloatArray jvmout)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
aiMesh* pcMesh = (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices*pcMesh->mNumUVComponents[jvmchannel]);
const aiVector3D* pcData = pcMesh->mTextureCoords[jvmchannel];
// now copy the data to the java array
jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices,pcMesh->mNumUVComponents[jvmchannel]);
jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
// delete the original data
delete[] pcMesh->mTextureCoords[jvmchannel];
pcMesh->mTextureCoords[jvmchannel] = NULL;
return 0;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeMapColors
* Signature: (JJI[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapColors
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex,
jint jvmchannel, jfloatArray jvmout)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
aiMesh* pcMesh = (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices*4);
const aiColor4D* pcData = pcMesh->mColors[jvmchannel];
// now copy the data to the java array
jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
CpyColorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
// delete the original data
delete[] pcMesh->mColors[jvmchannel];
pcMesh->mColors[jvmchannel] = NULL;
return 0;
}
// ------------------------------------------------------------------------------------------------
void CpyFacesToIntArray(jint* pDest, const aiFace* pSource, unsigned int iNum)
{
// assume that all faces are triangles
jint* pCursor = pDest;
const aiFace* const pvEnd = pSource + iNum;
while (pvEnd != pSource)
{
*pCursor++ = pSource->mIndices[0];
*pCursor++ = pSource->mIndices[1];
*pCursor++ = pSource->mIndices[2];
++pSource;
}
return;
}
// ------------------------------------------------------------------------------------------------
/*
* Class: assimp_Mesh
* Method: _NativeMapFaces
* Signature: (JJ[I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapFaces
(JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jintArray jvmout)
{
// we need a valid scene for this
Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
if (!pcImp)return AI_JNI_ERROR_RETURN;
// get the corresponding mesh
ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
aiMesh* pcMesh = (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumFaces*3);
const aiFace* pcData = pcMesh->mFaces;
// now copy the data to the java array
jint* pArray = jvmenv->GetIntArrayElements(jvmout,NULL);
CpyFacesToIntArray(pArray,pcData,pcMesh->mNumFaces);
jvmenv->ReleaseIntArrayElements(jvmout,pArray,0);
// delete the original data
for (unsigned int i = 0; i < pcMesh->mNumFaces;++i)
delete[] pcMesh->mFaces[i].mIndices;
delete[] pcMesh->mFaces;
pcMesh->mFaces = NULL;
return 0;
}
}; //! namespace JNIBridge
}; //! namespace Assimp
#endif // !ASSIMP_JNI_EXPORT
-188
View File
@@ -1,188 +0,0 @@
/*
---------------------------------------------------------------------------
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 JNI API for jAssimp */
#if (defined ASSIMP_JNI_EXPORT)
#include "JNIEnvironment.h"
#include "JNILogger.h"
using namespace Assimp;
namespace Assimp {
namespace JNIBridge {
/*static*/ jclass JNIEnvironment::Class_java_lang_String = 0;
/*static*/ jmethodID JNIEnvironment::MID_String_getBytes = 0;
/*static*/ jmethodID JNIEnvironment::MID_String_init = 0;
// ------------------------------------------------------------------------------------------------
bool JNIEnvironment::AttachToCurrentThread (JNIEnv* pcEnv)
{
ai_assert(NULL != pcEnv);
// first initialize some members
if (0 == Class_java_lang_String)
{
if( 0 == (Class_java_lang_String = pcEnv->FindClass("java.lang.String")))
return false;
}
if (0 == MID_String_getBytes)
{
if( 0 == (MID_String_getBytes = pcEnv->GetStaticMethodID(
Class_java_lang_String,"getBytes","()[byte")))
return false;
}
if (0 == MID_String_init)
{
if( 0 == (MID_String_init = pcEnv->GetStaticMethodID(
Class_java_lang_String,"String","([byte)V")))
return false;
}
// now initialize the thread-local storage
if (NULL == this->ptr.get())
{
// attach to the current thread
JavaVM* vm;
pcEnv->GetJavaVM(&vm);
vm->AttachCurrentThread((void **) &pcEnv, NULL);
this->ptr.reset(new JNIThreadData(pcEnv));
}
// increase the reference counter
else this->ptr->m_iNumRef++;
// attach the logger
((JNILogDispatcher*)DefaultLogger::get())->OnAttachToCurrentThread(this->ptr.get());
return true;
}
// ------------------------------------------------------------------------------------------------
bool JNIEnvironment::DetachFromCurrentThread ()
{
ai_assert(NULL != pcEnv);
// detach the logger
((JNILogDispatcher*)DefaultLogger::get())->OnDetachFromCurrentThread(this->ptr.get());
// decrease the reference counter
if (NULL != this->ptr.get())
{
this->ptr->m_iNumRef--;
if (0 == this->ptr->m_iNumRef)
{
JavaVM* vm;
this->ptr->m_pcEnv->GetJavaVM(&vm);
vm->DetachCurrentThread();
}
}
return true;
}
// ------------------------------------------------------------------------------------------------
JNIThreadData* JNIEnvironment::GetThread()
{
ai_assert(NULL != this->ptr.get());
return this->ptr.get();
}
// ------------------------------------------------------------------------------------------------
jstring JNU_NewStringNative(JNIEnv *env, const char *str)
{
jstring result;
jbyteArray bytes = 0;
int len;
if (env->EnsureLocalCapacity( 2) < 0)
{
return NULL; /* out of memory error */
}
len = strlen(str);
bytes = env->NewByteArray(len);
if (bytes != NULL)
{
env->SetByteArrayRegion(bytes, 0, len,
(jbyte *)str);
result = (jstring)env->NewObject(JNIEnvironment::Class_java_lang_String,
JNIEnvironment::MID_String_init, bytes);
env->DeleteLocalRef(bytes);
return result;
} /* else fall through */
return NULL;
}
// ------------------------------------------------------------------------------------------------
char *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr)
{
jbyteArray bytes = 0;
jthrowable exc;
char *result = 0;
if (env->EnsureLocalCapacity(2) < 0)
{
return 0; /* out of memory error */
}
bytes = (jbyteArray)env->CallObjectMethod(jstr,JNIEnvironment::MID_String_getBytes);
exc = env->ExceptionOccurred();
if (!exc)
{
jint len = env->GetArrayLength(bytes);
result = (char *)malloc(len + 1);
if (result == 0)
{
env->DeleteLocalRef(bytes);
return 0;
}
env->GetByteArrayRegion(bytes, 0, len,
(jbyte *)result);
result[len] = 0; /* NULL-terminate */
}
else
{
env->DeleteLocalRef(exc);
}
env->DeleteLocalRef(bytes);
return result;
}
};};
#endif // ! JNI only
-184
View File
@@ -1,184 +0,0 @@
/*
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.
----------------------------------------------------------------------
*/
#if (!defined AI_JNIENVIRONMENT_H_INCLUDED)
#define AI_JNIENVIRONMENT_H_INCLUDED
#include <boost/thread/thread.hpp>
#include <boost/thread/tss.hpp>
#include <vector>
#include <jni.h>
#include "../../include/aiAssert.h"
namespace Assimp {
namespace JNIBridge {
// ---------------------------------------------------------------------------
/** @class JNIThreadData
* @brief Manages a list of JNI data structures that are
* private to a thread.
*/
struct JNIThreadData
{
//! Default constructor
JNIThreadData() : m_pcEnv(NULL), m_iNumRef(1) {}
//! Construction from an existing JNIEnv
JNIThreadData(JNIEnv* env) : m_pcEnv(env), m_iNumRef(1) {}
//! JNI environment, is attached to the thread
JNIEnv* m_pcEnv;
//! Number of Importer instances that have been
//! created by this thread
unsigned int m_iNumRef;
};
// ---------------------------------------------------------------------------
/** @class JNIEnvironment
* @brief Helper class to manage the JNI environment for multithreaded
* use of the library.
*/
class JNIEnvironment
{
private:
JNIEnvironment() : m_iRefCnt(1) {}
public:
//! Create the JNI environment class
//! refcnt = 1
static JNIEnvironment* Create()
{
if (NULL == s_pcEnv)
{
s_pcEnv = new JNIEnvironment();
}
else s_pcEnv->AddRef();
return s_pcEnv;
}
//! static getter for the singleton instance
//! doesn't hange the reference counter
static JNIEnvironment* Get()
{
ai_assert(NULL != s_pcEnv);
return s_pcEnv;
}
//! COM-style reference counting mechanism
unsigned int AddRef()
{
return ++this->m_iRefCnt;
}
//! COM-style reference counting mechanism
unsigned int Release()
{
unsigned int iNew = --this->m_iRefCnt;
if (0 == iNew)delete this;
return iNew;
}
//! Attach to the current thread
bool AttachToCurrentThread (JNIEnv* pcEnv);
//! Detach from the current thread
bool DetachFromCurrentThread ();
//! Get the thread local data of the current thread
JNIThreadData* GetThread();
public:
//! Handle to the java.lang.String class
static jclass Class_java_lang_String;
//! Handle to the java.lang.String.getBytes() class
static jmethodID MID_String_getBytes;
//! Handle to the java.lang.String.String(byte[]) c'tor
static jmethodID MID_String_init;
private:
//! Singleton instance
static JNIEnvironment* s_pcEnv;
//! TLS data
boost::thread_specific_ptr<JNIThreadData> ptr;
//! Reference counter of the whole class
unsigned int m_iRefCnt;
};
};};
// ---------------------------------------------------------------------------
/** @brief Helper function to create a java.lang.String from
* a native char*.
*
* This function has been taken from
* http://java.sun.com/docs/books/jni/html/other.html#26021
* I am not sure whether it is really necessary, but I trust the source
*/
jstring JNU_NewStringNative(JNIEnv *env, const char *str);
// ---------------------------------------------------------------------------
/** @brief Helper function to create a char* from
* a managed jstring
*
* This function has been taken from
* http://java.sun.com/docs/books/jni/html/other.html#26021
* I am not sure whether it is really necessary, but I trust the source
*/
char* JNU_GetStringNativeChars(JNIEnv *env, jstring jstr);
#endif //! AI_JNIENVIRONMENT_H_INCLUDED
-166
View File
@@ -1,166 +0,0 @@
/*
---------------------------------------------------------------------------
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 JNI API for jAssimp */
#if (defined ASSIMP_JNI_EXPORT)
// include assimp
#include "../../include/aiTypes.h"
#include "../../include/aiMesh.h"
#include "../../include/aiAnim.h"
#include "../../include/aiScene.h"
#include "../../include/aiAssert.h"
#include "../../include/aiPostProcess.h"
#include "../../include/assimp.hpp"
#include "../../include/DefaultLogger.h"
#include "JNIEnvironment.h"
#include "JNILogger.h"
using namespace Assimp;
namespace Assimp {
namespace JNIBridge {
// ------------------------------------------------------------------------------------------------
bool JNILogDispatcher::OnAttachToCurrentThread(JNIThreadData* pcData)
{
ai_assert(NULL != pcData);
//this->AddRef(); - done at another position
// there is much error handling code in this function.
// However, it is not impossible that the jAssimp package
// loaded by the JVM is incomplete ...
JNIEnv* jvmenv = JNIEnvironment::Get()->GetThread()->m_pcEnv;
// get a handle to the assimp.DefaultLogger class
if (NULL == this->m_pcClass)
{
if( NULL == (this->m_pcClass = jvmenv->FindClass("assimp.DefaultLogger")))
{
return false;
}
}
// get handles to the logging functions
if (NULL == this->m_pcMethodError)
{
if( NULL == (this->m_pcMethodError = jvmenv->GetStaticMethodID(
this->m_pcClass,"_NativeCallWriteError","(Ljava/lang/String;)V")))
{
return false;
}
}
if (NULL == this->m_pcMethodWarn)
{
if( NULL == (this->m_pcMethodWarn = jvmenv->GetStaticMethodID(
this->m_pcClass,"_NativeCallWriteWarn","(Ljava/lang/String;)V")))
{
return false;
}
}
if (NULL == this->m_pcMethodInfo)
{
if( NULL == (this->m_pcMethodInfo = jvmenv->GetStaticMethodID(
this->m_pcClass,"_NativeCallWriteInfo","(Ljava/lang/String;)V")))
{
return false;
}
}
if (NULL == this->m_pcMethodDebug)
{
if( NULL == (this->m_pcMethodDebug = jvmenv->GetStaticMethodID(
this->m_pcClass,"_NativeCallWriteDebug","(Ljava/lang/String;)V")))
{
return false;
}
}
return true;
}
// ------------------------------------------------------------------------------------------------
bool JNILogDispatcher::OnDetachFromCurrentThread(JNIThreadData* pcData)
{
ai_assert(NULL != pcData);
this->Release();
return true;
}
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::debug(const std::string &message)
{
JNIEnv* jvmenv = JNIEnvironment::Get()->GetThread()->m_pcEnv;
jstring jstr = JNU_NewStringNative(jvmenv,message.c_str());
jvmenv->CallStaticVoidMethod(this->m_pcClass,this->m_pcMethodDebug,jstr);
jvmenv->DeleteLocalRef(jstr);
}
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::info(const std::string &message)
{
JNIEnv* jvmenv = JNIEnvironment::Get()->GetThread()->m_pcEnv;
jstring jstr = JNU_NewStringNative(jvmenv,message.c_str());
jvmenv->CallStaticVoidMethod(this->m_pcClass,this->m_pcMethodInfo,jstr);
jvmenv->DeleteLocalRef(jstr);
}
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::warn(const std::string &message)
{
JNIEnv* jvmenv = JNIEnvironment::Get()->GetThread()->m_pcEnv;
jstring jstr = JNU_NewStringNative(jvmenv,message.c_str());
jvmenv->CallStaticVoidMethod(this->m_pcClass,this->m_pcMethodWarn,jstr);
jvmenv->DeleteLocalRef(jstr);
}
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::error(const std::string &message)
{
JNIEnv* jvmenv = JNIEnvironment::Get()->GetThread()->m_pcEnv;
jstring jstr = JNU_NewStringNative(jvmenv,message.c_str());
jvmenv->CallStaticVoidMethod(this->m_pcClass,this->m_pcMethodError,jstr);
jvmenv->DeleteLocalRef(jstr);
}
};};
#endif // jni
-142
View File
@@ -1,142 +0,0 @@
/*
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.
----------------------------------------------------------------------
*/
#if (!defined AI_JNILOGGER_H_INCLUDED)
#define AI_JNILOGGER_H_INCLUDED
#include "../../include/Logger.h"
#include "../../include/DefaultLogger.h"
#include <vector>
#include <jni.h>
namespace Assimp {
namespace JNIBridge {
// ---------------------------------------------------------------------------
class IOStream;
struct LogStreamInfo;
// ---------------------------------------------------------------------------
/** @class JNILogDispatcher
* @brief Logging system implementation that is used to send all
* log messages generated by native code to the Java logging system.
*/
class JNILogDispatcher : public Logger
{
friend class JNIEnvironment;
public:
//! Default constructor
JNILogDispatcher() : m_iRefCnt(1) {}
/** @brief Logs a debug message */
void debug(const std::string &message);
/** @brief Logs an info message */
void info(const std::string &message);
/** @brief Logs a warning message */
void warn(const std::string &message);
/** @brief Logs an error message */
void error(const std::string &message);
/** @brief Log severity setter */
void setLogSeverity(LogSeverity log_severity) {}
/** @brief Detach a still attached stream from logger */
void attachStream(LogStream *pStream, unsigned int severity) {}
/** @brief Detach a still attached stream from logger */
void detatchStream(LogStream *pStream, unsigned int severity) {}
//! COM-style reference counting mechanism
unsigned int AddRef()
{
return ++this->m_iRefCnt;
}
//! COM-style reference counting mechanism
unsigned int Release()
{
unsigned int iNew = --this->m_iRefCnt;
if (0 == iNew)
{
delete this;
// don't forget to reset the logger to the default implementation
DefaultLogger::set(NULL);
}
return iNew;
}
private:
//! Called by JNIEnvironment
bool OnAttachToCurrentThread(JNIThreadData* pcData);
bool OnDetachFromCurrentThread(JNIThreadData* pcData);
private:
//! Handle to assimp.DefaultLogger class
jclass m_pcClass;
//! Handle to the static assimp.DefaultLogger._NativeCallWriteError() method
jmethodID m_pcMethodError;
//! Handle to the static assimp.DefaultLogger._NativeCallWriteInfo() method
jmethodID m_pcMethodInfo;
//! Handle to the static assimp.DefaultLogger._NativeCallWriteDebug() method
jmethodID m_pcMethodDebug;
//! Handle to the static assimp.DefaultLogger._NativeCallWriteWarn() method
jmethodID m_pcMethodWarn;
//! Reference counter of the logger
unsigned int m_iRefCnt;
};
};};
#endif // AI_JNILOGGER_H_INCLUDED
-13
View File
@@ -1,13 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class assimp_Animation */
#ifndef _Included_assimp_Animation
#define _Included_assimp_Animation
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
-37
View File
@@ -1,37 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class assimp_Importer */
#ifndef _Included_assimp_Importer
#define _Included_assimp_Importer
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: assimp_Importer
* Method: _NativeInitContext
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeInitContext
(JNIEnv *, jobject);
/*
* Class: assimp_Importer
* Method: _NativeFreeContext
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeFreeContext
(JNIEnv *, jobject, jlong);
/*
* Class: assimp_Importer
* Method: _NativeLoad
* Signature: (Ljava/lang/String;IJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad
(JNIEnv *, jobject, jstring, jint, jlong);
#ifdef __cplusplus
}
#endif
#endif
-13
View File
@@ -1,13 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class assimp_Material */
#ifndef _Included_assimp_Material
#define _Included_assimp_Material
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
-133
View File
@@ -1,133 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class assimp_Mesh */
#ifndef _Included_assimp_Mesh
#define _Included_assimp_Mesh
#ifdef __cplusplus
extern "C" {
#endif
#undef assimp_Mesh_MAX_NUMBER_OF_TEXTURECOORDS
#define assimp_Mesh_MAX_NUMBER_OF_TEXTURECOORDS 4L
#undef assimp_Mesh_MAX_NUMBER_OF_COLOR_SETS
#define assimp_Mesh_MAX_NUMBER_OF_COLOR_SETS 4L
#undef assimp_Mesh_PF_POSITION
#define assimp_Mesh_PF_POSITION 1L
#undef assimp_Mesh_PF_NORMAL
#define assimp_Mesh_PF_NORMAL 2L
#undef assimp_Mesh_PF_TANGENTBITANGENT
#define assimp_Mesh_PF_TANGENTBITANGENT 4L
#undef assimp_Mesh_PF_BONES
#define assimp_Mesh_PF_BONES 8L
#undef assimp_Mesh_PF_VERTEXCOLOR
#define assimp_Mesh_PF_VERTEXCOLOR 4096L
#undef assimp_Mesh_PF_UVCOORD
#define assimp_Mesh_PF_UVCOORD 65536L
/*
* Class: assimp_Mesh
* Method: _NativeGetPresenceFlags
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetPresenceFlags
(JNIEnv *, jobject, jlong, jlong);
/*
* Class: assimp_Mesh
* Method: _NativeGetNumVertices
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumVertices
(JNIEnv *, jobject, jlong, jlong);
/*
* Class: assimp_Mesh
* Method: _NativeGetNumFaces
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumFaces
(JNIEnv *, jobject, jlong, jlong);
/*
* Class: assimp_Mesh
* Method: _NativeGetNumBones
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumBones
(JNIEnv *, jobject, jlong, jlong);
/*
* Class: assimp_Mesh
* Method: _NativeGetMaterialIndex
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetMaterialIndex
(JNIEnv *, jobject, jlong, jlong);
/*
* Class: assimp_Mesh
* Method: _NativeGetNumUVComponents
* Signature: (JJ[I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumUVComponents
(JNIEnv *, jobject, jlong, jlong, jintArray);
/*
* Class: assimp_Mesh
* Method: _NativeMapVertices
* Signature: (JJ[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapVertices
(JNIEnv *, jobject, jlong, jlong, jfloatArray);
/*
* Class: assimp_Mesh
* Method: _NativeMapNormals
* Signature: (JJ[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapNormals
(JNIEnv *, jobject, jlong, jlong, jfloatArray);
/*
* Class: assimp_Mesh
* Method: _NativeMapTangents
* Signature: (JJ[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapTangents
(JNIEnv *, jobject, jlong, jlong, jfloatArray);
/*
* Class: assimp_Mesh
* Method: _NativeMapBitangents
* Signature: (JJ[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapBitangents
(JNIEnv *, jobject, jlong, jlong, jfloatArray);
/*
* Class: assimp_Mesh
* Method: _NativeMapUVs
* Signature: (JJI[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapUVs
(JNIEnv *, jobject, jlong, jlong, jint, jfloatArray);
/*
* Class: assimp_Mesh
* Method: _NativeMapColors
* Signature: (JJI[F)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapColors
(JNIEnv *, jobject, jlong, jlong, jint, jfloatArray);
/*
* Class: assimp_Mesh
* Method: _NativeMapFaces
* Signature: (JJ[I)I
*/
JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapFaces
(JNIEnv *, jobject, jlong, jlong, jintArray);
#ifdef __cplusplus
}
#endif
#endif
-13
View File
@@ -1,13 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class assimp_Node */
#ifndef _Included_assimp_Node
#define _Included_assimp_Node
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
-33
View File
@@ -1,33 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class assimp_PostProcessStep */
#ifndef _Included_assimp_PostProcessStep
#define _Included_assimp_PostProcessStep
#ifdef __cplusplus
extern "C" {
#endif
#undef assimp_PostProcessStep_DEFAULT_VERTEX_SPLIT_LIMIT
#define assimp_PostProcessStep_DEFAULT_VERTEX_SPLIT_LIMIT 1000000L
#undef assimp_PostProcessStep_DEFAULT_TRIANGLE_SPLIT_LIMIT
#define assimp_PostProcessStep_DEFAULT_TRIANGLE_SPLIT_LIMIT 1000000L
/*
* Class: assimp_PostProcessStep
* Method: _NativeSetVertexSplitLimit
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_assimp_PostProcessStep__1NativeSetVertexSplitLimit
(JNIEnv *, jclass, jint);
/*
* Class: assimp_PostProcessStep
* Method: _NativeSetTriangleSplitLimit
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_assimp_PostProcessStep__1NativeSetTriangleSplitLimit
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
-45
View File
@@ -1,45 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class assimp_Scene */
#ifndef _Included_assimp_Scene
#define _Included_assimp_Scene
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: assimp_Scene
* Method: _NativeGetNumMeshes
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMeshes
(JNIEnv *, jobject, jlong);
/*
* Class: assimp_Scene
* Method: _NativeGetNumAnimations
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumAnimations
(JNIEnv *, jobject, jlong);
/*
* Class: assimp_Scene
* Method: _NativeGetNumTextures
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumTextures
(JNIEnv *, jobject, jlong);
/*
* Class: assimp_Scene
* Method: _NativeGetNumMaterials
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMaterials
(JNIEnv *, jobject, jlong);
#ifdef __cplusplus
}
#endif
#endif
-29
View File
@@ -1,29 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class assimp_Texture */
#ifndef _Included_assimp_Texture
#define _Included_assimp_Texture
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: assimp_Texture
* Method: _NativeMapColorData
* Signature: (JJ[B)I
*/
JNIEXPORT jint JNICALL Java_assimp_Texture__1NativeMapColorData
(JNIEnv *, jobject, jlong, jlong, jbyteArray);
/*
* Class: assimp_Texture
* Method: _NativeGetTextureInfo
* Signature: (JJ)J
*/
JNIEXPORT jlong JNICALL Java_assimp_Texture__1NativeGetTextureInfo
(JNIEnv *, jobject, jlong, jlong);
#ifdef __cplusplus
}
#endif
#endif
+42
View File
@@ -0,0 +1,42 @@
#if (!defined AI_QNAN_H_INCLUDED)
#define AI_QNAN_H_INCLUDED
#if (!defined ASSIMP_BUILD_CPP_09)
# include <boost/static_assert.hpp>
#endif
inline bool is_qnan(const float in)
{
// _isnan() takes a double as argument and would
// require a cast. Therefore we must do it on our own ...
// Another method would be to check whether in != in.
// This should also wor since nan compares to inequal,
// even when compared with itself. However, this could
// case problems with other special floats like snan or inf
union _tagFPUNION
{
float f;
int32_t i;
} FPUNION1,FPUNION2;
// use a compile-time asertion if possible
#if (defined ASSIMP_BUILD_CPP_09)
static_assert(sizeof(float)==sizeof(int32_t),
"A float seems not to be 4 bytes on this platform");
#else
BOOST_STATIC_ASSERT(sizeof(float)==sizeof(int32_t));
#endif
FPUNION1.f = in;
FPUNION2.f = std::numeric_limits<float>::quiet_NaN();
return FPUNION1.i == FPUNION2.i;
}
inline bool is_not_qnan(const float in)
{
return !is_qnan(in);
}
#endif // !! AI_QNAN_H_INCLUDED