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:
+26
-23
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+293
-94
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user