From 906c45eeeb9fe8b30a7eb2fa1218ebb3a514ac0a Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Tue, 13 Apr 2010 17:34:55 +0000 Subject: [PATCH] Fix: qnan detection code. Appearently I fooled myself when I wrote this. Fix: MDLLoader does not reset texture array properly when textures are substituted by plain colors. This caused crashes in ~aiScene or heap corruption. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@677 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/MDLLoader.cpp | 2 + code/MDLMaterialLoader.cpp | 12 +++-- code/qnan.h | 90 ++++++++++++++++++++++++++++---------- 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index 42a08a039..b9d7bb8e9 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -510,6 +510,8 @@ void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1( ) if (is_not_qnan(clr.r)) { delete pScene->mTextures[0]; delete[] pScene->mTextures; + + pScene->mTextures = NULL; pScene->mNumTextures = 0; } else { diff --git a/code/MDLMaterialLoader.cpp b/code/MDLMaterialLoader.cpp index 45416ca99..1a0ce542c 100644 --- a/code/MDLMaterialLoader.cpp +++ b/code/MDLMaterialLoader.cpp @@ -101,7 +101,8 @@ aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture) { if (*pcTexel != *(pcTexel-1)) { - pcTexel = NULL;break; + pcTexel = NULL; + break; } ++pcTexel; } @@ -458,7 +459,10 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData, delete[] pc; } } - else delete pcNew; + else { + pcNew->pcData = NULL; + delete pcNew; + } return; } @@ -638,7 +642,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( // opacity like this .... ARRRGGHH! clrTemp.r = pcMatIn->Ambient.a; AI_SWAP4(clrTemp.r); - if (is_not_qnan(clrTexture.r))clrTemp.r *= clrTexture.a; + if (is_not_qnan(clrTexture.r)) { + clrTemp.r *= clrTexture.a; + } pcMatOut->AddProperty(&clrTemp.r,1,AI_MATKEY_OPACITY); // read phong power diff --git a/code/qnan.h b/code/qnan.h index fdebab6a9..44f4eb353 100644 --- a/code/qnan.h +++ b/code/qnan.h @@ -1,20 +1,60 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2010, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ /** @file qnan.h * @brief Some utilities for our dealings with qnans. * - * @note Some loaders use qnans heavily to mark invalid values (and they're - * even returned by Gen(Smooth)Normals if normals are undefined for a - * primitive). Their whole usage is wrapped here, so you can easily - * fix issues with platforms with a different qnan implementation. + * @note Some loaders use qnans to mark invalid values tempoarily, also + * Assimp explicitly enforces undefined normals to be set to qnan. + * qnan utilities are available in standard libraries (C99 for example) + * but last time I checked compiler coverage was so bad that I decided + * to reinvent the wheel. */ -#if (!defined AI_QNAN_H_INCLUDED) +#ifndef AI_QNAN_H_INCLUDED #define AI_QNAN_H_INCLUDED // --------------------------------------------------------------------------- -/** @brief Data structure for the bit pattern of a 32 Bit - * IEEE 754 floating-point number. - */ +/** Data structure to represent the bit pattern of a 32 Bit + * IEEE 754 floating-point number. */ union _IEEESingle { float Float; @@ -27,37 +67,41 @@ union _IEEESingle } ; // --------------------------------------------------------------------------- -/** @brief check whether a float is qNaN. - * @param in Input value - */ -AI_FORCE_INLINE bool is_qnan(float in) +/** Check whether a given float is qNaN. + * @param in Input value */ +AI_FORCE_INLINE bool is_qnan(float in) { - return (in != in); + // the straightforward solution does not work: + // return (in != in); + // compiler generates code like this + // load to + // compare against + + // FIXME: Use stuff instead? I think fpclassify needs C99 + return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1 && + reinterpret_cast<_IEEESingle*>(&in)->IEEE.Frac); } // --------------------------------------------------------------------------- -/** @brief check whether a float is NOT qNaN. - * @param in Input value - */ -AI_FORCE_INLINE bool is_not_qnan(float in) +/** Check whether a float is NOT qNaN. + * @param in Input value */ +AI_FORCE_INLINE bool is_not_qnan(float in) { - return (in == in); + return !is_qnan(in); } // --------------------------------------------------------------------------- /** @brief check whether a float is either NaN or (+/-) INF. * * Denorms return false, they're treated like normal values. - * @param in Input value - */ + * @param in Input value */ AI_FORCE_INLINE bool is_special_float(float in) { - return (((_IEEESingle*)&in)->IEEE.Exp == (1u << 8)-1); + return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1); } // --------------------------------------------------------------------------- -/** @brief Get a qnan - */ +/** @brief Get a fresh qnan. */ AI_FORCE_INLINE float get_qnan() { return std::numeric_limits::quiet_NaN();