summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/assimp/code/MDLLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/assimp/code/MDLLoader.cpp')
-rw-r--r--src/3rdparty/assimp/code/MDLLoader.cpp3389
1 files changed, 1708 insertions, 1681 deletions
diff --git a/src/3rdparty/assimp/code/MDLLoader.cpp b/src/3rdparty/assimp/code/MDLLoader.cpp
index ebe6caf68..ba5c4c32c 100644
--- a/src/3rdparty/assimp/code/MDLLoader.cpp
+++ b/src/3rdparty/assimp/code/MDLLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2016, assimp 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
+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
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+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
+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
+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
+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.
---------------------------------------------------------------------------
*/
@@ -45,279 +45,295 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// internal headers
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
#include "MDLLoader.h"
+#include "Macros.h"
+#include "qnan.h"
#include "MDLDefaultColorMap.h"
-#include "MD2FileData.h"
+#include "MD2FileData.h"
+#include "StringUtils.h"
+#include <assimp/Importer.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+
+#include <memory>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Quake Mesh / 3D GameStudio Mesh Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 7,
- 0,
- "mdl"
+ "Quake Mesh / 3D GameStudio Mesh Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 7,
+ 0,
+ "mdl"
};
// ------------------------------------------------------------------------------------------------
// Ugly stuff ... nevermind
-#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \
- (*((const _type*)(((const char*)_data) + _index * _limit)))
+#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \
+ (*((const _type*)(((const char*)_data) + _index * _limit)))
-#define _AI_MDL7_ACCESS_PTR(_data, _index, _limit, _type) \
- ((BE_NCONST _type*)(((const char*)_data) + _index * _limit))
+#define _AI_MDL7_ACCESS_PTR(_data, _index, _limit, _type) \
+ ((BE_NCONST _type*)(((const char*)_data) + _index * _limit))
-#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \
- _AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7)
+#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \
+ _AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7)
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MDLImporter::MDLImporter()
+ : configFrameID(),
+ mBuffer(),
+ iGSFileVersion(),
+ pIOHandler(),
+ pScene(),
+ iFileSize()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
MDLImporter::~MDLImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
-
- // if check for extension is not enough, check for the magic tokens
- if (extension == "mdl" || !extension.length() || checkSig) {
- uint32_t tokens[8];
- tokens[0] = AI_MDL_MAGIC_NUMBER_LE_HL2a;
- tokens[1] = AI_MDL_MAGIC_NUMBER_LE_HL2b;
- tokens[2] = AI_MDL_MAGIC_NUMBER_LE_GS7;
- tokens[3] = AI_MDL_MAGIC_NUMBER_LE_GS5b;
- tokens[4] = AI_MDL_MAGIC_NUMBER_LE_GS5a;
- tokens[5] = AI_MDL_MAGIC_NUMBER_LE_GS4;
- tokens[6] = AI_MDL_MAGIC_NUMBER_LE_GS3;
- tokens[7] = AI_MDL_MAGIC_NUMBER_LE;
- return CheckMagicToken(pIOHandler,pFile,tokens,8,0);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+
+ // if check for extension is not enough, check for the magic tokens
+ if (extension == "mdl" || !extension.length() || checkSig) {
+ uint32_t tokens[8];
+ tokens[0] = AI_MDL_MAGIC_NUMBER_LE_HL2a;
+ tokens[1] = AI_MDL_MAGIC_NUMBER_LE_HL2b;
+ tokens[2] = AI_MDL_MAGIC_NUMBER_LE_GS7;
+ tokens[3] = AI_MDL_MAGIC_NUMBER_LE_GS5b;
+ tokens[4] = AI_MDL_MAGIC_NUMBER_LE_GS5a;
+ tokens[5] = AI_MDL_MAGIC_NUMBER_LE_GS4;
+ tokens[6] = AI_MDL_MAGIC_NUMBER_LE_GS3;
+ tokens[7] = AI_MDL_MAGIC_NUMBER_LE;
+ return CheckMagicToken(pIOHandler,pFile,tokens,8,0);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void MDLImporter::SetupProperties(const Importer* pImp)
{
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDL_KEYFRAME,-1);
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDL_KEYFRAME,-1);
- // The
- // AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the
- // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
- if(static_cast<unsigned int>(-1) == configFrameID) {
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
- }
+ // The
+ // AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the
+ // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+ if(static_cast<unsigned int>(-1) == configFrameID) {
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+ }
- // AI_CONFIG_IMPORT_MDL_COLORMAP - pallette file
- configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp");
+ // AI_CONFIG_IMPORT_MDL_COLORMAP - pallette file
+ configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp");
}
// ------------------------------------------------------------------------------------------------
// Get a list of all supported extensions
const aiImporterDesc* MDLImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void MDLImporter::InternReadFile( const std::string& pFile,
- aiScene* _pScene, IOSystem* _pIOHandler)
+// Imports the given file into the given scene structure.
+void MDLImporter::InternReadFile( const std::string& pFile,
+ aiScene* _pScene, IOSystem* _pIOHandler)
{
- pScene = _pScene;
- pIOHandler = _pIOHandler;
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open MDL file " + pFile + ".");
- }
-
- // This should work for all other types of MDL files, too ...
- // the quake header is one of the smallest, afaik
- iFileSize = (unsigned int)file->FileSize();
- if( iFileSize < sizeof(MDL::Header)) {
- throw DeadlyImportError( "MDL File is too small.");
- }
-
- // Allocate storage and copy the contents of the file to a memory buffer
- std::vector<unsigned char> buffer(iFileSize+1);
- mBuffer = &buffer[0];
- file->Read( (void*)mBuffer, 1, iFileSize);
-
- // Append a binary zero to the end of the buffer.
- // this is just for safety that string parsing routines
- // find the end of the buffer ...
- mBuffer[iFileSize] = '\0';
- const uint32_t iMagicWord = *((uint32_t*)mBuffer);
-
- // Determine the file subtype and call the appropriate member function
-
- // Original Quake1 format
- if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
- iGSFileVersion = 0;
- InternReadFile_Quake1();
- }
- // GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
- else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
- iGSFileVersion = 2;
- InternReadFile_Quake1();
- }
- // GameStudio A4 MDL3 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
- iGSFileVersion = 3;
- InternReadFile_3DGS_MDL345();
- }
- // GameStudio A5+ MDL4 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
- iGSFileVersion = 4;
- InternReadFile_3DGS_MDL345();
- }
- // GameStudio A5+ MDL5 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
- iGSFileVersion = 5;
- InternReadFile_3DGS_MDL345();
- }
- // GameStudio A7 MDL7 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
- iGSFileVersion = 7;
- InternReadFile_3DGS_MDL7();
- }
- // IDST/IDSQ Format (CS:S/HL^2, etc ...)
- else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
- AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
- {
- DefaultLogger::get()->debug("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ");
- iGSFileVersion = 0;
- InternReadFile_HL2();
- }
- else {
- // print the magic word to the log file
- throw DeadlyImportError( "Unknown MDL subformat " + pFile +
- ". Magic word (" + std::string((char*)&iMagicWord,4) + ") is not known");
- }
-
- // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
- pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
-
- // delete the file buffer and cleanup
- AI_DEBUG_INVALIDATE_PTR(mBuffer);
- AI_DEBUG_INVALIDATE_PTR(pIOHandler);
- AI_DEBUG_INVALIDATE_PTR(pScene);
+ pScene = _pScene;
+ pIOHandler = _pIOHandler;
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open MDL file " + pFile + ".");
+ }
+
+ // This should work for all other types of MDL files, too ...
+ // the quake header is one of the smallest, afaik
+ iFileSize = (unsigned int)file->FileSize();
+ if( iFileSize < sizeof(MDL::Header)) {
+ throw DeadlyImportError( "MDL File is too small.");
+ }
+
+ // Allocate storage and copy the contents of the file to a memory buffer
+ std::vector<unsigned char> buffer(iFileSize+1);
+ mBuffer = &buffer[0];
+ file->Read( (void*)mBuffer, 1, iFileSize);
+
+ // Append a binary zero to the end of the buffer.
+ // this is just for safety that string parsing routines
+ // find the end of the buffer ...
+ mBuffer[iFileSize] = '\0';
+ const uint32_t iMagicWord = *((uint32_t*)mBuffer);
+
+ // Determine the file subtype and call the appropriate member function
+
+ // Original Quake1 format
+ if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
+ iGSFileVersion = 0;
+ InternReadFile_Quake1();
+ }
+ // GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
+ iGSFileVersion = 2;
+ InternReadFile_Quake1();
+ }
+ // GameStudio A4 MDL3 format
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
+ iGSFileVersion = 3;
+ InternReadFile_3DGS_MDL345();
+ }
+ // GameStudio A5+ MDL4 format
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
+ iGSFileVersion = 4;
+ InternReadFile_3DGS_MDL345();
+ }
+ // GameStudio A5+ MDL5 format
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
+ iGSFileVersion = 5;
+ InternReadFile_3DGS_MDL345();
+ }
+ // GameStudio A7 MDL7 format
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
+ iGSFileVersion = 7;
+ InternReadFile_3DGS_MDL7();
+ }
+ // IDST/IDSQ Format (CS:S/HL^2, etc ...)
+ else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
+ AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
+ {
+ DefaultLogger::get()->debug("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ");
+ iGSFileVersion = 0;
+ InternReadFile_HL2();
+ }
+ else {
+ // print the magic word to the log file
+ throw DeadlyImportError( "Unknown MDL subformat " + pFile +
+ ". Magic word (" + std::string((char*)&iMagicWord,4) + ") is not known");
+ }
+
+ // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+ pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
+ 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
+
+ // delete the file buffer and cleanup
+ AI_DEBUG_INVALIDATE_PTR(mBuffer);
+ AI_DEBUG_INVALIDATE_PTR(pIOHandler);
+ AI_DEBUG_INVALIDATE_PTR(pScene);
}
// ------------------------------------------------------------------------------------------------
// Check whether we're still inside the valid file range
void MDLImporter::SizeCheck(const void* szPos)
{
- if (!szPos || (const unsigned char*)szPos > this->mBuffer + this->iFileSize)
- {
- throw DeadlyImportError("Invalid MDL file. The file is too small "
- "or contains invalid data.");
- }
+ if (!szPos || (const unsigned char*)szPos > this->mBuffer + this->iFileSize)
+ {
+ throw DeadlyImportError("Invalid MDL file. The file is too small "
+ "or contains invalid data.");
+ }
}
// ------------------------------------------------------------------------------------------------
// Just for debgging purposes
void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int iLine)
{
- ai_assert(NULL != szFile);
- if (!szPos || (const unsigned char*)szPos > mBuffer + iFileSize)
- {
- // remove a directory if there is one
- const char* szFilePtr = ::strrchr(szFile,'\\');
- if (!szFilePtr) {
- if(!(szFilePtr = ::strrchr(szFile,'/')))
- szFilePtr = szFile;
- }
- if (szFilePtr)++szFilePtr;
-
- char szBuffer[1024];
- ::sprintf(szBuffer,"Invalid MDL file. The file is too small "
- "or contains invalid data (File: %s Line: %i)",szFilePtr,iLine);
-
- throw DeadlyImportError(szBuffer);
- }
+ ai_assert(NULL != szFile);
+ if (!szPos || (const unsigned char*)szPos > mBuffer + iFileSize)
+ {
+ // remove a directory if there is one
+ const char* szFilePtr = ::strrchr(szFile,'\\');
+ if (!szFilePtr) {
+ if(!(szFilePtr = ::strrchr(szFile,'/')))
+ szFilePtr = szFile;
+ }
+ if (szFilePtr)++szFilePtr;
+
+ char szBuffer[1024];
+ ::sprintf(szBuffer,"Invalid MDL file. The file is too small "
+ "or contains invalid data (File: %s Line: %u)",szFilePtr,iLine);
+
+ throw DeadlyImportError(szBuffer);
+ }
}
// ------------------------------------------------------------------------------------------------
// Validate a quake file header
void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader)
{
- // some values may not be NULL
- if (!pcHeader->num_frames)
- throw DeadlyImportError( "[Quake 1 MDL] There are no frames in the file");
-
- if (!pcHeader->num_verts)
- throw DeadlyImportError( "[Quake 1 MDL] There are no vertices in the file");
-
- if (!pcHeader->num_tris)
- throw DeadlyImportError( "[Quake 1 MDL] There are no triangles in the file");
-
- // check whether the maxima are exceeded ...however, this applies for Quake 1 MDLs only
- if (!this->iGSFileVersion)
- {
- if (pcHeader->num_verts > AI_MDL_MAX_VERTS)
- DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices");
-
- if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES)
- DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles");
-
- if (pcHeader->num_frames > AI_MDL_MAX_FRAMES)
- DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames");
-
- // (this does not apply for 3DGS MDLs)
- if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION)
- DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is "
- "the expected file format version");
- if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight))
- DefaultLogger::get()->warn("Skin width or height are 0");
- }
+ // some values may not be NULL
+ if (!pcHeader->num_frames)
+ throw DeadlyImportError( "[Quake 1 MDL] There are no frames in the file");
+
+ if (!pcHeader->num_verts)
+ throw DeadlyImportError( "[Quake 1 MDL] There are no vertices in the file");
+
+ if (!pcHeader->num_tris)
+ throw DeadlyImportError( "[Quake 1 MDL] There are no triangles in the file");
+
+ // check whether the maxima are exceeded ...however, this applies for Quake 1 MDLs only
+ if (!this->iGSFileVersion)
+ {
+ if (pcHeader->num_verts > AI_MDL_MAX_VERTS)
+ DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices");
+
+ if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES)
+ DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles");
+
+ if (pcHeader->num_frames > AI_MDL_MAX_FRAMES)
+ DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames");
+
+ // (this does not apply for 3DGS MDLs)
+ if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION)
+ DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is "
+ "the expected file format version");
+ if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight))
+ DefaultLogger::get()->warn("Skin width or height are 0");
+ }
}
#ifdef AI_BUILD_BIG_ENDIAN
// ------------------------------------------------------------------------------------------------
void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader)
{
- AI_SWAP4( pcHeader->ident);
- AI_SWAP4( pcHeader->version);
- AI_SWAP4( pcHeader->boundingradius);
- AI_SWAP4( pcHeader->flags);
- AI_SWAP4( pcHeader->num_frames);
- AI_SWAP4( pcHeader->num_skins);
- AI_SWAP4( pcHeader->num_tris);
- AI_SWAP4( pcHeader->num_verts);
- for (unsigned int i = 0; i < 3;++i)
- {
- AI_SWAP4( pcHeader->scale[i]);
- AI_SWAP4( pcHeader->translate[i]);
- }
- AI_SWAP4( pcHeader->size);
- AI_SWAP4( pcHeader->skinheight);
- AI_SWAP4( pcHeader->skinwidth);
- AI_SWAP4( pcHeader->synctype);
+ AI_SWAP4( pcHeader->ident);
+ AI_SWAP4( pcHeader->version);
+ AI_SWAP4( pcHeader->boundingradius);
+ AI_SWAP4( pcHeader->flags);
+ AI_SWAP4( pcHeader->num_frames);
+ AI_SWAP4( pcHeader->num_skins);
+ AI_SWAP4( pcHeader->num_tris);
+ AI_SWAP4( pcHeader->num_verts);
+ for (unsigned int i = 0; i < 3;++i)
+ {
+ AI_SWAP4( pcHeader->scale[i]);
+ AI_SWAP4( pcHeader->translate[i]);
+ }
+ AI_SWAP4( pcHeader->size);
+ AI_SWAP4( pcHeader->skinheight);
+ AI_SWAP4( pcHeader->skinwidth);
+ AI_SWAP4( pcHeader->synctype);
}
#endif
@@ -325,630 +341,637 @@ void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader)
// Read a Quake 1 file
void MDLImporter::InternReadFile_Quake1( )
{
- ai_assert(NULL != pScene);
- BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
+ ai_assert(NULL != pScene);
+ BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
#ifdef AI_BUILD_BIG_ENDIAN
- FlipQuakeHeader(pcHeader);
+ FlipQuakeHeader(pcHeader);
#endif
- ValidateHeader_Quake1(pcHeader);
-
- // current cursor position in the file
- const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
-
- // need to read all textures
- for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i)
- {
- union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;};
- pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
-
- AI_SWAP4( pcSkin->group );
-
- // Quake 1 groupskins
- if (1 == pcSkin->group)
- {
- AI_SWAP4( pcGroupSkin->nb );
-
- // need to skip multiple images
- const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb;
- szCurrent += sizeof(uint32_t) * 2;
-
- if (0 != iNumImages)
- {
- if (!i) {
- // however, create only one output image (the first)
- this->CreateTextureARGB8_3DGS_MDL3(szCurrent + iNumImages * sizeof(float));
- }
- // go to the end of the skin section / the beginning of the next skin
- szCurrent += pcHeader->skinheight * pcHeader->skinwidth +
- sizeof(float) * iNumImages;
- }
- }
- // 3DGS has a few files that are using other 3DGS like texture formats here
- else
- {
- szCurrent += sizeof(uint32_t);
- unsigned int iSkip = i ? UINT_MAX : 0;
- CreateTexture_3DGS_MDL4(szCurrent,pcSkin->group,&iSkip);
- szCurrent += iSkip;
- }
- }
- // get a pointer to the texture coordinates
- BE_NCONST MDL::TexCoord* pcTexCoords = (BE_NCONST MDL::TexCoord*)szCurrent;
- szCurrent += sizeof(MDL::TexCoord) * pcHeader->num_verts;
-
- // get a pointer to the triangles
- BE_NCONST MDL::Triangle* pcTriangles = (BE_NCONST MDL::Triangle*)szCurrent;
- szCurrent += sizeof(MDL::Triangle) * pcHeader->num_tris;
- VALIDATE_FILE_SIZE(szCurrent);
-
- // now get a pointer to the first frame in the file
- BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
- BE_NCONST MDL::SimpleFrame* pcFirstFrame;
-
- if (0 == pcFrames->type)
- {
- // get address of single frame
- pcFirstFrame = &pcFrames->frame;
- }
- else
- {
- // get the first frame in the group
- BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames;
- pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
- }
- BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
- VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));
+ ValidateHeader_Quake1(pcHeader);
+
+ // current cursor position in the file
+ const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
+
+ // need to read all textures
+ for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i)
+ {
+ union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;};
+ if (szCurrent + sizeof(MDL::Skin) > this->mBuffer + this->iFileSize) {
+ throw DeadlyImportError("[Quake 1 MDL] Unexpected EOF");
+ }
+ pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
+
+ AI_SWAP4( pcSkin->group );
+
+ // Quake 1 groupskins
+ if (1 == pcSkin->group)
+ {
+ AI_SWAP4( pcGroupSkin->nb );
+
+ // need to skip multiple images
+ const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb;
+ szCurrent += sizeof(uint32_t) * 2;
+
+ if (0 != iNumImages)
+ {
+ if (!i) {
+ // however, create only one output image (the first)
+ this->CreateTextureARGB8_3DGS_MDL3(szCurrent + iNumImages * sizeof(float));
+ }
+ // go to the end of the skin section / the beginning of the next skin
+ szCurrent += pcHeader->skinheight * pcHeader->skinwidth +
+ sizeof(float) * iNumImages;
+ }
+ }
+ // 3DGS has a few files that are using other 3DGS like texture formats here
+ else
+ {
+ szCurrent += sizeof(uint32_t);
+ unsigned int iSkip = i ? UINT_MAX : 0;
+ CreateTexture_3DGS_MDL4(szCurrent,pcSkin->group,&iSkip);
+ szCurrent += iSkip;
+ }
+ }
+ // get a pointer to the texture coordinates
+ BE_NCONST MDL::TexCoord* pcTexCoords = (BE_NCONST MDL::TexCoord*)szCurrent;
+ szCurrent += sizeof(MDL::TexCoord) * pcHeader->num_verts;
+
+ // get a pointer to the triangles
+ BE_NCONST MDL::Triangle* pcTriangles = (BE_NCONST MDL::Triangle*)szCurrent;
+ szCurrent += sizeof(MDL::Triangle) * pcHeader->num_tris;
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ // now get a pointer to the first frame in the file
+ BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
+ BE_NCONST MDL::SimpleFrame* pcFirstFrame;
+
+ if (0 == pcFrames->type)
+ {
+ // get address of single frame
+ pcFirstFrame = &pcFrames->frame;
+ }
+ else
+ {
+ // get the first frame in the group
+ BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames;
+ pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
+ }
+ BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
+ VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));
#ifdef AI_BUILD_BIG_ENDIAN
- for (int i = 0; i<pcHeader->num_verts;++i)
- {
- AI_SWAP4( pcTexCoords[i].onseam );
- AI_SWAP4( pcTexCoords[i].s );
- AI_SWAP4( pcTexCoords[i].t );
- }
-
- for (int i = 0; i<pcHeader->num_tris;++i)
- {
- AI_SWAP4( pcTriangles[i].facesfront);
- AI_SWAP4( pcTriangles[i].vertex[0]);
- AI_SWAP4( pcTriangles[i].vertex[1]);
- AI_SWAP4( pcTriangles[i].vertex[2]);
- }
+ for (int i = 0; i<pcHeader->num_verts;++i)
+ {
+ AI_SWAP4( pcTexCoords[i].onseam );
+ AI_SWAP4( pcTexCoords[i].s );
+ AI_SWAP4( pcTexCoords[i].t );
+ }
+
+ for (int i = 0; i<pcHeader->num_tris;++i)
+ {
+ AI_SWAP4( pcTriangles[i].facesfront);
+ AI_SWAP4( pcTriangles[i].vertex[0]);
+ AI_SWAP4( pcTriangles[i].vertex[1]);
+ AI_SWAP4( pcTriangles[i].vertex[2]);
+ }
#endif
- // setup materials
- SetupMaterialProperties_3DGS_MDL5_Quake1();
-
- // allocate enough storage to hold all vertices and triangles
- aiMesh* pcMesh = new aiMesh();
-
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
- pcMesh->mNumVertices = pcHeader->num_tris * 3;
- pcMesh->mNumFaces = pcHeader->num_tris;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNumUVComponents[0] = 2;
-
- // there won't be more than one mesh inside the file
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- pScene->mMeshes[0] = pcMesh;
-
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i)
- {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
-
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent)
- {
- pcMesh->mFaces[i].mIndices[c] = iCurrent;
-
- // read vertices
- unsigned int iIndex = pcTriangles->vertex[c];
- if (iIndex >= (unsigned int)pcHeader->num_verts)
- {
- iIndex = pcHeader->num_verts-1;
- DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
- }
-
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
- vec.x += pcHeader->translate[0];
-
- vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
- vec.y += pcHeader->translate[1];
- //vec.y *= -1.0f;
-
- vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
- vec.z += pcHeader->translate[2];
-
- // read the normal vector from the precalculated normal table
- MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
- //pcMesh->mNormals[iCurrent].y *= -1.0f;
-
- // read texture coordinates
- float s = (float)pcTexCoords[iIndex].s;
- float t = (float)pcTexCoords[iIndex].t;
-
- // translate texture coordinates
- if (0 == pcTriangles->facesfront && 0 != pcTexCoords[iIndex].onseam) {
- s += pcHeader->skinwidth * 0.5f;
- }
-
- // Scale s and t to range from 0.0 to 1.0
- pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / pcHeader->skinwidth;
- pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / pcHeader->skinheight;
-
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
- return;
+ // setup materials
+ SetupMaterialProperties_3DGS_MDL5_Quake1();
+
+ // allocate enough storage to hold all vertices and triangles
+ aiMesh* pcMesh = new aiMesh();
+
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+ pcMesh->mNumVertices = pcHeader->num_tris * 3;
+ pcMesh->mNumFaces = pcHeader->num_tris;
+ pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+ pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNumUVComponents[0] = 2;
+
+ // there won't be more than one mesh inside the file
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
+ pScene->mMeshes[0] = pcMesh;
+
+ // now iterate through all triangles
+ unsigned int iCurrent = 0;
+ for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i)
+ {
+ pcMesh->mFaces[i].mIndices = new unsigned int[3];
+ pcMesh->mFaces[i].mNumIndices = 3;
+
+ unsigned int iTemp = iCurrent;
+ for (unsigned int c = 0; c < 3;++c,++iCurrent)
+ {
+ pcMesh->mFaces[i].mIndices[c] = iCurrent;
+
+ // read vertices
+ unsigned int iIndex = pcTriangles->vertex[c];
+ if (iIndex >= (unsigned int)pcHeader->num_verts)
+ {
+ iIndex = pcHeader->num_verts-1;
+ DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
+ }
+
+ aiVector3D& vec = pcMesh->mVertices[iCurrent];
+ vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
+ vec.x += pcHeader->translate[0];
+
+ vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+ vec.y += pcHeader->translate[1];
+ //vec.y *= -1.0f;
+
+ vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+ vec.z += pcHeader->translate[2];
+
+ // read the normal vector from the precalculated normal table
+ MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
+ //pcMesh->mNormals[iCurrent].y *= -1.0f;
+
+ // read texture coordinates
+ float s = (float)pcTexCoords[iIndex].s;
+ float t = (float)pcTexCoords[iIndex].t;
+
+ // translate texture coordinates
+ if (0 == pcTriangles->facesfront && 0 != pcTexCoords[iIndex].onseam) {
+ s += pcHeader->skinwidth * 0.5f;
+ }
+
+ // Scale s and t to range from 0.0 to 1.0
+ pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / pcHeader->skinwidth;
+ pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / pcHeader->skinheight;
+
+ }
+ pcMesh->mFaces[i].mIndices[0] = iTemp+2;
+ pcMesh->mFaces[i].mIndices[1] = iTemp+1;
+ pcMesh->mFaces[i].mIndices[2] = iTemp+0;
+ pcTriangles++;
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
// Setup material properties for Quake and older GameStudio files
void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1( )
{
- const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
-
- // allocate ONE material
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = new aiMaterial();
- pScene->mNumMaterials = 1;
-
- // setup the material's properties
- const int iMode = (int)aiShadingMode_Gouraud;
- aiMaterial* const pcHelper = (aiMaterial*)pScene->mMaterials[0];
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- aiColor4D clr;
- if (0 != pcHeader->num_skins && pScene->mNumTextures) {
- // can we replace the texture with a single color?
- clr = this->ReplaceTextureWithColor(pScene->mTextures[0]);
- if (is_not_qnan(clr.r)) {
- delete pScene->mTextures[0];
- delete[] pScene->mTextures;
-
- pScene->mTextures = NULL;
- pScene->mNumTextures = 0;
- }
- else {
- clr.b = clr.a = clr.g = clr.r = 1.0f;
- aiString szString;
- ::memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3);
- szString.length = 2;
- pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- }
-
- pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- clr.r *= 0.05f;clr.g *= 0.05f;
- clr.b *= 0.05f;clr.a = 1.0f;
- pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+ const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
+
+ // allocate ONE material
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = new aiMaterial();
+ pScene->mNumMaterials = 1;
+
+ // setup the material's properties
+ const int iMode = (int)aiShadingMode_Gouraud;
+ aiMaterial* const pcHelper = (aiMaterial*)pScene->mMaterials[0];
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ aiColor4D clr;
+ if (0 != pcHeader->num_skins && pScene->mNumTextures) {
+ // can we replace the texture with a single color?
+ clr = this->ReplaceTextureWithColor(pScene->mTextures[0]);
+ if (is_not_qnan(clr.r)) {
+ delete pScene->mTextures[0];
+ delete[] pScene->mTextures;
+
+ pScene->mTextures = NULL;
+ pScene->mNumTextures = 0;
+ }
+ else {
+ clr.b = clr.a = clr.g = clr.r = 1.0f;
+ aiString szString;
+ ::memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3);
+ szString.length = 2;
+ pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ }
+
+ pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ clr.r *= 0.05f;clr.g *= 0.05f;
+ clr.b *= 0.05f;clr.a = 1.0f;
+ pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
}
// ------------------------------------------------------------------------------------------------
// Read a MDL 3,4,5 file
void MDLImporter::InternReadFile_3DGS_MDL345( )
{
- ai_assert(NULL != pScene);
+ ai_assert(NULL != pScene);
- // the header of MDL 3/4/5 is nearly identical to the original Quake1 header
- BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
+ // the header of MDL 3/4/5 is nearly identical to the original Quake1 header
+ BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
#ifdef AI_BUILD_BIG_ENDIAN
- FlipQuakeHeader(pcHeader);
+ FlipQuakeHeader(pcHeader);
#endif
- ValidateHeader_Quake1(pcHeader);
-
- // current cursor position in the file
- const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
-
- // need to read all textures
- for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i) {
- BE_NCONST MDL::Skin* pcSkin;
- pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
- AI_SWAP4( pcSkin->group);
- // create one output image
- unsigned int iSkip = i ? UINT_MAX : 0;
- if (5 <= iGSFileVersion)
- {
- // MDL5 format could contain MIPmaps
- CreateTexture_3DGS_MDL5((unsigned char*)pcSkin + sizeof(uint32_t),
- pcSkin->group,&iSkip);
- }
- else {
- CreateTexture_3DGS_MDL4((unsigned char*)pcSkin + sizeof(uint32_t),
- pcSkin->group,&iSkip);
- }
- // need to skip one image
- szCurrent += iSkip + sizeof(uint32_t);
-
- }
- // get a pointer to the texture coordinates
- BE_NCONST MDL::TexCoord_MDL3* pcTexCoords = (BE_NCONST MDL::TexCoord_MDL3*)szCurrent;
- szCurrent += sizeof(MDL::TexCoord_MDL3) * pcHeader->synctype;
-
- // NOTE: for MDLn formats "synctype" corresponds to the number of UV coords
-
- // get a pointer to the triangles
- BE_NCONST MDL::Triangle_MDL3* pcTriangles = (BE_NCONST MDL::Triangle_MDL3*)szCurrent;
- szCurrent += sizeof(MDL::Triangle_MDL3) * pcHeader->num_tris;
+ ValidateHeader_Quake1(pcHeader);
+
+ // current cursor position in the file
+ const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
+ const unsigned char* szEnd = mBuffer + iFileSize;
+
+ // need to read all textures
+ for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i) {
+ if (szCurrent >= szEnd) {
+ throw DeadlyImportError( "Texture data past end of file.");
+ }
+ BE_NCONST MDL::Skin* pcSkin;
+ pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
+ AI_SWAP4( pcSkin->group);
+ // create one output image
+ unsigned int iSkip = i ? UINT_MAX : 0;
+ if (5 <= iGSFileVersion)
+ {
+ // MDL5 format could contain MIPmaps
+ CreateTexture_3DGS_MDL5((unsigned char*)pcSkin + sizeof(uint32_t),
+ pcSkin->group,&iSkip);
+ }
+ else {
+ CreateTexture_3DGS_MDL4((unsigned char*)pcSkin + sizeof(uint32_t),
+ pcSkin->group,&iSkip);
+ }
+ // need to skip one image
+ szCurrent += iSkip + sizeof(uint32_t);
+
+ }
+ // get a pointer to the texture coordinates
+ BE_NCONST MDL::TexCoord_MDL3* pcTexCoords = (BE_NCONST MDL::TexCoord_MDL3*)szCurrent;
+ szCurrent += sizeof(MDL::TexCoord_MDL3) * pcHeader->synctype;
+
+ // NOTE: for MDLn formats "synctype" corresponds to the number of UV coords
+
+ // get a pointer to the triangles
+ BE_NCONST MDL::Triangle_MDL3* pcTriangles = (BE_NCONST MDL::Triangle_MDL3*)szCurrent;
+ szCurrent += sizeof(MDL::Triangle_MDL3) * pcHeader->num_tris;
#ifdef AI_BUILD_BIG_ENDIAN
- for (int i = 0; i<pcHeader->synctype;++i) {
- AI_SWAP2( pcTexCoords[i].u );
- AI_SWAP2( pcTexCoords[i].v );
- }
+ for (int i = 0; i<pcHeader->synctype;++i) {
+ AI_SWAP2( pcTexCoords[i].u );
+ AI_SWAP2( pcTexCoords[i].v );
+ }
- for (int i = 0; i<pcHeader->num_tris;++i) {
- AI_SWAP2( pcTriangles[i].index_xyz[0]);
- AI_SWAP2( pcTriangles[i].index_xyz[1]);
- AI_SWAP2( pcTriangles[i].index_xyz[2]);
- AI_SWAP2( pcTriangles[i].index_uv[0]);
- AI_SWAP2( pcTriangles[i].index_uv[1]);
- AI_SWAP2( pcTriangles[i].index_uv[2]);
- }
+ for (int i = 0; i<pcHeader->num_tris;++i) {
+ AI_SWAP2( pcTriangles[i].index_xyz[0]);
+ AI_SWAP2( pcTriangles[i].index_xyz[1]);
+ AI_SWAP2( pcTriangles[i].index_xyz[2]);
+ AI_SWAP2( pcTriangles[i].index_uv[0]);
+ AI_SWAP2( pcTriangles[i].index_uv[1]);
+ AI_SWAP2( pcTriangles[i].index_uv[2]);
+ }
#endif
- VALIDATE_FILE_SIZE(szCurrent);
-
- // setup materials
- SetupMaterialProperties_3DGS_MDL5_Quake1();
-
- // allocate enough storage to hold all vertices and triangles
- aiMesh* pcMesh = new aiMesh();
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- pcMesh->mNumVertices = pcHeader->num_tris * 3;
- pcMesh->mNumFaces = pcHeader->num_tris;
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
-
- // there won't be more than one mesh inside the file
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- pScene->mMeshes[0] = pcMesh;
-
- // allocate output storage
- pcMesh->mNumVertices = (unsigned int)pcHeader->num_tris*3;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
-
- if (pcHeader->synctype) {
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNumUVComponents[0] = 2;
- }
-
- // now get a pointer to the first frame in the file
- BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
- AI_SWAP4(pcFrames->type);
-
- // byte packed vertices
- // FIXME: these two snippets below are almost identical ... join them?
- /////////////////////////////////////////////////////////////////////////////////////
- if (0 == pcFrames->type || 3 >= this->iGSFileVersion) {
-
- const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t));
- const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
-
- VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
-
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
-
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent) {
- // read vertices
- unsigned int iIndex = pcTriangles->index_xyz[c];
- if (iIndex >= (unsigned int)pcHeader->num_verts) {
- iIndex = pcHeader->num_verts-1;
- DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
- }
-
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
- vec.x += pcHeader->translate[0];
-
- vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
- vec.y += pcHeader->translate[1];
- // vec.y *= -1.0f;
-
- vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
- vec.z += pcHeader->translate[2];
-
- // read the normal vector from the precalculated normal table
- MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
- // pcMesh->mNormals[iCurrent].y *= -1.0f;
-
- // read texture coordinates
- if (pcHeader->synctype) {
- ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent],
- pcTexCoords,pcTriangles->index_uv[c]);
- }
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
-
- }
- // short packed vertices
- /////////////////////////////////////////////////////////////////////////////////////
- else {
- // now get a pointer to the first frame in the file
- const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*) (szCurrent + sizeof(uint32_t));
-
- // get a pointer to the vertices
- const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) +
- sizeof(pcFirstFrame->name));
-
- VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
-
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
-
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent) {
- // read vertices
- unsigned int iIndex = pcTriangles->index_xyz[c];
- if (iIndex >= (unsigned int)pcHeader->num_verts) {
- iIndex = pcHeader->num_verts-1;
- DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
- }
-
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
- vec.x += pcHeader->translate[0];
-
- vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
- vec.y += pcHeader->translate[1];
- // vec.y *= -1.0f;
-
- vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
- vec.z += pcHeader->translate[2];
-
- // read the normal vector from the precalculated normal table
- MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
- // pcMesh->mNormals[iCurrent].y *= -1.0f;
-
- // read texture coordinates
- if (pcHeader->synctype) {
- ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent],
- pcTexCoords,pcTriangles->index_uv[c]);
- }
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
- }
-
- // For MDL5 we will need to build valid texture coordinates
- // basing upon the file loaded (only support one file as skin)
- if (0x5 == iGSFileVersion)
- CalculateUVCoordinates_MDL5();
- return;
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ // setup materials
+ SetupMaterialProperties_3DGS_MDL5_Quake1();
+
+ // allocate enough storage to hold all vertices and triangles
+ aiMesh* pcMesh = new aiMesh();
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ pcMesh->mNumVertices = pcHeader->num_tris * 3;
+ pcMesh->mNumFaces = pcHeader->num_tris;
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+ // there won't be more than one mesh inside the file
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
+ pScene->mMeshes[0] = pcMesh;
+
+ // allocate output storage
+ pcMesh->mNumVertices = (unsigned int)pcHeader->num_tris*3;
+ pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+
+ if (pcHeader->synctype) {
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNumUVComponents[0] = 2;
+ }
+
+ // now get a pointer to the first frame in the file
+ BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
+ AI_SWAP4(pcFrames->type);
+
+ // byte packed vertices
+ // FIXME: these two snippets below are almost identical ... join them?
+ /////////////////////////////////////////////////////////////////////////////////////
+ if (0 == pcFrames->type || 3 >= this->iGSFileVersion) {
+
+ const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t));
+ const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
+
+ VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
+
+ // now iterate through all triangles
+ unsigned int iCurrent = 0;
+ for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) {
+ pcMesh->mFaces[i].mIndices = new unsigned int[3];
+ pcMesh->mFaces[i].mNumIndices = 3;
+
+ unsigned int iTemp = iCurrent;
+ for (unsigned int c = 0; c < 3;++c,++iCurrent) {
+ // read vertices
+ unsigned int iIndex = pcTriangles->index_xyz[c];
+ if (iIndex >= (unsigned int)pcHeader->num_verts) {
+ iIndex = pcHeader->num_verts-1;
+ DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
+ }
+
+ aiVector3D& vec = pcMesh->mVertices[iCurrent];
+ vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
+ vec.x += pcHeader->translate[0];
+
+ vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+ vec.y += pcHeader->translate[1];
+ // vec.y *= -1.0f;
+
+ vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+ vec.z += pcHeader->translate[2];
+
+ // read the normal vector from the precalculated normal table
+ MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
+ // pcMesh->mNormals[iCurrent].y *= -1.0f;
+
+ // read texture coordinates
+ if (pcHeader->synctype) {
+ ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent],
+ pcTexCoords,pcTriangles->index_uv[c]);
+ }
+ }
+ pcMesh->mFaces[i].mIndices[0] = iTemp+2;
+ pcMesh->mFaces[i].mIndices[1] = iTemp+1;
+ pcMesh->mFaces[i].mIndices[2] = iTemp+0;
+ pcTriangles++;
+ }
+
+ }
+ // short packed vertices
+ /////////////////////////////////////////////////////////////////////////////////////
+ else {
+ // now get a pointer to the first frame in the file
+ const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*) (szCurrent + sizeof(uint32_t));
+
+ // get a pointer to the vertices
+ const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) +
+ sizeof(pcFirstFrame->name));
+
+ VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
+
+ // now iterate through all triangles
+ unsigned int iCurrent = 0;
+ for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) {
+ pcMesh->mFaces[i].mIndices = new unsigned int[3];
+ pcMesh->mFaces[i].mNumIndices = 3;
+
+ unsigned int iTemp = iCurrent;
+ for (unsigned int c = 0; c < 3;++c,++iCurrent) {
+ // read vertices
+ unsigned int iIndex = pcTriangles->index_xyz[c];
+ if (iIndex >= (unsigned int)pcHeader->num_verts) {
+ iIndex = pcHeader->num_verts-1;
+ DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
+ }
+
+ aiVector3D& vec = pcMesh->mVertices[iCurrent];
+ vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
+ vec.x += pcHeader->translate[0];
+
+ vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+ vec.y += pcHeader->translate[1];
+ // vec.y *= -1.0f;
+
+ vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+ vec.z += pcHeader->translate[2];
+
+ // read the normal vector from the precalculated normal table
+ MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
+ // pcMesh->mNormals[iCurrent].y *= -1.0f;
+
+ // read texture coordinates
+ if (pcHeader->synctype) {
+ ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent],
+ pcTexCoords,pcTriangles->index_uv[c]);
+ }
+ }
+ pcMesh->mFaces[i].mIndices[0] = iTemp+2;
+ pcMesh->mFaces[i].mIndices[1] = iTemp+1;
+ pcMesh->mFaces[i].mIndices[2] = iTemp+0;
+ pcTriangles++;
+ }
+ }
+
+ // For MDL5 we will need to build valid texture coordinates
+ // basing upon the file loaded (only support one file as skin)
+ if (0x5 == iGSFileVersion)
+ CalculateUVCoordinates_MDL5();
+ return;
}
// ------------------------------------------------------------------------------------------------
// Get a single UV coordinate for Quake and older GameStudio files
-void MDLImporter::ImportUVCoordinate_3DGS_MDL345(
- aiVector3D& vOut,
- const MDL::TexCoord_MDL3* pcSrc,
- unsigned int iIndex)
+void MDLImporter::ImportUVCoordinate_3DGS_MDL345(
+ aiVector3D& vOut,
+ const MDL::TexCoord_MDL3* pcSrc,
+ unsigned int iIndex)
{
- ai_assert(NULL != pcSrc);
- const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
-
- // validate UV indices
- if (iIndex >= (unsigned int) pcHeader->synctype) {
- iIndex = pcHeader->synctype-1;
- DefaultLogger::get()->warn("Index overflow in MDLn UV coord list");
- }
-
- float s = (float)pcSrc[iIndex].u;
- float t = (float)pcSrc[iIndex].v;
-
- // Scale s and t to range from 0.0 to 1.0
- if (0x5 != iGSFileVersion) {
- s = (s + 0.5f) / pcHeader->skinwidth;
- t = 1.0f-(t + 0.5f) / pcHeader->skinheight;
- }
-
- vOut.x = s;
- vOut.y = t;
- vOut.z = 0.0f;
+ ai_assert(NULL != pcSrc);
+ const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
+
+ // validate UV indices
+ if (iIndex >= (unsigned int) pcHeader->synctype) {
+ iIndex = pcHeader->synctype-1;
+ DefaultLogger::get()->warn("Index overflow in MDLn UV coord list");
+ }
+
+ float s = (float)pcSrc[iIndex].u;
+ float t = (float)pcSrc[iIndex].v;
+
+ // Scale s and t to range from 0.0 to 1.0
+ if (0x5 != iGSFileVersion) {
+ s = (s + 0.5f) / pcHeader->skinwidth;
+ t = 1.0f-(t + 0.5f) / pcHeader->skinheight;
+ }
+
+ vOut.x = s;
+ vOut.y = t;
+ vOut.z = 0.0f;
}
// ------------------------------------------------------------------------------------------------
// Compute UV coordinates for a MDL5 file
void MDLImporter::CalculateUVCoordinates_MDL5()
{
- const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
- if (pcHeader->num_skins && this->pScene->mNumTextures) {
- const aiTexture* pcTex = this->pScene->mTextures[0];
-
- // if the file is loaded in DDS format: get the size of the
- // texture from the header of the DDS file
- // skip three DWORDs and read first height, then the width
- unsigned int iWidth, iHeight;
- if (!pcTex->mHeight) {
- const uint32_t* piPtr = (uint32_t*)pcTex->pcData;
-
- piPtr += 3;
- iHeight = (unsigned int)*piPtr++;
- iWidth = (unsigned int)*piPtr;
- if (!iHeight || !iWidth)
- {
- DefaultLogger::get()->warn("Either the width or the height of the "
- "embedded DDS texture is zero. Unable to compute final texture "
- "coordinates. The texture coordinates remain in their original "
- "0-x/0-y (x,y = texture size) range.");
- iWidth = 1;
- iHeight = 1;
- }
- }
- else {
- iWidth = pcTex->mWidth;
- iHeight = pcTex->mHeight;
- }
-
- if (1 != iWidth || 1 != iHeight) {
- const float fWidth = (float)iWidth;
- const float fHeight = (float)iHeight;
- aiMesh* pcMesh = this->pScene->mMeshes[0];
- for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
- {
- pcMesh->mTextureCoords[0][i].x /= fWidth;
- pcMesh->mTextureCoords[0][i].y /= fHeight;
- pcMesh->mTextureCoords[0][i].y = 1.0f - pcMesh->mTextureCoords[0][i].y; // DX to OGL
- }
- }
- }
+ const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
+ if (pcHeader->num_skins && this->pScene->mNumTextures) {
+ const aiTexture* pcTex = this->pScene->mTextures[0];
+
+ // if the file is loaded in DDS format: get the size of the
+ // texture from the header of the DDS file
+ // skip three DWORDs and read first height, then the width
+ unsigned int iWidth, iHeight;
+ if (!pcTex->mHeight) {
+ const uint32_t* piPtr = (uint32_t*)pcTex->pcData;
+
+ piPtr += 3;
+ iHeight = (unsigned int)*piPtr++;
+ iWidth = (unsigned int)*piPtr;
+ if (!iHeight || !iWidth)
+ {
+ DefaultLogger::get()->warn("Either the width or the height of the "
+ "embedded DDS texture is zero. Unable to compute final texture "
+ "coordinates. The texture coordinates remain in their original "
+ "0-x/0-y (x,y = texture size) range.");
+ iWidth = 1;
+ iHeight = 1;
+ }
+ }
+ else {
+ iWidth = pcTex->mWidth;
+ iHeight = pcTex->mHeight;
+ }
+
+ if (1 != iWidth || 1 != iHeight) {
+ const float fWidth = (float)iWidth;
+ const float fHeight = (float)iHeight;
+ aiMesh* pcMesh = this->pScene->mMeshes[0];
+ for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
+ {
+ pcMesh->mTextureCoords[0][i].x /= fWidth;
+ pcMesh->mTextureCoords[0][i].y /= fHeight;
+ pcMesh->mTextureCoords[0][i].y = 1.0f - pcMesh->mTextureCoords[0][i].y; // DX to OGL
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Validate the header of a MDL7 file
void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader)
{
- ai_assert(NULL != pcHeader);
-
- // There are some fixed sizes ...
- if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) {
- throw DeadlyImportError(
- "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size");
- }
- if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size) {
- throw DeadlyImportError(
- "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size");
- }
- if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size) {
- throw DeadlyImportError(
- "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size");
- }
-
- // if there are no groups ... how should we load such a file?
- if(!pcHeader->groups_num) {
- throw DeadlyImportError( "[3DGS MDL7] No frames found");
- }
+ ai_assert(NULL != pcHeader);
+
+ // There are some fixed sizes ...
+ if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) {
+ throw DeadlyImportError(
+ "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size");
+ }
+ if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size) {
+ throw DeadlyImportError(
+ "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size");
+ }
+ if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size) {
+ throw DeadlyImportError(
+ "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size");
+ }
+
+ // if there are no groups ... how should we load such a file?
+ if(!pcHeader->groups_num) {
+ throw DeadlyImportError( "[3DGS MDL7] No frames found");
+ }
}
// ------------------------------------------------------------------------------------------------
// resolve bone animation matrices
void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones)
{
- const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- const MDL::Bone_MDL7* pcBones = (const MDL::Bone_MDL7*)(pcHeader+1);
- ai_assert(NULL != apcOutBones);
-
- // first find the bone that has NO parent, calculate the
- // animation matrix for it, then go on and search for the next parent
- // index (0) and so on until we can't find a new node.
- uint16_t iParent = 0xffff;
- uint32_t iIterations = 0;
- while (iIterations++ < pcHeader->bones_num) {
- for (uint32_t iBone = 0; iBone < pcHeader->bones_num;++iBone) {
- BE_NCONST MDL::Bone_MDL7* pcBone = _AI_MDL7_ACCESS_PTR(pcBones,iBone,
- pcHeader->bone_stc_size,MDL::Bone_MDL7);
-
- AI_SWAP2(pcBone->parent_index);
- AI_SWAP4(pcBone->x);
- AI_SWAP4(pcBone->y);
- AI_SWAP4(pcBone->z);
-
- if (iParent == pcBone->parent_index) {
- // MDL7 readme
- ////////////////////////////////////////////////////////////////
- /*
- The animation matrix is then calculated the following way:
-
- vector3 bPos = <absolute bone position>
- matrix44 laM; // local animation matrix
- sphrvector key_rotate = <bone rotation>
-
- matrix44 m1,m2;
- create_trans_matrix(m1, -bPos.x, -bPos.y, -bPos.z);
- create_trans_matrix(m2, -bPos.x, -bPos.y, -bPos.z);
-
- create_rotation_matrix(laM,key_rotate);
-
- laM = sm1 * laM;
- laM = laM * sm2;
- */
- /////////////////////////////////////////////////////////////////
-
- MDL::IntBone_MDL7* const pcOutBone = apcOutBones[iBone];
-
- // store the parent index of the bone
- pcOutBone->iParent = pcBone->parent_index;
- if (0xffff != iParent) {
- const MDL::IntBone_MDL7* pcParentBone = apcOutBones[iParent];
- pcOutBone->mOffsetMatrix.a4 = -pcParentBone->vPosition.x;
- pcOutBone->mOffsetMatrix.b4 = -pcParentBone->vPosition.y;
- pcOutBone->mOffsetMatrix.c4 = -pcParentBone->vPosition.z;
- }
- pcOutBone->vPosition.x = pcBone->x;
- pcOutBone->vPosition.y = pcBone->y;
- pcOutBone->vPosition.z = pcBone->z;
- pcOutBone->mOffsetMatrix.a4 -= pcBone->x;
- pcOutBone->mOffsetMatrix.b4 -= pcBone->y;
- pcOutBone->mOffsetMatrix.c4 -= pcBone->z;
-
- if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) {
- // no real name for our poor bone is specified :-(
- pcOutBone->mName.length = ::sprintf(pcOutBone->mName.data,
- "UnnamedBone_%i",iBone);
- }
- else {
- // Make sure we won't run over the buffer's end if there is no
- // terminal 0 character (however the documentation says there
- // should be one)
- uint32_t iMaxLen = pcHeader->bone_stc_size-16;
- for (uint32_t qq = 0; qq < iMaxLen;++qq) {
- if (!pcBone->name[qq]) {
- iMaxLen = qq;
- break;
- }
- }
-
- // store the name of the bone
- pcOutBone->mName.length = (size_t)iMaxLen;
- ::memcpy(pcOutBone->mName.data,pcBone->name,pcOutBone->mName.length);
- pcOutBone->mName.data[pcOutBone->mName.length] = '\0';
- }
- }
- }
- ++iParent;
- }
+ const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+ const MDL::Bone_MDL7* pcBones = (const MDL::Bone_MDL7*)(pcHeader+1);
+ ai_assert(NULL != apcOutBones);
+
+ // first find the bone that has NO parent, calculate the
+ // animation matrix for it, then go on and search for the next parent
+ // index (0) and so on until we can't find a new node.
+ uint16_t iParent = 0xffff;
+ uint32_t iIterations = 0;
+ while (iIterations++ < pcHeader->bones_num) {
+ for (uint32_t iBone = 0; iBone < pcHeader->bones_num;++iBone) {
+ BE_NCONST MDL::Bone_MDL7* pcBone = _AI_MDL7_ACCESS_PTR(pcBones,iBone,
+ pcHeader->bone_stc_size,MDL::Bone_MDL7);
+
+ AI_SWAP2(pcBone->parent_index);
+ AI_SWAP4(pcBone->x);
+ AI_SWAP4(pcBone->y);
+ AI_SWAP4(pcBone->z);
+
+ if (iParent == pcBone->parent_index) {
+ // MDL7 readme
+ ////////////////////////////////////////////////////////////////
+ /*
+ The animation matrix is then calculated the following way:
+
+ vector3 bPos = <absolute bone position>
+ matrix44 laM; // local animation matrix
+ sphrvector key_rotate = <bone rotation>
+
+ matrix44 m1,m2;
+ create_trans_matrix(m1, -bPos.x, -bPos.y, -bPos.z);
+ create_trans_matrix(m2, -bPos.x, -bPos.y, -bPos.z);
+
+ create_rotation_matrix(laM,key_rotate);
+
+ laM = sm1 * laM;
+ laM = laM * sm2;
+ */
+ /////////////////////////////////////////////////////////////////
+
+ MDL::IntBone_MDL7* const pcOutBone = apcOutBones[iBone];
+
+ // store the parent index of the bone
+ pcOutBone->iParent = pcBone->parent_index;
+ if (0xffff != iParent) {
+ const MDL::IntBone_MDL7* pcParentBone = apcOutBones[iParent];
+ pcOutBone->mOffsetMatrix.a4 = -pcParentBone->vPosition.x;
+ pcOutBone->mOffsetMatrix.b4 = -pcParentBone->vPosition.y;
+ pcOutBone->mOffsetMatrix.c4 = -pcParentBone->vPosition.z;
+ }
+ pcOutBone->vPosition.x = pcBone->x;
+ pcOutBone->vPosition.y = pcBone->y;
+ pcOutBone->vPosition.z = pcBone->z;
+ pcOutBone->mOffsetMatrix.a4 -= pcBone->x;
+ pcOutBone->mOffsetMatrix.b4 -= pcBone->y;
+ pcOutBone->mOffsetMatrix.c4 -= pcBone->z;
+
+ if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) {
+ // no real name for our poor bone is specified :-(
+ pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, MAXLEN,
+ "UnnamedBone_%i",iBone);
+ }
+ else {
+ // Make sure we won't run over the buffer's end if there is no
+ // terminal 0 character (however the documentation says there
+ // should be one)
+ uint32_t iMaxLen = pcHeader->bone_stc_size-16;
+ for (uint32_t qq = 0; qq < iMaxLen;++qq) {
+ if (!pcBone->name[qq]) {
+ iMaxLen = qq;
+ break;
+ }
+ }
+
+ // store the name of the bone
+ pcOutBone->mName.length = (size_t)iMaxLen;
+ ::memcpy(pcOutBone->mName.data,pcBone->name,pcOutBone->mName.length);
+ pcOutBone->mName.data[pcOutBone->mName.length] = '\0';
+ }
+ }
+ }
+ ++iParent;
+ }
}
// ------------------------------------------------------------------------------------------------
@@ -956,630 +979,634 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones)
MDL::IntBone_MDL7** MDLImporter::LoadBones_3DGS_MDL7()
{
const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- if (pcHeader->bones_num) {
- // validate the size of the bone data structure in the file
- if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS != pcHeader->bone_stc_size &&
- AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size &&
- AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size)
- {
- DefaultLogger::get()->warn("Unknown size of bone data structure");
- return NULL;
- }
-
- MDL::IntBone_MDL7** apcBonesOut = new MDL::IntBone_MDL7*[pcHeader->bones_num];
- for (uint32_t crank = 0; crank < pcHeader->bones_num;++crank)
- apcBonesOut[crank] = new MDL::IntBone_MDL7();
-
- // and calculate absolute bone offset matrices ...
- CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut);
- return apcBonesOut;
- }
- return NULL;
+ if (pcHeader->bones_num) {
+ // validate the size of the bone data structure in the file
+ if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS != pcHeader->bone_stc_size &&
+ AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size &&
+ AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size)
+ {
+ DefaultLogger::get()->warn("Unknown size of bone data structure");
+ return NULL;
+ }
+
+ MDL::IntBone_MDL7** apcBonesOut = new MDL::IntBone_MDL7*[pcHeader->bones_num];
+ for (uint32_t crank = 0; crank < pcHeader->bones_num;++crank)
+ apcBonesOut[crank] = new MDL::IntBone_MDL7();
+
+ // and calculate absolute bone offset matrices ...
+ CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut);
+ return apcBonesOut;
+ }
+ return NULL;
}
// ------------------------------------------------------------------------------------------------
// read faces from a MDL7 file
void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData)
+ MDL::IntGroupData_MDL7& groupData)
{
- const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
-
- // iterate through all triangles and build valid display lists
- unsigned int iOutIndex = 0;
- for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) {
- AI_SWAP2(pcGroupTris->v_index[0]);
- AI_SWAP2(pcGroupTris->v_index[1]);
- AI_SWAP2(pcGroupTris->v_index[2]);
-
- // iterate through all indices of the current triangle
- for (unsigned int c = 0; c < 3;++c,++iOutIndex) {
-
- // validate the vertex index
- unsigned int iIndex = pcGroupTris->v_index[c];
- if(iIndex > (unsigned int)groupInfo.pcGroup->numverts) {
- // (we might need to read this section a second time - to process frame vertices correctly)
- pcGroupTris->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1;
- DefaultLogger::get()->warn("Index overflow in MDL7 vertex list");
- }
-
- // write the output face index
- groupData.pcFaces[iTriangle].mIndices[2-c] = iOutIndex;
-
- aiVector3D& vPosition = groupData.vPositions[ iOutIndex ];
- vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex, pcHeader->mainvertex_stc_size) .x;
- vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
- vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
-
- // if we have bones, save the index
- if (!groupData.aiBones.empty()) {
- groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,
- iIndex,pcHeader->mainvertex_stc_size).vertindex;
- }
-
- // now read the normal vector
- if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) {
- // read the full normal vector
- aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
- vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0];
- AI_SWAP4(vNormal.x);
- vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
- AI_SWAP4(vNormal.y);
- vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
- AI_SWAP4(vNormal.z);
- }
- else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) {
- // read the normal vector from Quake2's smart table
- aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
- MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,
- pcHeader->mainvertex_stc_size) .norm162index,vNormal);
- }
- // validate and process the first uv coordinate set
- if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) {
-
- if (groupInfo.pcGroup->num_stpts) {
- AI_SWAP2(pcGroupTris->skinsets[0].st_index[0]);
- AI_SWAP2(pcGroupTris->skinsets[0].st_index[1]);
- AI_SWAP2(pcGroupTris->skinsets[0].st_index[2]);
-
- iIndex = pcGroupTris->skinsets[0].st_index[c];
- if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
- iIndex = groupInfo.pcGroup->num_stpts-1;
- DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#1)");
- }
-
- float u = groupInfo.pcGroupUVs[iIndex].u;
- float v = 1.0f-groupInfo.pcGroupUVs[iIndex].v; // DX to OGL
-
- groupData.vTextureCoords1[iOutIndex].x = u;
- groupData.vTextureCoords1[iOutIndex].y = v;
- }
- // assign the material index, but only if it is existing
- if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX){
- AI_SWAP4(pcGroupTris->skinsets[0].material);
- groupData.pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material;
- }
- }
- // validate and process the second uv coordinate set
- if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
-
- if (groupInfo.pcGroup->num_stpts) {
- AI_SWAP2(pcGroupTris->skinsets[1].st_index[0]);
- AI_SWAP2(pcGroupTris->skinsets[1].st_index[1]);
- AI_SWAP2(pcGroupTris->skinsets[1].st_index[2]);
- AI_SWAP4(pcGroupTris->skinsets[1].material);
-
- iIndex = pcGroupTris->skinsets[1].st_index[c];
- if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
- iIndex = groupInfo.pcGroup->num_stpts-1;
- DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#2)");
- }
-
- float u = groupInfo.pcGroupUVs[ iIndex ].u;
- float v = 1.0f-groupInfo.pcGroupUVs[ iIndex ].v;
-
- groupData.vTextureCoords2[ iOutIndex ].x = u;
- groupData.vTextureCoords2[ iOutIndex ].y = v; // DX to OGL
-
- // check whether we do really need the second texture
- // coordinate set ... wastes memory and loading time
- if (0 != iIndex && (u != groupData.vTextureCoords1[ iOutIndex ].x ||
- v != groupData.vTextureCoords1[ iOutIndex ].y ) )
- groupData.bNeed2UV = true;
-
- // if the material differs, we need a second skin, too
- if (pcGroupTris->skinsets[ 1 ].material != pcGroupTris->skinsets[ 0 ].material)
- groupData.bNeed2UV = true;
- }
- // assign the material index
- groupData.pcFaces[ iTriangle ].iMatIndex[ 1 ] = pcGroupTris->skinsets[ 1 ].material;
- }
- }
- // get the next triangle in the list
- pcGroupTris = (MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size);
- }
+ const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+ MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
+
+ // iterate through all triangles and build valid display lists
+ unsigned int iOutIndex = 0;
+ for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) {
+ AI_SWAP2(pcGroupTris->v_index[0]);
+ AI_SWAP2(pcGroupTris->v_index[1]);
+ AI_SWAP2(pcGroupTris->v_index[2]);
+
+ // iterate through all indices of the current triangle
+ for (unsigned int c = 0; c < 3;++c,++iOutIndex) {
+
+ // validate the vertex index
+ unsigned int iIndex = pcGroupTris->v_index[c];
+ if(iIndex > (unsigned int)groupInfo.pcGroup->numverts) {
+ // (we might need to read this section a second time - to process frame vertices correctly)
+ pcGroupTris->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1;
+ DefaultLogger::get()->warn("Index overflow in MDL7 vertex list");
+ }
+
+ // write the output face index
+ groupData.pcFaces[iTriangle].mIndices[2-c] = iOutIndex;
+
+ aiVector3D& vPosition = groupData.vPositions[ iOutIndex ];
+ vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex, pcHeader->mainvertex_stc_size) .x;
+ vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
+ vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
+
+ // if we have bones, save the index
+ if (!groupData.aiBones.empty()) {
+ groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,
+ iIndex,pcHeader->mainvertex_stc_size).vertindex;
+ }
+
+ // now read the normal vector
+ if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) {
+ // read the full normal vector
+ aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
+ vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0];
+ AI_SWAP4(vNormal.x);
+ vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
+ AI_SWAP4(vNormal.y);
+ vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
+ AI_SWAP4(vNormal.z);
+ }
+ else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) {
+ // read the normal vector from Quake2's smart table
+ aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
+ MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,
+ pcHeader->mainvertex_stc_size) .norm162index,vNormal);
+ }
+ // validate and process the first uv coordinate set
+ if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) {
+
+ if (groupInfo.pcGroup->num_stpts) {
+ AI_SWAP2(pcGroupTris->skinsets[0].st_index[0]);
+ AI_SWAP2(pcGroupTris->skinsets[0].st_index[1]);
+ AI_SWAP2(pcGroupTris->skinsets[0].st_index[2]);
+
+ iIndex = pcGroupTris->skinsets[0].st_index[c];
+ if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
+ iIndex = groupInfo.pcGroup->num_stpts-1;
+ DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#1)");
+ }
+
+ float u = groupInfo.pcGroupUVs[iIndex].u;
+ float v = 1.0f-groupInfo.pcGroupUVs[iIndex].v; // DX to OGL
+
+ groupData.vTextureCoords1[iOutIndex].x = u;
+ groupData.vTextureCoords1[iOutIndex].y = v;
+ }
+ // assign the material index, but only if it is existing
+ if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX){
+ AI_SWAP4(pcGroupTris->skinsets[0].material);
+ groupData.pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material;
+ }
+ }
+ // validate and process the second uv coordinate set
+ if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
+
+ if (groupInfo.pcGroup->num_stpts) {
+ AI_SWAP2(pcGroupTris->skinsets[1].st_index[0]);
+ AI_SWAP2(pcGroupTris->skinsets[1].st_index[1]);
+ AI_SWAP2(pcGroupTris->skinsets[1].st_index[2]);
+ AI_SWAP4(pcGroupTris->skinsets[1].material);
+
+ iIndex = pcGroupTris->skinsets[1].st_index[c];
+ if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
+ iIndex = groupInfo.pcGroup->num_stpts-1;
+ DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#2)");
+ }
+
+ float u = groupInfo.pcGroupUVs[ iIndex ].u;
+ float v = 1.0f-groupInfo.pcGroupUVs[ iIndex ].v;
+
+ groupData.vTextureCoords2[ iOutIndex ].x = u;
+ groupData.vTextureCoords2[ iOutIndex ].y = v; // DX to OGL
+
+ // check whether we do really need the second texture
+ // coordinate set ... wastes memory and loading time
+ if (0 != iIndex && (u != groupData.vTextureCoords1[ iOutIndex ].x ||
+ v != groupData.vTextureCoords1[ iOutIndex ].y ) )
+ groupData.bNeed2UV = true;
+
+ // if the material differs, we need a second skin, too
+ if (pcGroupTris->skinsets[ 1 ].material != pcGroupTris->skinsets[ 0 ].material)
+ groupData.bNeed2UV = true;
+ }
+ // assign the material index
+ groupData.pcFaces[ iTriangle ].iMatIndex[ 1 ] = pcGroupTris->skinsets[ 1 ].material;
+ }
+ }
+ // get the next triangle in the list
+ pcGroupTris = (MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size);
+ }
}
// ------------------------------------------------------------------------------------------------
// handle frames in a MDL7 file
bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSharedData_MDL7& shared,
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut)
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSharedData_MDL7& shared,
+ const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut)
{
- ai_assert(NULL != szCurrent && NULL != szCurrentOut);
- const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer;
-
- // if we have no bones we can simply skip all frames,
- // otherwise we'll need to process them.
- // FIX: If we need another frame than the first we must apply frame vertex replacements ...
- for(unsigned int iFrame = 0; iFrame < (unsigned int)groupInfo.pcGroup->numframes;++iFrame) {
- MDL::IntFrameInfo_MDL7 frame ((BE_NCONST MDL::Frame_MDL7*)szCurrent,iFrame);
-
- AI_SWAP4(frame.pcFrame->vertices_count);
- AI_SWAP4(frame.pcFrame->transmatrix_count);
-
- const unsigned int iAdd = pcHeader->frame_stc_size +
- frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size +
- frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size;
-
- if (((const char*)szCurrent - (const char*)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) {
- DefaultLogger::get()->warn("Index overflow in frame area. "
- "Ignoring all frames and all further mesh groups, too.");
-
- // don't parse more groups if we can't even read one
- // FIXME: sometimes this seems to occur even for valid files ...
- *szCurrentOut = szCurrent;
- return false;
- }
- // our output frame?
- if (configFrameID == iFrame) {
- BE_NCONST MDL::Vertex_MDL7* pcFrameVertices = (BE_NCONST MDL::Vertex_MDL7*)(szCurrent+pcHeader->frame_stc_size);
-
- for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count;++qq) {
- // I assume this are simple replacements for normal vertices, the bone index serving
- // as the index of the vertex to be replaced.
- uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices,qq,pcHeader->framevertex_stc_size,MDL::Vertex_MDL7).vertindex;
- AI_SWAP2(iIndex);
- if (iIndex >= groupInfo.pcGroup->numverts) {
- DefaultLogger::get()->warn("Invalid vertex index in frame vertex section");
- continue;
- }
-
- aiVector3D vPosition,vNormal;
-
- vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .x;
- AI_SWAP4(vPosition.x);
- vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y;
- AI_SWAP4(vPosition.y);
- vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z;
- AI_SWAP4(vPosition.z);
-
- // now read the normal vector
- if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) {
- // read the full normal vector
- vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[0];
- AI_SWAP4(vNormal.x);
- vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1];
- AI_SWAP4(vNormal.y);
- vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2];
- AI_SWAP4(vNormal.z);
- }
- else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) {
- // read the normal vector from Quake2's smart table
- MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,
- pcHeader->framevertex_stc_size) .norm162index,vNormal);
- }
-
- // FIXME: O(n^2) at the moment ...
- BE_NCONST MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
- unsigned int iOutIndex = 0;
- for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) {
- // iterate through all indices of the current triangle
- for (unsigned int c = 0; c < 3;++c,++iOutIndex) {
- // replace the vertex with the new data
- const unsigned int iCurIndex = pcGroupTris->v_index[c];
- if (iCurIndex == iIndex) {
- groupData.vPositions[iOutIndex] = vPosition;
- groupData.vNormals[iOutIndex] = vNormal;
- }
- }
- // get the next triangle in the list
- pcGroupTris = (BE_NCONST MDL::Triangle_MDL7*)((const char*)
- pcGroupTris + pcHeader->triangle_stc_size);
- }
- }
- }
- // parse bone trafo matrix keys (only if there are bones ...)
- if (shared.apcOutBones) {
- ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared);
- }
- szCurrent += iAdd;
- }
- *szCurrentOut = szCurrent;
- return true;
+ ai_assert(NULL != szCurrent && NULL != szCurrentOut);
+ const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer;
+
+ // if we have no bones we can simply skip all frames,
+ // otherwise we'll need to process them.
+ // FIX: If we need another frame than the first we must apply frame vertex replacements ...
+ for(unsigned int iFrame = 0; iFrame < (unsigned int)groupInfo.pcGroup->numframes;++iFrame) {
+ MDL::IntFrameInfo_MDL7 frame ((BE_NCONST MDL::Frame_MDL7*)szCurrent,iFrame);
+
+ AI_SWAP4(frame.pcFrame->vertices_count);
+ AI_SWAP4(frame.pcFrame->transmatrix_count);
+
+ const unsigned int iAdd = pcHeader->frame_stc_size +
+ frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size +
+ frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size;
+
+ if (((const char*)szCurrent - (const char*)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) {
+ DefaultLogger::get()->warn("Index overflow in frame area. "
+ "Ignoring all frames and all further mesh groups, too.");
+
+ // don't parse more groups if we can't even read one
+ // FIXME: sometimes this seems to occur even for valid files ...
+ *szCurrentOut = szCurrent;
+ return false;
+ }
+ // our output frame?
+ if (configFrameID == iFrame) {
+ BE_NCONST MDL::Vertex_MDL7* pcFrameVertices = (BE_NCONST MDL::Vertex_MDL7*)(szCurrent+pcHeader->frame_stc_size);
+
+ for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count;++qq) {
+ // I assume this are simple replacements for normal vertices, the bone index serving
+ // as the index of the vertex to be replaced.
+ uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices,qq,pcHeader->framevertex_stc_size,MDL::Vertex_MDL7).vertindex;
+ AI_SWAP2(iIndex);
+ if (iIndex >= groupInfo.pcGroup->numverts) {
+ DefaultLogger::get()->warn("Invalid vertex index in frame vertex section");
+ continue;
+ }
+
+ aiVector3D vPosition,vNormal;
+
+ vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .x;
+ AI_SWAP4(vPosition.x);
+ vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y;
+ AI_SWAP4(vPosition.y);
+ vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z;
+ AI_SWAP4(vPosition.z);
+
+ // now read the normal vector
+ if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) {
+ // read the full normal vector
+ vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[0];
+ AI_SWAP4(vNormal.x);
+ vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1];
+ AI_SWAP4(vNormal.y);
+ vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2];
+ AI_SWAP4(vNormal.z);
+ }
+ else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) {
+ // read the normal vector from Quake2's smart table
+ MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,
+ pcHeader->framevertex_stc_size) .norm162index,vNormal);
+ }
+
+ // FIXME: O(n^2) at the moment ...
+ BE_NCONST MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
+ unsigned int iOutIndex = 0;
+ for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) {
+ // iterate through all indices of the current triangle
+ for (unsigned int c = 0; c < 3;++c,++iOutIndex) {
+ // replace the vertex with the new data
+ const unsigned int iCurIndex = pcGroupTris->v_index[c];
+ if (iCurIndex == iIndex) {
+ groupData.vPositions[iOutIndex] = vPosition;
+ groupData.vNormals[iOutIndex] = vNormal;
+ }
+ }
+ // get the next triangle in the list
+ pcGroupTris = (BE_NCONST MDL::Triangle_MDL7*)((const char*)
+ pcGroupTris + pcHeader->triangle_stc_size);
+ }
+ }
+ }
+ // parse bone trafo matrix keys (only if there are bones ...)
+ if (shared.apcOutBones) {
+ ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared);
+ }
+ szCurrent += iAdd;
+ }
+ *szCurrentOut = szCurrent;
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Sort faces by material, handle multiple UVs correctly
void MDLImporter::SortByMaterials_3DGS_MDL7(
- const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSplitGroupData_MDL7& splitGroupData)
+ const MDL::IntGroupInfo_MDL7& groupInfo,
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSplitGroupData_MDL7& splitGroupData)
{
- const unsigned int iNumMaterials = (unsigned int)splitGroupData.shared.pcMats.size();
- if (!groupData.bNeed2UV) {
- // if we don't need a second set of texture coordinates there is no reason to keep it in memory ...
- groupData.vTextureCoords2.clear();
-
- // allocate the array
- splitGroupData.aiSplit = new std::vector<unsigned int>*[iNumMaterials];
-
- for (unsigned int m = 0; m < iNumMaterials;++m)
- splitGroupData.aiSplit[m] = new std::vector<unsigned int>();
-
- // iterate through all faces and sort by material
- for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) {
- // check range
- if (groupData.pcFaces[iFace].iMatIndex[0] >= iNumMaterials) {
- // use the last material instead
- splitGroupData.aiSplit[iNumMaterials-1]->push_back(iFace);
-
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- if(0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0])
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]");
- }
- else splitGroupData.aiSplit[groupData.pcFaces[iFace].
- iMatIndex[0]]->push_back(iFace);
- }
- }
- else
- {
- // we need to build combined materials for each combination of
- std::vector<MDL::IntMaterial_MDL7> avMats;
- avMats.reserve(iNumMaterials*2);
-
- // fixme: why on the heap?
- std::vector<std::vector<unsigned int>* > aiTempSplit(iNumMaterials*2);
- for (unsigned int m = 0; m < iNumMaterials;++m)
- aiTempSplit[m] = new std::vector<unsigned int>();
-
- // iterate through all faces and sort by material
- for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) {
- // check range
- unsigned int iMatIndex = groupData.pcFaces[iFace].iMatIndex[0];
- if (iMatIndex >= iNumMaterials) {
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- if(UINT_MAX != iMatIndex)
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]");
- iMatIndex = iNumMaterials-1;
- }
- unsigned int iMatIndex2 = groupData.pcFaces[iFace].iMatIndex[1];
-
- unsigned int iNum = iMatIndex;
- if (UINT_MAX != iMatIndex2 && iMatIndex != iMatIndex2) {
- if (iMatIndex2 >= iNumMaterials) {
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]");
- iMatIndex2 = iNumMaterials-1;
- }
-
- // do a slow seach in the list ...
- iNum = 0;
- bool bFound = false;
- for (std::vector<MDL::IntMaterial_MDL7>::iterator i = avMats.begin();i != avMats.end();++i,++iNum){
- if ((*i).iOldMatIndices[0] == iMatIndex && (*i).iOldMatIndices[1] == iMatIndex2) {
- // reuse this material
- bFound = true;
- break;
- }
- }
- if (!bFound) {
- // build a new material ...
- MDL::IntMaterial_MDL7 sHelper;
- sHelper.pcMat = new aiMaterial();
- sHelper.iOldMatIndices[0] = iMatIndex;
- sHelper.iOldMatIndices[1] = iMatIndex2;
- JoinSkins_3DGS_MDL7(splitGroupData.shared.pcMats[iMatIndex],
- splitGroupData.shared.pcMats[iMatIndex2],sHelper.pcMat);
-
- // and add it to the list
- avMats.push_back(sHelper);
- iNum = (unsigned int)avMats.size()-1;
- }
- // adjust the size of the file array
- if (iNum == aiTempSplit.size()) {
- aiTempSplit.push_back(new std::vector<unsigned int>());
- }
- }
- aiTempSplit[iNum]->push_back(iFace);
- }
-
- // now add the newly created materials to the old list
- if (0 == groupInfo.iIndex) {
- splitGroupData.shared.pcMats.resize(avMats.size());
- for (unsigned int o = 0; o < avMats.size();++o)
- splitGroupData.shared.pcMats[o] = avMats[o].pcMat;
- }
- else {
- // This might result in redundant materials ...
- splitGroupData.shared.pcMats.resize(iNumMaterials + avMats.size());
- for (unsigned int o = iNumMaterials; o < avMats.size();++o)
- splitGroupData.shared.pcMats[o] = avMats[o].pcMat;
- }
-
- // and build the final face-to-material array
- splitGroupData.aiSplit = new std::vector<unsigned int>*[aiTempSplit.size()];
- for (unsigned int m = 0; m < iNumMaterials;++m)
- splitGroupData.aiSplit[m] = aiTempSplit[m];
- }
+ const unsigned int iNumMaterials = (unsigned int)splitGroupData.shared.pcMats.size();
+ if (!groupData.bNeed2UV) {
+ // if we don't need a second set of texture coordinates there is no reason to keep it in memory ...
+ groupData.vTextureCoords2.clear();
+
+ // allocate the array
+ splitGroupData.aiSplit = new std::vector<unsigned int>*[iNumMaterials];
+
+ for (unsigned int m = 0; m < iNumMaterials;++m)
+ splitGroupData.aiSplit[m] = new std::vector<unsigned int>();
+
+ // iterate through all faces and sort by material
+ for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) {
+ // check range
+ if (groupData.pcFaces[iFace].iMatIndex[0] >= iNumMaterials) {
+ // use the last material instead
+ splitGroupData.aiSplit[iNumMaterials-1]->push_back(iFace);
+
+ // sometimes MED writes -1, but normally only if there is only
+ // one skin assigned. No warning in this case
+ if(0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0])
+ DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]");
+ }
+ else splitGroupData.aiSplit[groupData.pcFaces[iFace].
+ iMatIndex[0]]->push_back(iFace);
+ }
+ }
+ else
+ {
+ // we need to build combined materials for each combination of
+ std::vector<MDL::IntMaterial_MDL7> avMats;
+ avMats.reserve(iNumMaterials*2);
+
+ // fixme: why on the heap?
+ std::vector<std::vector<unsigned int>* > aiTempSplit(iNumMaterials*2);
+ for (unsigned int m = 0; m < iNumMaterials;++m)
+ aiTempSplit[m] = new std::vector<unsigned int>();
+
+ // iterate through all faces and sort by material
+ for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) {
+ // check range
+ unsigned int iMatIndex = groupData.pcFaces[iFace].iMatIndex[0];
+ if (iMatIndex >= iNumMaterials) {
+ // sometimes MED writes -1, but normally only if there is only
+ // one skin assigned. No warning in this case
+ if(UINT_MAX != iMatIndex)
+ DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]");
+ iMatIndex = iNumMaterials-1;
+ }
+ unsigned int iMatIndex2 = groupData.pcFaces[iFace].iMatIndex[1];
+
+ unsigned int iNum = iMatIndex;
+ if (UINT_MAX != iMatIndex2 && iMatIndex != iMatIndex2) {
+ if (iMatIndex2 >= iNumMaterials) {
+ // sometimes MED writes -1, but normally only if there is only
+ // one skin assigned. No warning in this case
+ DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]");
+ iMatIndex2 = iNumMaterials-1;
+ }
+
+ // do a slow search in the list ...
+ iNum = 0;
+ bool bFound = false;
+ for (std::vector<MDL::IntMaterial_MDL7>::iterator i = avMats.begin();i != avMats.end();++i,++iNum){
+ if ((*i).iOldMatIndices[0] == iMatIndex && (*i).iOldMatIndices[1] == iMatIndex2) {
+ // reuse this material
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound) {
+ // build a new material ...
+ MDL::IntMaterial_MDL7 sHelper;
+ sHelper.pcMat = new aiMaterial();
+ sHelper.iOldMatIndices[0] = iMatIndex;
+ sHelper.iOldMatIndices[1] = iMatIndex2;
+ JoinSkins_3DGS_MDL7(splitGroupData.shared.pcMats[iMatIndex],
+ splitGroupData.shared.pcMats[iMatIndex2],sHelper.pcMat);
+
+ // and add it to the list
+ avMats.push_back(sHelper);
+ iNum = (unsigned int)avMats.size()-1;
+ }
+ // adjust the size of the file array
+ if (iNum == aiTempSplit.size()) {
+ aiTempSplit.push_back(new std::vector<unsigned int>());
+ }
+ }
+ aiTempSplit[iNum]->push_back(iFace);
+ }
+
+ // now add the newly created materials to the old list
+ if (0 == groupInfo.iIndex) {
+ splitGroupData.shared.pcMats.resize(avMats.size());
+ for (unsigned int o = 0; o < avMats.size();++o)
+ splitGroupData.shared.pcMats[o] = avMats[o].pcMat;
+ }
+ else {
+ // This might result in redundant materials ...
+ splitGroupData.shared.pcMats.resize(iNumMaterials + avMats.size());
+ for (unsigned int o = iNumMaterials; o < avMats.size();++o)
+ splitGroupData.shared.pcMats[o] = avMats[o].pcMat;
+ }
+
+ // and build the final face-to-material array
+ splitGroupData.aiSplit = new std::vector<unsigned int>*[aiTempSplit.size()];
+ for (unsigned int m = 0; m < iNumMaterials;++m)
+ splitGroupData.aiSplit[m] = aiTempSplit[m];
+ }
}
// ------------------------------------------------------------------------------------------------
// Read a MDL7 file
void MDLImporter::InternReadFile_3DGS_MDL7( )
{
- ai_assert(NULL != pScene);
-
- MDL::IntSharedData_MDL7 sharedData;
-
- // current cursor position in the file
- BE_NCONST MDL::Header_MDL7 *pcHeader = (BE_NCONST MDL::Header_MDL7*)this->mBuffer;
- const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
-
- AI_SWAP4(pcHeader->version);
- AI_SWAP4(pcHeader->bones_num);
- AI_SWAP4(pcHeader->groups_num);
- AI_SWAP4(pcHeader->data_size);
- AI_SWAP4(pcHeader->entlump_size);
- AI_SWAP4(pcHeader->medlump_size);
- AI_SWAP2(pcHeader->bone_stc_size);
- AI_SWAP2(pcHeader->skin_stc_size);
- AI_SWAP2(pcHeader->colorvalue_stc_size);
- AI_SWAP2(pcHeader->material_stc_size);
- AI_SWAP2(pcHeader->skinpoint_stc_size);
- AI_SWAP2(pcHeader->triangle_stc_size);
- AI_SWAP2(pcHeader->mainvertex_stc_size);
- AI_SWAP2(pcHeader->framevertex_stc_size);
- AI_SWAP2(pcHeader->bonetrans_stc_size);
- AI_SWAP2(pcHeader->frame_stc_size);
-
- // validate the header of the file. There are some structure
- // sizes that are expected by the loader to be constant
- this->ValidateHeader_3DGS_MDL7(pcHeader);
-
- // load all bones (they are shared by all groups, so
- // we'll need to add them to all groups/meshes later)
- // apcBonesOut is a list of all bones or NULL if they could not been loaded
- szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
- sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
-
- // vector to held all created meshes
- std::vector<aiMesh*>* avOutList;
-
- // 3 meshes per group - that should be OK for most models
- avOutList = new std::vector<aiMesh*>[pcHeader->groups_num];
- for (uint32_t i = 0; i < pcHeader->groups_num;++i)
- avOutList[i].reserve(3);
-
- // buffer to held the names of all groups in the file
- char* aszGroupNameBuffer = new char[AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num];
-
- // read all groups
- for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup) {
- MDL::IntGroupInfo_MDL7 groupInfo((BE_NCONST MDL::Group_MDL7*)szCurrent,iGroup);
- szCurrent = (const unsigned char*)(groupInfo.pcGroup+1);
-
- VALIDATE_FILE_SIZE(szCurrent);
-
- AI_SWAP4(groupInfo.pcGroup->groupdata_size);
- AI_SWAP4(groupInfo.pcGroup->numskins);
- AI_SWAP4(groupInfo.pcGroup->num_stpts);
- AI_SWAP4(groupInfo.pcGroup->numtris);
- AI_SWAP4(groupInfo.pcGroup->numverts);
- AI_SWAP4(groupInfo.pcGroup->numframes);
-
- if (1 != groupInfo.pcGroup->typ) {
- // Not a triangle-based mesh
- DefaultLogger::get()->warn("[3DGS MDL7] Not a triangle mesh group. Continuing happily");
- }
-
- // store the name of the group
- const unsigned int ofs = iGroup*AI_MDL7_MAX_GROUPNAMESIZE;
- ::memcpy(&aszGroupNameBuffer[ofs],
- groupInfo.pcGroup->name,AI_MDL7_MAX_GROUPNAMESIZE);
-
- // make sure '\0' is at the end
- aszGroupNameBuffer[ofs+AI_MDL7_MAX_GROUPNAMESIZE-1] = '\0';
-
- // read all skins
- sharedData.pcMats.reserve(sharedData.pcMats.size() + groupInfo.pcGroup->numskins);
- sharedData.abNeedMaterials.resize(sharedData.abNeedMaterials.size() +
- groupInfo.pcGroup->numskins,false);
-
- for (unsigned int iSkin = 0; iSkin < (unsigned int)groupInfo.pcGroup->numskins;++iSkin) {
- ParseSkinLump_3DGS_MDL7(szCurrent,&szCurrent,sharedData.pcMats);
- }
- // if we have absolutely no skin loaded we need to generate a default material
- if (sharedData.pcMats.empty()) {
- const int iMode = (int)aiShadingMode_Gouraud;
- sharedData.pcMats.push_back(new aiMaterial());
- aiMaterial* pcHelper = (aiMaterial*)sharedData.pcMats[0];
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.6f;
- 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);
-
- sharedData.abNeedMaterials.resize(1,false);
- }
-
- // now get a pointer to all texture coords in the group
- groupInfo.pcGroupUVs = (BE_NCONST MDL::TexCoord_MDL7*)szCurrent;
- for(int i = 0; i < groupInfo.pcGroup->num_stpts; ++i){
- AI_SWAP4(groupInfo.pcGroupUVs[i].u);
- AI_SWAP4(groupInfo.pcGroupUVs[i].v);
- }
- szCurrent += pcHeader->skinpoint_stc_size * groupInfo.pcGroup->num_stpts;
-
- // now get a pointer to all triangle in the group
- groupInfo.pcGroupTris = (Triangle_MDL7*)szCurrent;
- szCurrent += pcHeader->triangle_stc_size * groupInfo.pcGroup->numtris;
-
- // now get a pointer to all vertices in the group
- groupInfo.pcGroupVerts = (BE_NCONST MDL::Vertex_MDL7*)szCurrent;
- for(int i = 0; i < groupInfo.pcGroup->numverts; ++i){
- AI_SWAP4(groupInfo.pcGroupVerts[i].x);
- AI_SWAP4(groupInfo.pcGroupVerts[i].y);
- AI_SWAP4(groupInfo.pcGroupVerts[i].z);
-
- AI_SWAP2(groupInfo.pcGroupVerts[i].vertindex);
- //We can not swap the normal information now as we don't know which of the two kinds it is
- }
- szCurrent += pcHeader->mainvertex_stc_size * groupInfo.pcGroup->numverts;
- VALIDATE_FILE_SIZE(szCurrent);
-
- MDL::IntSplitGroupData_MDL7 splitGroupData(sharedData,avOutList[iGroup]);
- MDL::IntGroupData_MDL7 groupData;
- if (groupInfo.pcGroup->numtris && groupInfo.pcGroup->numverts)
- {
- // build output vectors
- const unsigned int iNumVertices = groupInfo.pcGroup->numtris*3;
- groupData.vPositions.resize(iNumVertices);
- groupData.vNormals.resize(iNumVertices);
-
- if (sharedData.apcOutBones)groupData.aiBones.resize(iNumVertices,UINT_MAX);
-
- // it is also possible that there are 0 UV coordinate sets
- if (groupInfo.pcGroup->num_stpts){
- groupData.vTextureCoords1.resize(iNumVertices,aiVector3D());
-
- // check whether the triangle data structure is large enough
- // to contain a second UV coodinate set
- if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
- groupData.vTextureCoords2.resize(iNumVertices,aiVector3D());
- groupData.bNeed2UV = true;
- }
- }
- groupData.pcFaces = new MDL::IntFace_MDL7[groupInfo.pcGroup->numtris];
-
- // read all faces into the preallocated arrays
- ReadFaces_3DGS_MDL7(groupInfo, groupData);
-
- // sort by materials
- SortByMaterials_3DGS_MDL7(groupInfo, groupData,
- splitGroupData);
-
- for (unsigned int qq = 0; qq < sharedData.pcMats.size();++qq) {
- if (!splitGroupData.aiSplit[qq]->empty())
- sharedData.abNeedMaterials[qq] = true;
+ ai_assert(NULL != pScene);
+
+ MDL::IntSharedData_MDL7 sharedData;
+
+ // current cursor position in the file
+ BE_NCONST MDL::Header_MDL7 *pcHeader = (BE_NCONST MDL::Header_MDL7*)this->mBuffer;
+ const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
+
+ AI_SWAP4(pcHeader->version);
+ AI_SWAP4(pcHeader->bones_num);
+ AI_SWAP4(pcHeader->groups_num);
+ AI_SWAP4(pcHeader->data_size);
+ AI_SWAP4(pcHeader->entlump_size);
+ AI_SWAP4(pcHeader->medlump_size);
+ AI_SWAP2(pcHeader->bone_stc_size);
+ AI_SWAP2(pcHeader->skin_stc_size);
+ AI_SWAP2(pcHeader->colorvalue_stc_size);
+ AI_SWAP2(pcHeader->material_stc_size);
+ AI_SWAP2(pcHeader->skinpoint_stc_size);
+ AI_SWAP2(pcHeader->triangle_stc_size);
+ AI_SWAP2(pcHeader->mainvertex_stc_size);
+ AI_SWAP2(pcHeader->framevertex_stc_size);
+ AI_SWAP2(pcHeader->bonetrans_stc_size);
+ AI_SWAP2(pcHeader->frame_stc_size);
+
+ // validate the header of the file. There are some structure
+ // sizes that are expected by the loader to be constant
+ this->ValidateHeader_3DGS_MDL7(pcHeader);
+
+ // load all bones (they are shared by all groups, so
+ // we'll need to add them to all groups/meshes later)
+ // apcBonesOut is a list of all bones or NULL if they could not been loaded
+ szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
+ sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
+
+ // vector to held all created meshes
+ std::vector<aiMesh*>* avOutList;
+
+ // 3 meshes per group - that should be OK for most models
+ avOutList = new std::vector<aiMesh*>[pcHeader->groups_num];
+ for (uint32_t i = 0; i < pcHeader->groups_num;++i)
+ avOutList[i].reserve(3);
+
+ // buffer to held the names of all groups in the file
+ const size_t buffersize( AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num );
+ char* aszGroupNameBuffer = new char[ buffersize ];
+
+ // read all groups
+ for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup) {
+ MDL::IntGroupInfo_MDL7 groupInfo((BE_NCONST MDL::Group_MDL7*)szCurrent,iGroup);
+ szCurrent = (const unsigned char*)(groupInfo.pcGroup+1);
+
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ AI_SWAP4(groupInfo.pcGroup->groupdata_size);
+ AI_SWAP4(groupInfo.pcGroup->numskins);
+ AI_SWAP4(groupInfo.pcGroup->num_stpts);
+ AI_SWAP4(groupInfo.pcGroup->numtris);
+ AI_SWAP4(groupInfo.pcGroup->numverts);
+ AI_SWAP4(groupInfo.pcGroup->numframes);
+
+ if (1 != groupInfo.pcGroup->typ) {
+ // Not a triangle-based mesh
+ DefaultLogger::get()->warn("[3DGS MDL7] Not a triangle mesh group. Continuing happily");
+ }
+
+ // store the name of the group
+ const unsigned int ofs = iGroup*AI_MDL7_MAX_GROUPNAMESIZE;
+ ::memcpy(&aszGroupNameBuffer[ofs],
+ groupInfo.pcGroup->name,AI_MDL7_MAX_GROUPNAMESIZE);
+
+ // make sure '\0' is at the end
+ aszGroupNameBuffer[ofs+AI_MDL7_MAX_GROUPNAMESIZE-1] = '\0';
+
+ // read all skins
+ sharedData.pcMats.reserve(sharedData.pcMats.size() + groupInfo.pcGroup->numskins);
+ sharedData.abNeedMaterials.resize(sharedData.abNeedMaterials.size() +
+ groupInfo.pcGroup->numskins,false);
+
+ for (unsigned int iSkin = 0; iSkin < (unsigned int)groupInfo.pcGroup->numskins;++iSkin) {
+ ParseSkinLump_3DGS_MDL7(szCurrent,&szCurrent,sharedData.pcMats);
+ }
+ // if we have absolutely no skin loaded we need to generate a default material
+ if (sharedData.pcMats.empty()) {
+ const int iMode = (int)aiShadingMode_Gouraud;
+ sharedData.pcMats.push_back(new aiMaterial());
+ aiMaterial* pcHelper = (aiMaterial*)sharedData.pcMats[0];
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 0.6f;
+ 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);
+
+ sharedData.abNeedMaterials.resize(1,false);
+ }
+
+ // now get a pointer to all texture coords in the group
+ groupInfo.pcGroupUVs = (BE_NCONST MDL::TexCoord_MDL7*)szCurrent;
+ for(int i = 0; i < groupInfo.pcGroup->num_stpts; ++i){
+ AI_SWAP4(groupInfo.pcGroupUVs[i].u);
+ AI_SWAP4(groupInfo.pcGroupUVs[i].v);
+ }
+ szCurrent += pcHeader->skinpoint_stc_size * groupInfo.pcGroup->num_stpts;
+
+ // now get a pointer to all triangle in the group
+ groupInfo.pcGroupTris = (Triangle_MDL7*)szCurrent;
+ szCurrent += pcHeader->triangle_stc_size * groupInfo.pcGroup->numtris;
+
+ // now get a pointer to all vertices in the group
+ groupInfo.pcGroupVerts = (BE_NCONST MDL::Vertex_MDL7*)szCurrent;
+ for(int i = 0; i < groupInfo.pcGroup->numverts; ++i){
+ AI_SWAP4(groupInfo.pcGroupVerts[i].x);
+ AI_SWAP4(groupInfo.pcGroupVerts[i].y);
+ AI_SWAP4(groupInfo.pcGroupVerts[i].z);
+
+ AI_SWAP2(groupInfo.pcGroupVerts[i].vertindex);
+ //We can not swap the normal information now as we don't know which of the two kinds it is
+ }
+ szCurrent += pcHeader->mainvertex_stc_size * groupInfo.pcGroup->numverts;
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ MDL::IntSplitGroupData_MDL7 splitGroupData(sharedData,avOutList[iGroup]);
+ MDL::IntGroupData_MDL7 groupData;
+ if (groupInfo.pcGroup->numtris && groupInfo.pcGroup->numverts)
+ {
+ // build output vectors
+ const unsigned int iNumVertices = groupInfo.pcGroup->numtris*3;
+ groupData.vPositions.resize(iNumVertices);
+ groupData.vNormals.resize(iNumVertices);
+
+ if (sharedData.apcOutBones)groupData.aiBones.resize(iNumVertices,UINT_MAX);
+
+ // it is also possible that there are 0 UV coordinate sets
+ if (groupInfo.pcGroup->num_stpts){
+ groupData.vTextureCoords1.resize(iNumVertices,aiVector3D());
+
+ // check whether the triangle data structure is large enough
+ // to contain a second UV coodinate set
+ if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
+ groupData.vTextureCoords2.resize(iNumVertices,aiVector3D());
+ groupData.bNeed2UV = true;
+ }
+ }
+ groupData.pcFaces = new MDL::IntFace_MDL7[groupInfo.pcGroup->numtris];
+
+ // read all faces into the preallocated arrays
+ ReadFaces_3DGS_MDL7(groupInfo, groupData);
+
+ // sort by materials
+ SortByMaterials_3DGS_MDL7(groupInfo, groupData,
+ splitGroupData);
+
+ for (unsigned int qq = 0; qq < sharedData.pcMats.size();++qq) {
+ if (!splitGroupData.aiSplit[qq]->empty())
+ sharedData.abNeedMaterials[qq] = true;
+ }
+ }
+ else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 "
+ "vertices or faces. It will be skipped.");
+
+ // process all frames and generate output meshes
+ ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent);
+ GenerateOutputMeshes_3DGS_MDL7(groupData,splitGroupData);
+ }
+
+ // generate a nodegraph and subnodes for each group
+ pScene->mRootNode = new aiNode();
+
+ // now we need to build a final mesh list
+ for (uint32_t i = 0; i < pcHeader->groups_num;++i)
+ pScene->mNumMeshes += (unsigned int)avOutList[i].size();
+
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; {
+ unsigned int p = 0,q = 0;
+ for (uint32_t i = 0; i < pcHeader->groups_num;++i) {
+ for (unsigned int a = 0; a < avOutList[i].size();++a) {
+ pScene->mMeshes[p++] = avOutList[i][a];
+ }
+ if (!avOutList[i].empty())++pScene->mRootNode->mNumChildren;
+ }
+ // we will later need an extra node to serve as parent for all bones
+ if (sharedData.apcOutBones)++pScene->mRootNode->mNumChildren;
+ this->pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
+ p = 0;
+ for (uint32_t i = 0; i < pcHeader->groups_num;++i) {
+ if (avOutList[i].empty())continue;
+
+ aiNode* const pcNode = pScene->mRootNode->mChildren[p] = new aiNode();
+ pcNode->mNumMeshes = (unsigned int)avOutList[i].size();
+ pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
+ pcNode->mParent = this->pScene->mRootNode;
+ for (unsigned int a = 0; a < pcNode->mNumMeshes;++a)
+ pcNode->mMeshes[a] = q + a;
+ q += (unsigned int)avOutList[i].size();
+
+ // setup the name of the node
+ char* const szBuffer = &aszGroupNameBuffer[i*AI_MDL7_MAX_GROUPNAMESIZE];
+ if ('\0' == *szBuffer) {
+ const size_t maxSize(buffersize - (i*AI_MDL7_MAX_GROUPNAMESIZE));
+ pcNode->mName.length = ai_snprintf(szBuffer, maxSize, "Group_%u", p);
+ } else {
+ pcNode->mName.length = ::strlen(szBuffer);
}
- }
- else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 "
- "vertices or faces. It will be skipped.");
-
- // process all frames and generate output meshes
- ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent);
- GenerateOutputMeshes_3DGS_MDL7(groupData,splitGroupData);
- }
-
- // generate a nodegraph and subnodes for each group
- pScene->mRootNode = new aiNode();
-
- // now we need to build a final mesh list
- for (uint32_t i = 0; i < pcHeader->groups_num;++i)
- pScene->mNumMeshes += (unsigned int)avOutList[i].size();
-
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; {
- unsigned int p = 0,q = 0;
- for (uint32_t i = 0; i < pcHeader->groups_num;++i) {
- for (unsigned int a = 0; a < avOutList[i].size();++a) {
- pScene->mMeshes[p++] = avOutList[i][a];
- }
- if (!avOutList[i].empty())++pScene->mRootNode->mNumChildren;
- }
- // we will later need an extra node to serve as parent for all bones
- if (sharedData.apcOutBones)++pScene->mRootNode->mNumChildren;
- this->pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
- p = 0;
- for (uint32_t i = 0; i < pcHeader->groups_num;++i) {
- if (avOutList[i].empty())continue;
-
- aiNode* const pcNode = pScene->mRootNode->mChildren[p] = new aiNode();
- pcNode->mNumMeshes = (unsigned int)avOutList[i].size();
- pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
- pcNode->mParent = this->pScene->mRootNode;
- for (unsigned int a = 0; a < pcNode->mNumMeshes;++a)
- pcNode->mMeshes[a] = q + a;
- q += (unsigned int)avOutList[i].size();
-
- // setup the name of the node
- char* const szBuffer = &aszGroupNameBuffer[i*AI_MDL7_MAX_GROUPNAMESIZE];
- if ('\0' == *szBuffer)
- pcNode->mName.length = ::sprintf(szBuffer,"Group_%i",p);
- else pcNode->mName.length = ::strlen(szBuffer);
- ::strcpy(pcNode->mName.data,szBuffer);
- ++p;
- }
- }
-
- // if there is only one root node with a single child we can optimize it a bit ...
- if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) {
- aiNode* pcOldRoot = this->pScene->mRootNode;
- pScene->mRootNode = pcOldRoot->mChildren[0];
- pcOldRoot->mChildren[0] = NULL;
- delete pcOldRoot;
- pScene->mRootNode->mParent = NULL;
- }
- else pScene->mRootNode->mName.Set("<mesh_root>");
-
- delete[] avOutList;
- delete[] aszGroupNameBuffer;
- AI_DEBUG_INVALIDATE_PTR(avOutList);
- AI_DEBUG_INVALIDATE_PTR(aszGroupNameBuffer);
-
- // build a final material list.
- CopyMaterials_3DGS_MDL7(sharedData);
- HandleMaterialReferences_3DGS_MDL7();
-
- // generate output bone animations and add all bones to the scenegraph
- if (sharedData.apcOutBones) {
- // this step adds empty dummy bones to the nodegraph
- // insert another dummy node to avoid name conflicts
- aiNode* const pc = pScene->mRootNode->mChildren[pScene->mRootNode->mNumChildren-1] = new aiNode();
-
- pc->mName.Set("<skeleton_root>");
-
- // add bones to the nodegraph
- AddBonesToNodeGraph_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
- sharedData.apcOutBones,pc,0xffff);
-
- // this steps build a valid output animation
- BuildOutputAnims_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
- sharedData.apcOutBones);
- }
+ ::strcpy(pcNode->mName.data,szBuffer);
+ ++p;
+ }
+ }
+
+ // if there is only one root node with a single child we can optimize it a bit ...
+ if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) {
+ aiNode* pcOldRoot = this->pScene->mRootNode;
+ pScene->mRootNode = pcOldRoot->mChildren[0];
+ pcOldRoot->mChildren[0] = NULL;
+ delete pcOldRoot;
+ pScene->mRootNode->mParent = NULL;
+ }
+ else pScene->mRootNode->mName.Set("<mesh_root>");
+
+ delete[] avOutList;
+ delete[] aszGroupNameBuffer;
+ AI_DEBUG_INVALIDATE_PTR(avOutList);
+ AI_DEBUG_INVALIDATE_PTR(aszGroupNameBuffer);
+
+ // build a final material list.
+ CopyMaterials_3DGS_MDL7(sharedData);
+ HandleMaterialReferences_3DGS_MDL7();
+
+ // generate output bone animations and add all bones to the scenegraph
+ if (sharedData.apcOutBones) {
+ // this step adds empty dummy bones to the nodegraph
+ // insert another dummy node to avoid name conflicts
+ aiNode* const pc = pScene->mRootNode->mChildren[pScene->mRootNode->mNumChildren-1] = new aiNode();
+
+ pc->mName.Set("<skeleton_root>");
+
+ // add bones to the nodegraph
+ AddBonesToNodeGraph_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
+ sharedData.apcOutBones,pc,0xffff);
+
+ // this steps build a valid output animation
+ BuildOutputAnims_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
+ sharedData.apcOutBones);
+ }
}
// ------------------------------------------------------------------------------------------------
// Copy materials
void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared)
{
- pScene->mNumMaterials = (unsigned int)shared.pcMats.size();
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
- pScene->mMaterials[i] = shared.pcMats[i];
+ pScene->mNumMaterials = (unsigned int)shared.pcMats.size();
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+ pScene->mMaterials[i] = shared.pcMats[i];
}
@@ -1587,356 +1614,356 @@ void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared)
// Process material references
void MDLImporter::HandleMaterialReferences_3DGS_MDL7()
{
- // search for referrer materials
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
- int iIndex = 0;
- if (AI_SUCCESS == aiGetMaterialInteger(pScene->mMaterials[i],AI_MDL7_REFERRER_MATERIAL, &iIndex) ) {
- for (unsigned int a = 0; a < pScene->mNumMeshes;++a) {
- aiMesh* const pcMesh = pScene->mMeshes[a];
- if (i == pcMesh->mMaterialIndex) {
- pcMesh->mMaterialIndex = iIndex;
- }
- }
- // collapse the rest of the array
- delete pScene->mMaterials[i];
- for (unsigned int pp = i; pp < pScene->mNumMaterials-1;++pp) {
-
- pScene->mMaterials[pp] = pScene->mMaterials[pp+1];
- for (unsigned int a = 0; a < pScene->mNumMeshes;++a) {
- aiMesh* const pcMesh = pScene->mMeshes[a];
- if (pcMesh->mMaterialIndex > i)--pcMesh->mMaterialIndex;
- }
- }
- --pScene->mNumMaterials;
- }
- }
+ // search for referrer materials
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
+ int iIndex = 0;
+ if (AI_SUCCESS == aiGetMaterialInteger(pScene->mMaterials[i],AI_MDL7_REFERRER_MATERIAL, &iIndex) ) {
+ for (unsigned int a = 0; a < pScene->mNumMeshes;++a) {
+ aiMesh* const pcMesh = pScene->mMeshes[a];
+ if (i == pcMesh->mMaterialIndex) {
+ pcMesh->mMaterialIndex = iIndex;
+ }
+ }
+ // collapse the rest of the array
+ delete pScene->mMaterials[i];
+ for (unsigned int pp = i; pp < pScene->mNumMaterials-1;++pp) {
+
+ pScene->mMaterials[pp] = pScene->mMaterials[pp+1];
+ for (unsigned int a = 0; a < pScene->mNumMeshes;++a) {
+ aiMesh* const pcMesh = pScene->mMeshes[a];
+ if (pcMesh->mMaterialIndex > i)--pcMesh->mMaterialIndex;
+ }
+ }
+ --pScene->mNumMaterials;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Read bone transformation keys
void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7(
- const MDL::IntGroupInfo_MDL7& groupInfo,
- IntFrameInfo_MDL7& frame,
- MDL::IntSharedData_MDL7& shared)
+ const MDL::IntGroupInfo_MDL7& groupInfo,
+ IntFrameInfo_MDL7& frame,
+ MDL::IntSharedData_MDL7& shared)
{
- const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
-
- // only the first group contains bone animation keys
- if (frame.pcFrame->transmatrix_count) {
- if (!groupInfo.iIndex) {
- // skip all frames vertices. We can't support them
- const MDL::BoneTransform_MDL7* pcBoneTransforms = (const MDL::BoneTransform_MDL7*)
- (((const char*)frame.pcFrame) + pcHeader->frame_stc_size +
- frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size);
-
- // read all transformation matrices
- for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count;++iTrafo) {
- if(pcBoneTransforms->bone_index >= pcHeader->bones_num) {
- DefaultLogger::get()->warn("Index overflow in frame area. "
- "Unable to parse this bone transformation");
- }
- else {
- AddAnimationBoneTrafoKey_3DGS_MDL7(frame.iIndex,
- pcBoneTransforms,shared.apcOutBones);
- }
- pcBoneTransforms = (const MDL::BoneTransform_MDL7*)(
- (const char*)pcBoneTransforms + pcHeader->bonetrans_stc_size);
- }
- }
- else {
- DefaultLogger::get()->warn("Ignoring animation keyframes in groups != 0");
- }
- }
+ const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+
+ // only the first group contains bone animation keys
+ if (frame.pcFrame->transmatrix_count) {
+ if (!groupInfo.iIndex) {
+ // skip all frames vertices. We can't support them
+ const MDL::BoneTransform_MDL7* pcBoneTransforms = (const MDL::BoneTransform_MDL7*)
+ (((const char*)frame.pcFrame) + pcHeader->frame_stc_size +
+ frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size);
+
+ // read all transformation matrices
+ for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count;++iTrafo) {
+ if(pcBoneTransforms->bone_index >= pcHeader->bones_num) {
+ DefaultLogger::get()->warn("Index overflow in frame area. "
+ "Unable to parse this bone transformation");
+ }
+ else {
+ AddAnimationBoneTrafoKey_3DGS_MDL7(frame.iIndex,
+ pcBoneTransforms,shared.apcOutBones);
+ }
+ pcBoneTransforms = (const MDL::BoneTransform_MDL7*)(
+ (const char*)pcBoneTransforms + pcHeader->bonetrans_stc_size);
+ }
+ }
+ else {
+ DefaultLogger::get()->warn("Ignoring animation keyframes in groups != 0");
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Attach bones to the output nodegraph
void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBones,
- aiNode* pcParent,uint16_t iParentIndex)
+ aiNode* pcParent,uint16_t iParentIndex)
{
- ai_assert(NULL != apcBones && NULL != pcParent);
+ ai_assert(NULL != apcBones && NULL != pcParent);
- // get a pointer to the header ...
- const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+ // get a pointer to the header ...
+ const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- const MDL::IntBone_MDL7** apcBones2 = apcBones;
- for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
+ const MDL::IntBone_MDL7** apcBones2 = apcBones;
+ for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
- const MDL::IntBone_MDL7* const pcBone = *apcBones2++;
- if (pcBone->iParent == iParentIndex) {
- ++pcParent->mNumChildren;
- }
- }
- pcParent->mChildren = new aiNode*[pcParent->mNumChildren];
- unsigned int qq = 0;
- for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
+ const MDL::IntBone_MDL7* const pcBone = *apcBones2++;
+ if (pcBone->iParent == iParentIndex) {
+ ++pcParent->mNumChildren;
+ }
+ }
+ pcParent->mChildren = new aiNode*[pcParent->mNumChildren];
+ unsigned int qq = 0;
+ for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
- const MDL::IntBone_MDL7* const pcBone = *apcBones++;
- if (pcBone->iParent != iParentIndex)continue;
+ const MDL::IntBone_MDL7* const pcBone = *apcBones++;
+ if (pcBone->iParent != iParentIndex)continue;
- aiNode* pcNode = pcParent->mChildren[qq++] = new aiNode();
- pcNode->mName = aiString( pcBone->mName );
+ aiNode* pcNode = pcParent->mChildren[qq++] = new aiNode();
+ pcNode->mName = aiString( pcBone->mName );
- AddBonesToNodeGraph_3DGS_MDL7(apcBones,pcNode,(uint16_t)i);
- }
+ AddBonesToNodeGraph_3DGS_MDL7(apcBones,pcNode,(uint16_t)i);
+ }
}
// ------------------------------------------------------------------------------------------------
// Build output animations
void MDLImporter::BuildOutputAnims_3DGS_MDL7(
- const MDL::IntBone_MDL7** apcBonesOut)
+ const MDL::IntBone_MDL7** apcBonesOut)
{
- ai_assert(NULL != apcBonesOut);
- const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)mBuffer;
-
- // one animation ...
- aiAnimation* pcAnim = new aiAnimation();
- for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
- if (!apcBonesOut[i]->pkeyPositions.empty()) {
-
- // get the last frame ... (needn't be equal to pcHeader->frames_num)
- for (size_t qq = 0; qq < apcBonesOut[i]->pkeyPositions.size();++qq) {
- pcAnim->mDuration = std::max(pcAnim->mDuration, (double)
- apcBonesOut[i]->pkeyPositions[qq].mTime);
- }
- ++pcAnim->mNumChannels;
- }
- }
- if (pcAnim->mDuration) {
- pcAnim->mChannels = new aiNodeAnim*[pcAnim->mNumChannels];
-
- unsigned int iCnt = 0;
- for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
- if (!apcBonesOut[i]->pkeyPositions.empty()) {
- const MDL::IntBone_MDL7* const intBone = apcBonesOut[i];
-
- aiNodeAnim* const pcNodeAnim = pcAnim->mChannels[iCnt++] = new aiNodeAnim();
- pcNodeAnim->mNodeName = aiString( intBone->mName );
-
- // allocate enough storage for all keys
- pcNodeAnim->mNumPositionKeys = (unsigned int)intBone->pkeyPositions.size();
- pcNodeAnim->mNumScalingKeys = (unsigned int)intBone->pkeyPositions.size();
- pcNodeAnim->mNumRotationKeys = (unsigned int)intBone->pkeyPositions.size();
-
- pcNodeAnim->mPositionKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
- pcNodeAnim->mScalingKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
- pcNodeAnim->mRotationKeys = new aiQuatKey[pcNodeAnim->mNumPositionKeys];
-
- // copy all keys
- for (unsigned int qq = 0; qq < pcNodeAnim->mNumPositionKeys;++qq) {
- pcNodeAnim->mPositionKeys[qq] = intBone->pkeyPositions[qq];
- pcNodeAnim->mScalingKeys[qq] = intBone->pkeyScalings[qq];
- pcNodeAnim->mRotationKeys[qq] = intBone->pkeyRotations[qq];
- }
- }
- }
-
- // store the output animation
- pScene->mNumAnimations = 1;
- pScene->mAnimations = new aiAnimation*[1];
- pScene->mAnimations[0] = pcAnim;
- }
- else delete pcAnim;
+ ai_assert(NULL != apcBonesOut);
+ const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)mBuffer;
+
+ // one animation ...
+ aiAnimation* pcAnim = new aiAnimation();
+ for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
+ if (!apcBonesOut[i]->pkeyPositions.empty()) {
+
+ // get the last frame ... (needn't be equal to pcHeader->frames_num)
+ for (size_t qq = 0; qq < apcBonesOut[i]->pkeyPositions.size();++qq) {
+ pcAnim->mDuration = std::max(pcAnim->mDuration, (double)
+ apcBonesOut[i]->pkeyPositions[qq].mTime);
+ }
+ ++pcAnim->mNumChannels;
+ }
+ }
+ if (pcAnim->mDuration) {
+ pcAnim->mChannels = new aiNodeAnim*[pcAnim->mNumChannels];
+
+ unsigned int iCnt = 0;
+ for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
+ if (!apcBonesOut[i]->pkeyPositions.empty()) {
+ const MDL::IntBone_MDL7* const intBone = apcBonesOut[i];
+
+ aiNodeAnim* const pcNodeAnim = pcAnim->mChannels[iCnt++] = new aiNodeAnim();
+ pcNodeAnim->mNodeName = aiString( intBone->mName );
+
+ // allocate enough storage for all keys
+ pcNodeAnim->mNumPositionKeys = (unsigned int)intBone->pkeyPositions.size();
+ pcNodeAnim->mNumScalingKeys = (unsigned int)intBone->pkeyPositions.size();
+ pcNodeAnim->mNumRotationKeys = (unsigned int)intBone->pkeyPositions.size();
+
+ pcNodeAnim->mPositionKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
+ pcNodeAnim->mScalingKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
+ pcNodeAnim->mRotationKeys = new aiQuatKey[pcNodeAnim->mNumPositionKeys];
+
+ // copy all keys
+ for (unsigned int qq = 0; qq < pcNodeAnim->mNumPositionKeys;++qq) {
+ pcNodeAnim->mPositionKeys[qq] = intBone->pkeyPositions[qq];
+ pcNodeAnim->mScalingKeys[qq] = intBone->pkeyScalings[qq];
+ pcNodeAnim->mRotationKeys[qq] = intBone->pkeyRotations[qq];
+ }
+ }
+ }
+
+ // store the output animation
+ pScene->mNumAnimations = 1;
+ pScene->mAnimations = new aiAnimation*[1];
+ pScene->mAnimations[0] = pcAnim;
+ }
+ else delete pcAnim;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
- const MDL::BoneTransform_MDL7* pcBoneTransforms,
- MDL::IntBone_MDL7** apcBonesOut)
+ const MDL::BoneTransform_MDL7* pcBoneTransforms,
+ MDL::IntBone_MDL7** apcBonesOut)
{
- ai_assert(NULL != pcBoneTransforms);
- ai_assert(NULL != apcBonesOut);
-
- // first .. get the transformation matrix
- aiMatrix4x4 mTransform;
- mTransform.a1 = pcBoneTransforms->m[0];
- mTransform.b1 = pcBoneTransforms->m[1];
- mTransform.c1 = pcBoneTransforms->m[2];
- mTransform.d1 = pcBoneTransforms->m[3];
-
- mTransform.a2 = pcBoneTransforms->m[4];
- mTransform.b2 = pcBoneTransforms->m[5];
- mTransform.c2 = pcBoneTransforms->m[6];
- mTransform.d2 = pcBoneTransforms->m[7];
-
- mTransform.a3 = pcBoneTransforms->m[8];
- mTransform.b3 = pcBoneTransforms->m[9];
- mTransform.c3 = pcBoneTransforms->m[10];
- mTransform.d3 = pcBoneTransforms->m[11];
-
- // now decompose the transformation matrix into separate
- // scaling, rotation and translation
- aiVectorKey vScaling,vPosition;
- aiQuatKey qRotation;
-
- // FIXME: Decompose will assert in debug builds if the matrix is invalid ...
- mTransform.Decompose(vScaling.mValue,qRotation.mValue,vPosition.mValue);
-
- // now generate keys
- vScaling.mTime = qRotation.mTime = vPosition.mTime = (double)iTrafo;
-
- // add the keys to the bone
- MDL::IntBone_MDL7* const pcBoneOut = apcBonesOut[pcBoneTransforms->bone_index];
- pcBoneOut->pkeyPositions.push_back ( vPosition );
- pcBoneOut->pkeyScalings.push_back ( vScaling );
- pcBoneOut->pkeyRotations.push_back ( qRotation );
+ ai_assert(NULL != pcBoneTransforms);
+ ai_assert(NULL != apcBonesOut);
+
+ // first .. get the transformation matrix
+ aiMatrix4x4 mTransform;
+ mTransform.a1 = pcBoneTransforms->m[0];
+ mTransform.b1 = pcBoneTransforms->m[1];
+ mTransform.c1 = pcBoneTransforms->m[2];
+ mTransform.d1 = pcBoneTransforms->m[3];
+
+ mTransform.a2 = pcBoneTransforms->m[4];
+ mTransform.b2 = pcBoneTransforms->m[5];
+ mTransform.c2 = pcBoneTransforms->m[6];
+ mTransform.d2 = pcBoneTransforms->m[7];
+
+ mTransform.a3 = pcBoneTransforms->m[8];
+ mTransform.b3 = pcBoneTransforms->m[9];
+ mTransform.c3 = pcBoneTransforms->m[10];
+ mTransform.d3 = pcBoneTransforms->m[11];
+
+ // now decompose the transformation matrix into separate
+ // scaling, rotation and translation
+ aiVectorKey vScaling,vPosition;
+ aiQuatKey qRotation;
+
+ // FIXME: Decompose will assert in debug builds if the matrix is invalid ...
+ mTransform.Decompose(vScaling.mValue,qRotation.mValue,vPosition.mValue);
+
+ // now generate keys
+ vScaling.mTime = qRotation.mTime = vPosition.mTime = (double)iTrafo;
+
+ // add the keys to the bone
+ MDL::IntBone_MDL7* const pcBoneOut = apcBonesOut[pcBoneTransforms->bone_index];
+ pcBoneOut->pkeyPositions.push_back ( vPosition );
+ pcBoneOut->pkeyScalings.push_back ( vScaling );
+ pcBoneOut->pkeyRotations.push_back ( qRotation );
}
// ------------------------------------------------------------------------------------------------
// Construct output meshes
void MDLImporter::GenerateOutputMeshes_3DGS_MDL7(
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSplitGroupData_MDL7& splitGroupData)
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSplitGroupData_MDL7& splitGroupData)
{
- const MDL::IntSharedData_MDL7& shared = splitGroupData.shared;
-
- // get a pointer to the header ...
- const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- const unsigned int iNumOutBones = pcHeader->bones_num;
-
- for (std::vector<aiMaterial*>::size_type i = 0; i < shared.pcMats.size();++i) {
- if (!splitGroupData.aiSplit[i]->empty()) {
-
- // allocate the output mesh
- aiMesh* pcMesh = new aiMesh();
-
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
- pcMesh->mMaterialIndex = (unsigned int)i;
-
- // allocate output storage
- pcMesh->mNumFaces = (unsigned int)splitGroupData.aiSplit[i]->size();
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
-
- pcMesh->mNumVertices = pcMesh->mNumFaces*3;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
-
- if (!groupData.vTextureCoords1.empty()) {
- pcMesh->mNumUVComponents[0] = 2;
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- if (!groupData.vTextureCoords2.empty()) {
- pcMesh->mNumUVComponents[1] = 2;
- pcMesh->mTextureCoords[1] = new aiVector3D[pcMesh->mNumVertices];
- }
- }
-
- // iterate through all faces and build an unique set of vertices
- unsigned int iCurrent = 0;
- for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) {
- pcMesh->mFaces[iFace].mNumIndices = 3;
- pcMesh->mFaces[iFace].mIndices = new unsigned int[3];
-
- unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace);
- const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace];
-
- // iterate through all face indices
- for (unsigned int c = 0; c < 3;++c) {
- const uint32_t iIndex = oldFace.mIndices[c];
- pcMesh->mVertices[iCurrent] = groupData.vPositions[iIndex];
- pcMesh->mNormals[iCurrent] = groupData.vNormals[iIndex];
-
- if (!groupData.vTextureCoords1.empty()) {
-
- pcMesh->mTextureCoords[0][iCurrent] = groupData.vTextureCoords1[iIndex];
- if (!groupData.vTextureCoords2.empty()) {
- pcMesh->mTextureCoords[1][iCurrent] = groupData.vTextureCoords2[iIndex];
- }
- }
- pcMesh->mFaces[iFace].mIndices[c] = iCurrent++;
- }
- }
-
- // if we have bones in the mesh we'll need to generate
- // proper vertex weights for them
- if (!groupData.aiBones.empty()) {
- std::vector<std::vector<unsigned int> > aaiVWeightList;
- aaiVWeightList.resize(iNumOutBones);
-
- int iCurrent = 0;
- for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) {
- unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace);
- const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace];
-
- // iterate through all face indices
- for (unsigned int c = 0; c < 3;++c) {
- unsigned int iBone = groupData.aiBones[ oldFace.mIndices[c] ];
- if (UINT_MAX != iBone) {
- if (iBone >= iNumOutBones) {
- DefaultLogger::get()->error("Bone index overflow. "
- "The bone index of a vertex exceeds the allowed range. ");
- iBone = iNumOutBones-1;
- }
- aaiVWeightList[ iBone ].push_back ( iCurrent );
- }
- ++iCurrent;
- }
- }
- // now check which bones are required ...
- for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k != aaiVWeightList.end();++k) {
- if (!(*k).empty()) {
- ++pcMesh->mNumBones;
- }
- }
- pcMesh->mBones = new aiBone*[pcMesh->mNumBones];
- iCurrent = 0;
- for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k!= aaiVWeightList.end();++k,++iCurrent)
- {
- if ((*k).empty())
- continue;
-
- // seems we'll need this node
- aiBone* pcBone = pcMesh->mBones[ iCurrent ] = new aiBone();
- pcBone->mName = aiString(shared.apcOutBones[ iCurrent ]->mName);
- pcBone->mOffsetMatrix = shared.apcOutBones[ iCurrent ]->mOffsetMatrix;
-
- // setup vertex weights
- pcBone->mNumWeights = (unsigned int)(*k).size();
- pcBone->mWeights = new aiVertexWeight[pcBone->mNumWeights];
-
- for (unsigned int weight = 0; weight < pcBone->mNumWeights;++weight) {
- pcBone->mWeights[weight].mVertexId = (*k)[weight];
- pcBone->mWeights[weight].mWeight = 1.0f;
- }
- }
- }
- // add the mesh to the list of output meshes
- splitGroupData.avOutList.push_back(pcMesh);
- }
- }
+ const MDL::IntSharedData_MDL7& shared = splitGroupData.shared;
+
+ // get a pointer to the header ...
+ const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+ const unsigned int iNumOutBones = pcHeader->bones_num;
+
+ for (std::vector<aiMaterial*>::size_type i = 0; i < shared.pcMats.size();++i) {
+ if (!splitGroupData.aiSplit[i]->empty()) {
+
+ // allocate the output mesh
+ aiMesh* pcMesh = new aiMesh();
+
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+ pcMesh->mMaterialIndex = (unsigned int)i;
+
+ // allocate output storage
+ pcMesh->mNumFaces = (unsigned int)splitGroupData.aiSplit[i]->size();
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+ pcMesh->mNumVertices = pcMesh->mNumFaces*3;
+ pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+
+ if (!groupData.vTextureCoords1.empty()) {
+ pcMesh->mNumUVComponents[0] = 2;
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ if (!groupData.vTextureCoords2.empty()) {
+ pcMesh->mNumUVComponents[1] = 2;
+ pcMesh->mTextureCoords[1] = new aiVector3D[pcMesh->mNumVertices];
+ }
+ }
+
+ // iterate through all faces and build an unique set of vertices
+ unsigned int iCurrent = 0;
+ for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) {
+ pcMesh->mFaces[iFace].mNumIndices = 3;
+ pcMesh->mFaces[iFace].mIndices = new unsigned int[3];
+
+ unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace);
+ const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace];
+
+ // iterate through all face indices
+ for (unsigned int c = 0; c < 3;++c) {
+ const uint32_t iIndex = oldFace.mIndices[c];
+ pcMesh->mVertices[iCurrent] = groupData.vPositions[iIndex];
+ pcMesh->mNormals[iCurrent] = groupData.vNormals[iIndex];
+
+ if (!groupData.vTextureCoords1.empty()) {
+
+ pcMesh->mTextureCoords[0][iCurrent] = groupData.vTextureCoords1[iIndex];
+ if (!groupData.vTextureCoords2.empty()) {
+ pcMesh->mTextureCoords[1][iCurrent] = groupData.vTextureCoords2[iIndex];
+ }
+ }
+ pcMesh->mFaces[iFace].mIndices[c] = iCurrent++;
+ }
+ }
+
+ // if we have bones in the mesh we'll need to generate
+ // proper vertex weights for them
+ if (!groupData.aiBones.empty()) {
+ std::vector<std::vector<unsigned int> > aaiVWeightList;
+ aaiVWeightList.resize(iNumOutBones);
+
+ int iCurrent = 0;
+ for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) {
+ unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace);
+ const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace];
+
+ // iterate through all face indices
+ for (unsigned int c = 0; c < 3;++c) {
+ unsigned int iBone = groupData.aiBones[ oldFace.mIndices[c] ];
+ if (UINT_MAX != iBone) {
+ if (iBone >= iNumOutBones) {
+ DefaultLogger::get()->error("Bone index overflow. "
+ "The bone index of a vertex exceeds the allowed range. ");
+ iBone = iNumOutBones-1;
+ }
+ aaiVWeightList[ iBone ].push_back ( iCurrent );
+ }
+ ++iCurrent;
+ }
+ }
+ // now check which bones are required ...
+ for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k != aaiVWeightList.end();++k) {
+ if (!(*k).empty()) {
+ ++pcMesh->mNumBones;
+ }
+ }
+ pcMesh->mBones = new aiBone*[pcMesh->mNumBones];
+ iCurrent = 0;
+ for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k!= aaiVWeightList.end();++k,++iCurrent)
+ {
+ if ((*k).empty())
+ continue;
+
+ // seems we'll need this node
+ aiBone* pcBone = pcMesh->mBones[ iCurrent ] = new aiBone();
+ pcBone->mName = aiString(shared.apcOutBones[ iCurrent ]->mName);
+ pcBone->mOffsetMatrix = shared.apcOutBones[ iCurrent ]->mOffsetMatrix;
+
+ // setup vertex weights
+ pcBone->mNumWeights = (unsigned int)(*k).size();
+ pcBone->mWeights = new aiVertexWeight[pcBone->mNumWeights];
+
+ for (unsigned int weight = 0; weight < pcBone->mNumWeights;++weight) {
+ pcBone->mWeights[weight].mVertexId = (*k)[weight];
+ pcBone->mWeights[weight].mWeight = 1.0f;
+ }
+ }
+ }
+ // add the mesh to the list of output meshes
+ splitGroupData.avOutList.push_back(pcMesh);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Join to materials
void MDLImporter::JoinSkins_3DGS_MDL7(
- aiMaterial* pcMat1,
- aiMaterial* pcMat2,
- aiMaterial* pcMatOut)
+ aiMaterial* pcMat1,
+ aiMaterial* pcMat2,
+ aiMaterial* pcMatOut)
{
- ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut);
-
- // first create a full copy of the first skin property set
- // and assign it to the output material
- aiMaterial::CopyPropertyList(pcMatOut,pcMat1);
-
- int iVal = 0;
- pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
-
- // then extract the diffuse texture from the second skin,
- // setup 1 as UV source and we have it
- aiString sString;
- if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString )) {
- iVal = 1;
- pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
- pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1));
- }
+ ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut);
+
+ // first create a full copy of the first skin property set
+ // and assign it to the output material
+ aiMaterial::CopyPropertyList(pcMatOut,pcMat1);
+
+ int iVal = 0;
+ pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
+
+ // then extract the diffuse texture from the second skin,
+ // setup 1 as UV source and we have it
+ aiString sString;
+ if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString )) {
+ iVal = 1;
+ pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
+ pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1));
+ }
}
// ------------------------------------------------------------------------------------------------
// Read a half-life 2 MDL
void MDLImporter::InternReadFile_HL2( )
{
- //const MDL::Header_HL2* pcHeader = (const MDL::Header_HL2*)this->mBuffer;
- throw DeadlyImportError("HL2 MDLs are not implemented");
+ //const MDL::Header_HL2* pcHeader = (const MDL::Header_HL2*)this->mBuffer;
+ throw DeadlyImportError("HL2 MDLs are not implemented");
}
#endif // !! ASSIMP_BUILD_NO_MDL_IMPORTER