vrshoot

diff libs/assimp/MD2Loader.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/assimp/MD2Loader.cpp	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,426 @@
     1.4 +/*
     1.5 +---------------------------------------------------------------------------
     1.6 +Open Asset Import Library (assimp)
     1.7 +---------------------------------------------------------------------------
     1.8 +
     1.9 +Copyright (c) 2006-2012, assimp team
    1.10 +
    1.11 +All rights reserved.
    1.12 +
    1.13 +Redistribution and use of this software in source and binary forms, 
    1.14 +with or without modification, are permitted provided that the following 
    1.15 +conditions are met:
    1.16 +
    1.17 +* Redistributions of source code must retain the above
    1.18 +  copyright notice, this list of conditions and the
    1.19 +  following disclaimer.
    1.20 +
    1.21 +* Redistributions in binary form must reproduce the above
    1.22 +  copyright notice, this list of conditions and the
    1.23 +  following disclaimer in the documentation and/or other
    1.24 +  materials provided with the distribution.
    1.25 +
    1.26 +* Neither the name of the assimp team, nor the names of its
    1.27 +  contributors may be used to endorse or promote products
    1.28 +  derived from this software without specific prior
    1.29 +  written permission of the assimp team.
    1.30 +
    1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
    1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.42 +---------------------------------------------------------------------------
    1.43 +*/
    1.44 +
    1.45 +#include "AssimpPCH.h"
    1.46 +#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
    1.47 +
    1.48 +/** @file Implementation of the MD2 importer class */
    1.49 +#include "MD2Loader.h"
    1.50 +#include "ByteSwap.h"
    1.51 +#include "MD2NormalTable.h" // shouldn't be included by other units
    1.52 +
    1.53 +using namespace Assimp;
    1.54 +using namespace Assimp::MD2;
    1.55 +
    1.56 +
    1.57 +// helper macro to determine the size of an array
    1.58 +#if (!defined ARRAYSIZE)
    1.59 +#	define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0])))
    1.60 +#endif 
    1.61 +
    1.62 +static const aiImporterDesc desc = {
    1.63 +	"Quake II Mesh Importer",
    1.64 +	"",
    1.65 +	"",
    1.66 +	"",
    1.67 +	aiImporterFlags_SupportBinaryFlavour,
    1.68 +	0,
    1.69 +	0,
    1.70 +	0,
    1.71 +	0,
    1.72 +	"md2" 
    1.73 +};
    1.74 +
    1.75 +// ------------------------------------------------------------------------------------------------
    1.76 +// Helper function to lookup a normal in Quake 2's precalculated table
    1.77 +void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut)
    1.78 +{
    1.79 +	// make sure the normal index has a valid value
    1.80 +	if (iNormalIndex >= ARRAYSIZE(g_avNormals))	{
    1.81 +		DefaultLogger::get()->warn("Index overflow in Quake II normal vector list");
    1.82 +		iNormalIndex = ARRAYSIZE(g_avNormals) - 1;
    1.83 +	}
    1.84 +	vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex]));
    1.85 +}
    1.86 +
    1.87 +
    1.88 +// ------------------------------------------------------------------------------------------------
    1.89 +// Constructor to be privately used by Importer
    1.90 +MD2Importer::MD2Importer()
    1.91 +{}
    1.92 +
    1.93 +// ------------------------------------------------------------------------------------------------
    1.94 +// Destructor, private as well 
    1.95 +MD2Importer::~MD2Importer()
    1.96 +{}
    1.97 +
    1.98 +// ------------------------------------------------------------------------------------------------
    1.99 +// Returns whether the class can handle the format of the given file. 
   1.100 +bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
   1.101 +{
   1.102 +	const std::string extension = GetExtension(pFile);
   1.103 +	if (extension == "md2")
   1.104 +		return true;
   1.105 +
   1.106 +	// if check for extension is not enough, check for the magic tokens 
   1.107 +	if (!extension.length() || checkSig) {
   1.108 +		uint32_t tokens[1]; 
   1.109 +		tokens[0] = AI_MD2_MAGIC_NUMBER_LE;
   1.110 +		return CheckMagicToken(pIOHandler,pFile,tokens,1);
   1.111 +	}
   1.112 +	return false;
   1.113 +}
   1.114 +
   1.115 +// ------------------------------------------------------------------------------------------------
   1.116 +// Get a list of all extensions supported by this loader
   1.117 +const aiImporterDesc* MD2Importer::GetInfo () const
   1.118 +{
   1.119 +	return &desc;
   1.120 +}
   1.121 +
   1.122 +// ------------------------------------------------------------------------------------------------
   1.123 +// Setup configuration properties
   1.124 +void MD2Importer::SetupProperties(const Importer* pImp)
   1.125 +{
   1.126 +	// The 
   1.127 +	// AI_CONFIG_IMPORT_MD2_KEYFRAME option overrides the
   1.128 +	// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
   1.129 +	configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD2_KEYFRAME,-1);
   1.130 +	if(static_cast<unsigned int>(-1) == configFrameID){
   1.131 +		configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
   1.132 +	}
   1.133 +}
   1.134 +// ------------------------------------------------------------------------------------------------
   1.135 +// Validate the file header
   1.136 +void MD2Importer::ValidateHeader( )
   1.137 +{
   1.138 +	// check magic number
   1.139 +	if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
   1.140 +		m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
   1.141 +	{
   1.142 +		char szBuffer[5];
   1.143 +		szBuffer[0] = ((char*)&m_pcHeader->magic)[0];
   1.144 +		szBuffer[1] = ((char*)&m_pcHeader->magic)[1];
   1.145 +		szBuffer[2] = ((char*)&m_pcHeader->magic)[2];
   1.146 +		szBuffer[3] = ((char*)&m_pcHeader->magic)[3];
   1.147 +		szBuffer[4] = '\0';
   1.148 +
   1.149 +		throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the "
   1.150 +			"magic word found is " + std::string(szBuffer));
   1.151 +	}
   1.152 +
   1.153 +	// check file format version
   1.154 +	if (m_pcHeader->version != 8)
   1.155 +		DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ...");
   1.156 +
   1.157 +	// check some values whether they are valid
   1.158 +	if (0 == m_pcHeader->numFrames)
   1.159 +		throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0");
   1.160 +
   1.161 +	if (m_pcHeader->offsetEnd > (uint32_t)fileSize)
   1.162 +		throw DeadlyImportError( "Invalid md2 file: File is too small");
   1.163 +
   1.164 +	if (m_pcHeader->offsetSkins		+ m_pcHeader->numSkins * sizeof (MD2::Skin)			>= fileSize ||
   1.165 +		m_pcHeader->offsetTexCoords	+ m_pcHeader->numTexCoords * sizeof (MD2::TexCoord)	>= fileSize ||
   1.166 +		m_pcHeader->offsetTriangles	+ m_pcHeader->numTriangles * sizeof (MD2::Triangle)	>= fileSize ||
   1.167 +		m_pcHeader->offsetFrames		+ m_pcHeader->numFrames * sizeof (MD2::Frame)			>= fileSize ||
   1.168 +		m_pcHeader->offsetEnd			> fileSize)
   1.169 +	{
   1.170 +		throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file");
   1.171 +	}
   1.172 +
   1.173 +	if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
   1.174 +		DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports");
   1.175 +	if ( m_pcHeader->numFrames > AI_MD2_MAX_FRAMES)
   1.176 +		DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports");
   1.177 +	if (m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
   1.178 +		DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports");
   1.179 +
   1.180 +	if (m_pcHeader->numFrames <= configFrameID )
   1.181 +		throw DeadlyImportError("The requested frame is not existing the file");
   1.182 +}
   1.183 +
   1.184 +// ------------------------------------------------------------------------------------------------
   1.185 +// Imports the given file into the given scene structure. 
   1.186 +void MD2Importer::InternReadFile( const std::string& pFile, 
   1.187 +	aiScene* pScene, IOSystem* pIOHandler)
   1.188 +{
   1.189 +	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
   1.190 +
   1.191 +	// Check whether we can read from the file
   1.192 +	if( file.get() == NULL)
   1.193 +		throw DeadlyImportError( "Failed to open MD2 file " + pFile + "");
   1.194 +
   1.195 +	// check whether the md3 file is large enough to contain
   1.196 +	// at least the file header
   1.197 +	fileSize = (unsigned int)file->FileSize();
   1.198 +	if( fileSize < sizeof(MD2::Header))
   1.199 +		throw DeadlyImportError( "MD2 File is too small");
   1.200 +
   1.201 +	std::vector<uint8_t> mBuffer2(fileSize);
   1.202 +	file->Read(&mBuffer2[0], 1, fileSize);
   1.203 +	mBuffer = &mBuffer2[0];
   1.204 +
   1.205 +
   1.206 +	m_pcHeader = (BE_NCONST MD2::Header*)mBuffer;
   1.207 +
   1.208 +#ifdef AI_BUILD_BIG_ENDIAN
   1.209 +
   1.210 +	ByteSwap::Swap4(&m_pcHeader->frameSize);
   1.211 +	ByteSwap::Swap4(&m_pcHeader->magic);
   1.212 +	ByteSwap::Swap4(&m_pcHeader->numFrames);
   1.213 +	ByteSwap::Swap4(&m_pcHeader->numGlCommands);
   1.214 +	ByteSwap::Swap4(&m_pcHeader->numSkins);
   1.215 +	ByteSwap::Swap4(&m_pcHeader->numTexCoords);
   1.216 +	ByteSwap::Swap4(&m_pcHeader->numTriangles);
   1.217 +	ByteSwap::Swap4(&m_pcHeader->numVertices);
   1.218 +	ByteSwap::Swap4(&m_pcHeader->offsetEnd);
   1.219 +	ByteSwap::Swap4(&m_pcHeader->offsetFrames);
   1.220 +	ByteSwap::Swap4(&m_pcHeader->offsetGlCommands);
   1.221 +	ByteSwap::Swap4(&m_pcHeader->offsetSkins);
   1.222 +	ByteSwap::Swap4(&m_pcHeader->offsetTexCoords);
   1.223 +	ByteSwap::Swap4(&m_pcHeader->offsetTriangles);
   1.224 +	ByteSwap::Swap4(&m_pcHeader->skinHeight);
   1.225 +	ByteSwap::Swap4(&m_pcHeader->skinWidth);
   1.226 +	ByteSwap::Swap4(&m_pcHeader->version);
   1.227 +
   1.228 +#endif
   1.229 +
   1.230 +	ValidateHeader();
   1.231 +
   1.232 +	// there won't be more than one mesh inside the file
   1.233 +	pScene->mNumMaterials = 1;
   1.234 +	pScene->mRootNode = new aiNode();
   1.235 +	pScene->mRootNode->mNumMeshes = 1;
   1.236 +	pScene->mRootNode->mMeshes = new unsigned int[1];
   1.237 +	pScene->mRootNode->mMeshes[0] = 0;
   1.238 +	pScene->mMaterials = new aiMaterial*[1];
   1.239 +	pScene->mMaterials[0] = new aiMaterial();
   1.240 +	pScene->mNumMeshes = 1;
   1.241 +	pScene->mMeshes = new aiMesh*[1];
   1.242 +
   1.243 +	aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
   1.244 +	pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
   1.245 +
   1.246 +	// navigate to the begin of the frame data
   1.247 +	BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*)
   1.248 +		m_pcHeader + m_pcHeader->offsetFrames);
   1.249 +
   1.250 +	pcFrame += configFrameID;
   1.251 +
   1.252 +	// navigate to the begin of the triangle data
   1.253 +	MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*)
   1.254 +		m_pcHeader + m_pcHeader->offsetTriangles);
   1.255 +
   1.256 +	// navigate to the begin of the tex coords data
   1.257 +	BE_NCONST MD2::TexCoord* pcTexCoords = (BE_NCONST MD2::TexCoord*) ((uint8_t*)
   1.258 +		m_pcHeader + m_pcHeader->offsetTexCoords);
   1.259 +
   1.260 +	// navigate to the begin of the vertex data
   1.261 +	BE_NCONST MD2::Vertex* pcVerts = (BE_NCONST MD2::Vertex*) (pcFrame->vertices);
   1.262 +
   1.263 +#ifdef AI_BUILD_BIG_ENDIAN
   1.264 +	for (uint32_t i = 0; i< m_pcHeader->numTriangles; ++i)
   1.265 +	{
   1.266 +		for (unsigned int p = 0; p < 3;++p)
   1.267 +		{
   1.268 +			ByteSwap::Swap2(& pcTriangles[i].textureIndices[p]);
   1.269 +			ByteSwap::Swap2(& pcTriangles[i].vertexIndices[p]);
   1.270 +		}
   1.271 +	}
   1.272 +	for (uint32_t i = 0; i < m_pcHeader->offsetTexCoords;++i)
   1.273 +	{
   1.274 +		ByteSwap::Swap2(& pcTexCoords[i].s);
   1.275 +		ByteSwap::Swap2(& pcTexCoords[i].t);
   1.276 +	}
   1.277 +	ByteSwap::Swap4( & pcFrame->scale[0] );
   1.278 +	ByteSwap::Swap4( & pcFrame->scale[1] );
   1.279 +	ByteSwap::Swap4( & pcFrame->scale[2] );
   1.280 +	ByteSwap::Swap4( & pcFrame->translate[0] );
   1.281 +	ByteSwap::Swap4( & pcFrame->translate[1] );
   1.282 +	ByteSwap::Swap4( & pcFrame->translate[2] );
   1.283 +#endif
   1.284 +
   1.285 +	pcMesh->mNumFaces = m_pcHeader->numTriangles;
   1.286 +	pcMesh->mFaces = new aiFace[m_pcHeader->numTriangles];
   1.287 +
   1.288 +	// allocate output storage
   1.289 +	pcMesh->mNumVertices = (unsigned int)pcMesh->mNumFaces*3;
   1.290 +	pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
   1.291 +	pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
   1.292 +
   1.293 +	// Not sure whether there are MD2 files without texture coordinates
   1.294 +	// NOTE: texture coordinates can be there without a texture,
   1.295 +	// but a texture can't be there without a valid UV channel
   1.296 +	aiMaterial* pcHelper = (aiMaterial*)pScene->mMaterials[0];
   1.297 +	const int iMode = (int)aiShadingMode_Gouraud;
   1.298 +	pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
   1.299 +
   1.300 +	if (m_pcHeader->numTexCoords && m_pcHeader->numSkins)
   1.301 +	{
   1.302 +		// navigate to the first texture associated with the mesh
   1.303 +		const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)m_pcHeader + 
   1.304 +			m_pcHeader->offsetSkins);
   1.305 +
   1.306 +		aiColor3D clr;
   1.307 +		clr.b = clr.g = clr.r = 1.0f;
   1.308 +		pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
   1.309 +		pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
   1.310 +
   1.311 +		clr.b = clr.g = clr.r = 0.05f;
   1.312 +		pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
   1.313 +
   1.314 +		if (pcSkins->name[0])
   1.315 +		{
   1.316 +			aiString szString;
   1.317 +			const size_t iLen = ::strlen(pcSkins->name);
   1.318 +			::memcpy(szString.data,pcSkins->name,iLen);
   1.319 +			szString.data[iLen] = '\0';
   1.320 +			szString.length = iLen;
   1.321 +
   1.322 +			pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
   1.323 +		}
   1.324 +		else{
   1.325 +			DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped.");
   1.326 +		}
   1.327 +	}
   1.328 +	else	{
   1.329 +		// apply a default material
   1.330 +		aiColor3D clr;
   1.331 +		clr.b = clr.g = clr.r = 0.6f;
   1.332 +		pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
   1.333 +		pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
   1.334 +
   1.335 +		clr.b = clr.g = clr.r = 0.05f;
   1.336 +		pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
   1.337 +
   1.338 +		aiString szName;
   1.339 +		szName.Set(AI_DEFAULT_MATERIAL_NAME);
   1.340 +		pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
   1.341 +
   1.342 +		aiString sz;
   1.343 +
   1.344 +		// TODO: Try to guess the name of the texture file from the model file name
   1.345 +
   1.346 +		sz.Set("$texture_dummy.bmp");
   1.347 +		pcHelper->AddProperty(&sz,AI_MATKEY_TEXTURE_DIFFUSE(0));
   1.348 +	}
   1.349 +
   1.350 +
   1.351 +	// now read all triangles of the first frame, apply scaling and translation
   1.352 +	unsigned int iCurrent = 0;
   1.353 +
   1.354 +	float fDivisorU = 1.0f,fDivisorV = 1.0f;
   1.355 +	if (m_pcHeader->numTexCoords)	{
   1.356 +		// allocate storage for texture coordinates, too
   1.357 +		pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
   1.358 +		pcMesh->mNumUVComponents[0] = 2;
   1.359 +
   1.360 +		// check whether the skin width or height are zero (this would
   1.361 +		// cause a division through zero)
   1.362 +		if (!m_pcHeader->skinWidth)	{
   1.363 +			DefaultLogger::get()->error("MD2: No valid skin width given");
   1.364 +		}
   1.365 +		else fDivisorU = (float)m_pcHeader->skinWidth;
   1.366 +		if (!m_pcHeader->skinHeight){
   1.367 +			DefaultLogger::get()->error("MD2: No valid skin height given");
   1.368 +		}
   1.369 +		else fDivisorV = (float)m_pcHeader->skinHeight;
   1.370 +	}
   1.371 +
   1.372 +	for (unsigned int i = 0; i < (unsigned int)m_pcHeader->numTriangles;++i)	{
   1.373 +		// Allocate the face
   1.374 +		pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3];
   1.375 +		pScene->mMeshes[0]->mFaces[i].mNumIndices = 3;
   1.376 +
   1.377 +		// copy texture coordinates
   1.378 +		// check whether they are different from the previous value at this index.
   1.379 +		// In this case, create a full separate set of vertices/normals/texcoords
   1.380 +		for (unsigned int c = 0; c < 3;++c,++iCurrent)	{
   1.381 +
   1.382 +			// validate vertex indices
   1.383 +			register unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
   1.384 +			if (iIndex >= m_pcHeader->numVertices)	{
   1.385 +				DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range");
   1.386 +				iIndex = m_pcHeader->numVertices-1;
   1.387 +			}
   1.388 +
   1.389 +			// read x,y, and z component of the vertex
   1.390 +			aiVector3D& vec = pcMesh->mVertices[iCurrent];
   1.391 +
   1.392 +			vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
   1.393 +			vec.x += pcFrame->translate[0];
   1.394 +
   1.395 +			vec.y = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1];
   1.396 +			vec.y += pcFrame->translate[1];
   1.397 +
   1.398 +			vec.z = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2];
   1.399 +			vec.z += pcFrame->translate[2];
   1.400 +
   1.401 +			// read the normal vector from the precalculated normal table
   1.402 +			aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
   1.403 +			LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
   1.404 +
   1.405 +			// flip z and y to become right-handed
   1.406 +			std::swap((float&)vNormal.z,(float&)vNormal.y);
   1.407 +			std::swap((float&)vec.z,(float&)vec.y);
   1.408 +
   1.409 +			if (m_pcHeader->numTexCoords)	{
   1.410 +				// validate texture coordinates
   1.411 +				iIndex = pcTriangles[i].textureIndices[c];
   1.412 +				if (iIndex >= m_pcHeader->numTexCoords)	{
   1.413 +					DefaultLogger::get()->error("MD2: UV index is outside the allowed range");
   1.414 +					iIndex = m_pcHeader->numTexCoords-1;
   1.415 +				}
   1.416 +
   1.417 +				aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent];
   1.418 +
   1.419 +				// the texture coordinates are absolute values but we
   1.420 +				// need relative values between 0 and 1
   1.421 +				pcOut.x = pcTexCoords[iIndex].s / fDivisorU;
   1.422 +				pcOut.y = 1.f-pcTexCoords[iIndex].t / fDivisorV;
   1.423 +			}
   1.424 +			pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
   1.425 +		}
   1.426 +	}
   1.427 +}
   1.428 +
   1.429 +#endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER