From 3cd55c54dbf66a320438d743fbd223952043cd39 Mon Sep 17 00:00:00 2001 From: Andy Maloney Date: Wed, 7 Dec 2016 19:33:08 -0500 Subject: Update assimp lib to 3.3.1 The currently included assimp lib is v3.0 from 2012. This updates assimp lib to the latest released version (3.3.1). Change-Id: I15a60e3150c0b268422f23137107b34e4c5c4342 Reviewed-by: Sean Harmer --- src/3rdparty/assimp/code/MD2Loader.cpp | 661 +++++++++++++++++---------------- 1 file changed, 346 insertions(+), 315 deletions(-) (limited to 'src/3rdparty/assimp/code/MD2Loader.cpp') diff --git a/src/3rdparty/assimp/code/MD2Loader.cpp b/src/3rdparty/assimp/code/MD2Loader.cpp index 050555bad..b4c124774 100644 --- a/src/3rdparty/assimp/code/MD2Loader.cpp +++ b/src/3rdparty/assimp/code/MD2Loader.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,402 +25,433 @@ 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. --------------------------------------------------------------------------- */ -#include "AssimpPCH.h" + #ifndef ASSIMP_BUILD_NO_MD2_IMPORTER /** @file Implementation of the MD2 importer class */ #include "MD2Loader.h" -#include "ByteSwap.h" +#include "ByteSwapper.h" #include "MD2NormalTable.h" // shouldn't be included by other units +#include +#include +#include +#include +#include using namespace Assimp; using namespace Assimp::MD2; - // helper macro to determine the size of an array #if (!defined ARRAYSIZE) -# define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0]))) -#endif +# define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0]))) +#endif static const aiImporterDesc desc = { - "Quake II Mesh Importer", - "", - "", - "", - aiImporterFlags_SupportBinaryFlavour, - 0, - 0, - 0, - 0, - "md2" + "Quake II Mesh Importer", + "", + "", + "", + aiImporterFlags_SupportBinaryFlavour, + 0, + 0, + 0, + 0, + "md2" }; // ------------------------------------------------------------------------------------------------ // Helper function to lookup a normal in Quake 2's precalculated table void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut) { - // make sure the normal index has a valid value - if (iNormalIndex >= ARRAYSIZE(g_avNormals)) { - DefaultLogger::get()->warn("Index overflow in Quake II normal vector list"); - iNormalIndex = ARRAYSIZE(g_avNormals) - 1; - } - vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex])); + // make sure the normal index has a valid value + if (iNormalIndex >= ARRAYSIZE(g_avNormals)) { + DefaultLogger::get()->warn("Index overflow in Quake II normal vector list"); + iNormalIndex = ARRAYSIZE(g_avNormals) - 1; + } + vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex])); } // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer MD2Importer::MD2Importer() + : configFrameID(), + m_pcHeader(), + mBuffer(), + fileSize() {} // ------------------------------------------------------------------------------------------------ -// Destructor, private as well +// Destructor, private as well MD2Importer::~MD2Importer() {} // ------------------------------------------------------------------------------------------------ -// 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 MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - if (extension == "md2") - return true; - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || checkSig) { - uint32_t tokens[1]; - tokens[0] = AI_MD2_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler,pFile,tokens,1); - } - return false; + const std::string extension = GetExtension(pFile); + if (extension == "md2") + return true; + + // if check for extension is not enough, check for the magic tokens + if (!extension.length() || checkSig) { + uint32_t tokens[1]; + tokens[0] = AI_MD2_MAGIC_NUMBER_LE; + return CheckMagicToken(pIOHandler,pFile,tokens,1); + } + return false; } // ------------------------------------------------------------------------------------------------ // Get a list of all extensions supported by this loader const aiImporterDesc* MD2Importer::GetInfo () const { - return &desc; + return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties void MD2Importer::SetupProperties(const Importer* pImp) { - // The - // AI_CONFIG_IMPORT_MD2_KEYFRAME option overrides the - // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD2_KEYFRAME,-1); - if(static_cast(-1) == configFrameID){ - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); - } + // The + // AI_CONFIG_IMPORT_MD2_KEYFRAME option overrides the + // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. + configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD2_KEYFRAME,-1); + if(static_cast(-1) == configFrameID){ + configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); + } } // ------------------------------------------------------------------------------------------------ // Validate the file header void MD2Importer::ValidateHeader( ) { - // check magic number - if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE && - m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE) - { - char szBuffer[5]; - szBuffer[0] = ((char*)&m_pcHeader->magic)[0]; - szBuffer[1] = ((char*)&m_pcHeader->magic)[1]; - szBuffer[2] = ((char*)&m_pcHeader->magic)[2]; - szBuffer[3] = ((char*)&m_pcHeader->magic)[3]; - szBuffer[4] = '\0'; - - throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the " - "magic word found is " + std::string(szBuffer)); - } - - // check file format version - if (m_pcHeader->version != 8) - DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ..."); - - // check some values whether they are valid - if (0 == m_pcHeader->numFrames) - throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0"); - - if (m_pcHeader->offsetEnd > (uint32_t)fileSize) - throw DeadlyImportError( "Invalid md2 file: File is too small"); - - if (m_pcHeader->offsetSkins + m_pcHeader->numSkins * sizeof (MD2::Skin) >= fileSize || - m_pcHeader->offsetTexCoords + m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= fileSize || - m_pcHeader->offsetTriangles + m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= fileSize || - m_pcHeader->offsetFrames + m_pcHeader->numFrames * sizeof (MD2::Frame) >= fileSize || - m_pcHeader->offsetEnd > fileSize) - { - throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file"); - } - - if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS) - DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports"); - if ( m_pcHeader->numFrames > AI_MD2_MAX_FRAMES) - DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports"); - if (m_pcHeader->numVertices > AI_MD2_MAX_VERTS) - DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports"); - - if (m_pcHeader->numFrames <= configFrameID ) - throw DeadlyImportError("The requested frame is not existing the file"); + // check magic number + if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE && + m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE) + { + char szBuffer[5]; + szBuffer[0] = ((char*)&m_pcHeader->magic)[0]; + szBuffer[1] = ((char*)&m_pcHeader->magic)[1]; + szBuffer[2] = ((char*)&m_pcHeader->magic)[2]; + szBuffer[3] = ((char*)&m_pcHeader->magic)[3]; + szBuffer[4] = '\0'; + + throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the " + "magic word found is " + std::string(szBuffer)); + } + + // check file format version + if (m_pcHeader->version != 8) + DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ..."); + + // check some values whether they are valid + if (0 == m_pcHeader->numFrames) + throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0"); + + if (m_pcHeader->offsetEnd > (uint32_t)fileSize) + throw DeadlyImportError( "Invalid md2 file: File is too small"); + + if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) { + throw DeadlyImportError("Invalid MD2 header: too many skins, would overflow"); + } + + if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) { + throw DeadlyImportError("Invalid MD2 header: too many vertices, would overflow"); + } + + if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) { + throw DeadlyImportError("Invalid MD2 header: too many texcoords, would overflow"); + } + + if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) { + throw DeadlyImportError("Invalid MD2 header: too many triangles, would overflow"); + } + + if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) { + throw DeadlyImportError("Invalid MD2 header: too many frames, would overflow"); + } + + // -1 because Frame already contains one + unsigned int frameSize = sizeof (MD2::Frame) + (m_pcHeader->numVertices - 1) * sizeof(MD2::Vertex); + + if (m_pcHeader->offsetSkins + m_pcHeader->numSkins * sizeof (MD2::Skin) >= fileSize || + m_pcHeader->offsetTexCoords + m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= fileSize || + m_pcHeader->offsetTriangles + m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= fileSize || + m_pcHeader->offsetFrames + m_pcHeader->numFrames * frameSize >= fileSize || + m_pcHeader->offsetEnd > fileSize) + { + throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file"); + } + + if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS) + DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports"); + if ( m_pcHeader->numFrames > AI_MD2_MAX_FRAMES) + DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports"); + if (m_pcHeader->numVertices > AI_MD2_MAX_VERTS) + DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports"); + + if (m_pcHeader->numFrames <= configFrameID ) + throw DeadlyImportError("The requested frame is not existing the file"); } // ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void MD2Importer::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) +// Imports the given file into the given scene structure. +void MD2Importer::InternReadFile( const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) { - boost::scoped_ptr file( pIOHandler->Open( pFile)); + std::unique_ptr file( pIOHandler->Open( pFile)); - // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open MD2 file " + pFile + ""); + // Check whether we can read from the file + if( file.get() == NULL) + throw DeadlyImportError( "Failed to open MD2 file " + pFile + ""); - // check whether the md3 file is large enough to contain - // at least the file header - fileSize = (unsigned int)file->FileSize(); - if( fileSize < sizeof(MD2::Header)) - throw DeadlyImportError( "MD2 File is too small"); + // check whether the md3 file is large enough to contain + // at least the file header + fileSize = (unsigned int)file->FileSize(); + if( fileSize < sizeof(MD2::Header)) + throw DeadlyImportError( "MD2 File is too small"); - std::vector mBuffer2(fileSize); - file->Read(&mBuffer2[0], 1, fileSize); - mBuffer = &mBuffer2[0]; + std::vector mBuffer2(fileSize); + file->Read(&mBuffer2[0], 1, fileSize); + mBuffer = &mBuffer2[0]; - m_pcHeader = (BE_NCONST MD2::Header*)mBuffer; + m_pcHeader = (BE_NCONST MD2::Header*)mBuffer; #ifdef AI_BUILD_BIG_ENDIAN - ByteSwap::Swap4(&m_pcHeader->frameSize); - ByteSwap::Swap4(&m_pcHeader->magic); - ByteSwap::Swap4(&m_pcHeader->numFrames); - ByteSwap::Swap4(&m_pcHeader->numGlCommands); - ByteSwap::Swap4(&m_pcHeader->numSkins); - ByteSwap::Swap4(&m_pcHeader->numTexCoords); - ByteSwap::Swap4(&m_pcHeader->numTriangles); - ByteSwap::Swap4(&m_pcHeader->numVertices); - ByteSwap::Swap4(&m_pcHeader->offsetEnd); - ByteSwap::Swap4(&m_pcHeader->offsetFrames); - ByteSwap::Swap4(&m_pcHeader->offsetGlCommands); - ByteSwap::Swap4(&m_pcHeader->offsetSkins); - ByteSwap::Swap4(&m_pcHeader->offsetTexCoords); - ByteSwap::Swap4(&m_pcHeader->offsetTriangles); - ByteSwap::Swap4(&m_pcHeader->skinHeight); - ByteSwap::Swap4(&m_pcHeader->skinWidth); - ByteSwap::Swap4(&m_pcHeader->version); + ByteSwap::Swap4(&m_pcHeader->frameSize); + ByteSwap::Swap4(&m_pcHeader->magic); + ByteSwap::Swap4(&m_pcHeader->numFrames); + ByteSwap::Swap4(&m_pcHeader->numGlCommands); + ByteSwap::Swap4(&m_pcHeader->numSkins); + ByteSwap::Swap4(&m_pcHeader->numTexCoords); + ByteSwap::Swap4(&m_pcHeader->numTriangles); + ByteSwap::Swap4(&m_pcHeader->numVertices); + ByteSwap::Swap4(&m_pcHeader->offsetEnd); + ByteSwap::Swap4(&m_pcHeader->offsetFrames); + ByteSwap::Swap4(&m_pcHeader->offsetGlCommands); + ByteSwap::Swap4(&m_pcHeader->offsetSkins); + ByteSwap::Swap4(&m_pcHeader->offsetTexCoords); + ByteSwap::Swap4(&m_pcHeader->offsetTriangles); + ByteSwap::Swap4(&m_pcHeader->skinHeight); + ByteSwap::Swap4(&m_pcHeader->skinWidth); + ByteSwap::Swap4(&m_pcHeader->version); #endif - ValidateHeader(); + ValidateHeader(); - // there won't be more than one mesh inside the file - pScene->mNumMaterials = 1; - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = new aiMaterial(); - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; + // there won't be more than one mesh inside the file + pScene->mNumMaterials = 1; + pScene->mRootNode = new aiNode(); + pScene->mRootNode->mNumMeshes = 1; + pScene->mRootNode->mMeshes = new unsigned int[1]; + pScene->mRootNode->mMeshes[0] = 0; + pScene->mMaterials = new aiMaterial*[1]; + pScene->mMaterials[0] = new aiMaterial(); + pScene->mNumMeshes = 1; + pScene->mMeshes = new aiMesh*[1]; - aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); - pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); + pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - // navigate to the begin of the frame data - BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*) - m_pcHeader + m_pcHeader->offsetFrames); + // navigate to the begin of the frame data + BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*) + m_pcHeader + m_pcHeader->offsetFrames); - pcFrame += configFrameID; + pcFrame += configFrameID; - // navigate to the begin of the triangle data - MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*) - m_pcHeader + m_pcHeader->offsetTriangles); + // navigate to the begin of the triangle data + MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*) + m_pcHeader + m_pcHeader->offsetTriangles); - // navigate to the begin of the tex coords data - BE_NCONST MD2::TexCoord* pcTexCoords = (BE_NCONST MD2::TexCoord*) ((uint8_t*) - m_pcHeader + m_pcHeader->offsetTexCoords); + // navigate to the begin of the tex coords data + BE_NCONST MD2::TexCoord* pcTexCoords = (BE_NCONST MD2::TexCoord*) ((uint8_t*) + m_pcHeader + m_pcHeader->offsetTexCoords); - // navigate to the begin of the vertex data - BE_NCONST MD2::Vertex* pcVerts = (BE_NCONST MD2::Vertex*) (pcFrame->vertices); + // navigate to the begin of the vertex data + BE_NCONST MD2::Vertex* pcVerts = (BE_NCONST MD2::Vertex*) (pcFrame->vertices); #ifdef AI_BUILD_BIG_ENDIAN - for (uint32_t i = 0; i< m_pcHeader->numTriangles; ++i) - { - for (unsigned int p = 0; p < 3;++p) - { - ByteSwap::Swap2(& pcTriangles[i].textureIndices[p]); - ByteSwap::Swap2(& pcTriangles[i].vertexIndices[p]); - } - } - for (uint32_t i = 0; i < m_pcHeader->offsetTexCoords;++i) - { - ByteSwap::Swap2(& pcTexCoords[i].s); - ByteSwap::Swap2(& pcTexCoords[i].t); - } - ByteSwap::Swap4( & pcFrame->scale[0] ); - ByteSwap::Swap4( & pcFrame->scale[1] ); - ByteSwap::Swap4( & pcFrame->scale[2] ); - ByteSwap::Swap4( & pcFrame->translate[0] ); - ByteSwap::Swap4( & pcFrame->translate[1] ); - ByteSwap::Swap4( & pcFrame->translate[2] ); + for (uint32_t i = 0; i< m_pcHeader->numTriangles; ++i) + { + for (unsigned int p = 0; p < 3;++p) + { + ByteSwap::Swap2(& pcTriangles[i].textureIndices[p]); + ByteSwap::Swap2(& pcTriangles[i].vertexIndices[p]); + } + } + for (uint32_t i = 0; i < m_pcHeader->offsetTexCoords;++i) + { + ByteSwap::Swap2(& pcTexCoords[i].s); + ByteSwap::Swap2(& pcTexCoords[i].t); + } + ByteSwap::Swap4( & pcFrame->scale[0] ); + ByteSwap::Swap4( & pcFrame->scale[1] ); + ByteSwap::Swap4( & pcFrame->scale[2] ); + ByteSwap::Swap4( & pcFrame->translate[0] ); + ByteSwap::Swap4( & pcFrame->translate[1] ); + ByteSwap::Swap4( & pcFrame->translate[2] ); #endif - pcMesh->mNumFaces = m_pcHeader->numTriangles; - pcMesh->mFaces = new aiFace[m_pcHeader->numTriangles]; - - // allocate output storage - pcMesh->mNumVertices = (unsigned int)pcMesh->mNumFaces*3; - pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - - // Not sure whether there are MD2 files without texture coordinates - // NOTE: texture coordinates can be there without a texture, - // but a texture can't be there without a valid UV channel - aiMaterial* pcHelper = (aiMaterial*)pScene->mMaterials[0]; - const int iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - if (m_pcHeader->numTexCoords && m_pcHeader->numSkins) - { - // navigate to the first texture associated with the mesh - const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)m_pcHeader + - m_pcHeader->offsetSkins); - - aiColor3D clr; - clr.b = clr.g = clr.r = 1.0f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - if (pcSkins->name[0]) - { - aiString szString; - const size_t iLen = ::strlen(pcSkins->name); - ::memcpy(szString.data,pcSkins->name,iLen); - szString.data[iLen] = '\0'; - szString.length = iLen; - - pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - else{ - DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped."); - } - } - else { - // apply a default material - aiColor3D clr; - clr.b = clr.g = clr.r = 0.6f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - aiString szName; - szName.Set(AI_DEFAULT_MATERIAL_NAME); - pcHelper->AddProperty(&szName,AI_MATKEY_NAME); - - aiString sz; - - // TODO: Try to guess the name of the texture file from the model file name - - sz.Set("$texture_dummy.bmp"); - pcHelper->AddProperty(&sz,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - - - // now read all triangles of the first frame, apply scaling and translation - unsigned int iCurrent = 0; - - float fDivisorU = 1.0f,fDivisorV = 1.0f; - if (m_pcHeader->numTexCoords) { - // allocate storage for texture coordinates, too - pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNumUVComponents[0] = 2; - - // check whether the skin width or height are zero (this would - // cause a division through zero) - if (!m_pcHeader->skinWidth) { - DefaultLogger::get()->error("MD2: No valid skin width given"); - } - else fDivisorU = (float)m_pcHeader->skinWidth; - if (!m_pcHeader->skinHeight){ - DefaultLogger::get()->error("MD2: No valid skin height given"); - } - else fDivisorV = (float)m_pcHeader->skinHeight; - } - - for (unsigned int i = 0; i < (unsigned int)m_pcHeader->numTriangles;++i) { - // Allocate the face - pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3]; - pScene->mMeshes[0]->mFaces[i].mNumIndices = 3; - - // copy texture coordinates - // check whether they are different from the previous value at this index. - // In this case, create a full separate set of vertices/normals/texcoords - for (unsigned int c = 0; c < 3;++c,++iCurrent) { - - // validate vertex indices - unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; - if (iIndex >= m_pcHeader->numVertices) { - DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range"); - iIndex = m_pcHeader->numVertices-1; - } - - // read x,y, and z component of the vertex - aiVector3D& vec = pcMesh->mVertices[iCurrent]; - - vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0]; - vec.x += pcFrame->translate[0]; - - vec.y = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1]; - vec.y += pcFrame->translate[1]; - - vec.z = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2]; - vec.z += pcFrame->translate[2]; - - // read the normal vector from the precalculated normal table - aiVector3D& vNormal = pcMesh->mNormals[iCurrent]; - LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal); - - // flip z and y to become right-handed - std::swap((float&)vNormal.z,(float&)vNormal.y); - std::swap((float&)vec.z,(float&)vec.y); - - if (m_pcHeader->numTexCoords) { - // validate texture coordinates - iIndex = pcTriangles[i].textureIndices[c]; - if (iIndex >= m_pcHeader->numTexCoords) { - DefaultLogger::get()->error("MD2: UV index is outside the allowed range"); - iIndex = m_pcHeader->numTexCoords-1; - } - - aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent]; - - // the texture coordinates are absolute values but we - // need relative values between 0 and 1 - pcOut.x = pcTexCoords[iIndex].s / fDivisorU; - pcOut.y = 1.f-pcTexCoords[iIndex].t / fDivisorV; - } - pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; - } - } + pcMesh->mNumFaces = m_pcHeader->numTriangles; + pcMesh->mFaces = new aiFace[m_pcHeader->numTriangles]; + + // allocate output storage + pcMesh->mNumVertices = (unsigned int)pcMesh->mNumFaces*3; + pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; + + // Not sure whether there are MD2 files without texture coordinates + // NOTE: texture coordinates can be there without a texture, + // but a texture can't be there without a valid UV channel + aiMaterial* pcHelper = (aiMaterial*)pScene->mMaterials[0]; + const int iMode = (int)aiShadingMode_Gouraud; + pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); + + if (m_pcHeader->numTexCoords && m_pcHeader->numSkins) + { + // navigate to the first texture associated with the mesh + const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)m_pcHeader + + m_pcHeader->offsetSkins); + + aiColor3D clr; + clr.b = clr.g = clr.r = 1.0f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + + clr.b = clr.g = clr.r = 0.05f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + + if (pcSkins->name[0]) + { + aiString szString; + const size_t iLen = ::strlen(pcSkins->name); + ::memcpy(szString.data,pcSkins->name,iLen); + szString.data[iLen] = '\0'; + szString.length = iLen; + + pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + else{ + DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped."); + } + } + else { + // apply a default material + aiColor3D clr; + clr.b = clr.g = clr.r = 0.6f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + + clr.b = clr.g = clr.r = 0.05f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + + aiString szName; + szName.Set(AI_DEFAULT_MATERIAL_NAME); + pcHelper->AddProperty(&szName,AI_MATKEY_NAME); + + aiString sz; + + // TODO: Try to guess the name of the texture file from the model file name + + sz.Set("$texture_dummy.bmp"); + pcHelper->AddProperty(&sz,AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + + + // now read all triangles of the first frame, apply scaling and translation + unsigned int iCurrent = 0; + + float fDivisorU = 1.0f,fDivisorV = 1.0f; + if (m_pcHeader->numTexCoords) { + // allocate storage for texture coordinates, too + pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mNumUVComponents[0] = 2; + + // check whether the skin width or height are zero (this would + // cause a division through zero) + if (!m_pcHeader->skinWidth) { + DefaultLogger::get()->error("MD2: No valid skin width given"); + } + else fDivisorU = (float)m_pcHeader->skinWidth; + if (!m_pcHeader->skinHeight){ + DefaultLogger::get()->error("MD2: No valid skin height given"); + } + else fDivisorV = (float)m_pcHeader->skinHeight; + } + + for (unsigned int i = 0; i < (unsigned int)m_pcHeader->numTriangles;++i) { + // Allocate the face + pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3]; + pScene->mMeshes[0]->mFaces[i].mNumIndices = 3; + + // copy texture coordinates + // check whether they are different from the previous value at this index. + // In this case, create a full separate set of vertices/normals/texcoords + for (unsigned int c = 0; c < 3;++c,++iCurrent) { + + // validate vertex indices + unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; + if (iIndex >= m_pcHeader->numVertices) { + DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range"); + iIndex = m_pcHeader->numVertices-1; + } + + // read x,y, and z component of the vertex + aiVector3D& vec = pcMesh->mVertices[iCurrent]; + + vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0]; + vec.x += pcFrame->translate[0]; + + vec.y = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1]; + vec.y += pcFrame->translate[1]; + + vec.z = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2]; + vec.z += pcFrame->translate[2]; + + // read the normal vector from the precalculated normal table + aiVector3D& vNormal = pcMesh->mNormals[iCurrent]; + LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal); + + // flip z and y to become right-handed + std::swap((float&)vNormal.z,(float&)vNormal.y); + std::swap((float&)vec.z,(float&)vec.y); + + if (m_pcHeader->numTexCoords) { + // validate texture coordinates + iIndex = pcTriangles[i].textureIndices[c]; + if (iIndex >= m_pcHeader->numTexCoords) { + DefaultLogger::get()->error("MD2: UV index is outside the allowed range"); + iIndex = m_pcHeader->numTexCoords-1; + } + + aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent]; + + // the texture coordinates are absolute values but we + // need relative values between 0 and 1 + pcOut.x = pcTexCoords[iIndex].s / fDivisorU; + pcOut.y = 1.f-pcTexCoords[iIndex].t / fDivisorV; + } + pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; + } + } } #endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER -- cgit v1.2.3