vrshoot

diff libs/assimp/FixNormalsStep.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/FixNormalsStep.cpp	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,176 @@
     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 +/** @file Implementation of the post processing step to invert
    1.46 + * all normals in meshes with infacing normals.
    1.47 + */
    1.48 +
    1.49 +#include "AssimpPCH.h"
    1.50 +
    1.51 +// internal headers
    1.52 +#include "FixNormalsStep.h"
    1.53 +
    1.54 +using namespace Assimp;
    1.55 +
    1.56 +
    1.57 +// ------------------------------------------------------------------------------------------------
    1.58 +// Constructor to be privately used by Importer
    1.59 +FixInfacingNormalsProcess::FixInfacingNormalsProcess()
    1.60 +{
    1.61 +	// nothing to do here
    1.62 +}
    1.63 +
    1.64 +// ------------------------------------------------------------------------------------------------
    1.65 +// Destructor, private as well
    1.66 +FixInfacingNormalsProcess::~FixInfacingNormalsProcess()
    1.67 +{
    1.68 +	// nothing to do here
    1.69 +}
    1.70 +
    1.71 +// ------------------------------------------------------------------------------------------------
    1.72 +// Returns whether the processing step is present in the given flag field.
    1.73 +bool FixInfacingNormalsProcess::IsActive( unsigned int pFlags) const
    1.74 +{
    1.75 +	return (pFlags & aiProcess_FixInfacingNormals) != 0;
    1.76 +}
    1.77 +
    1.78 +// ------------------------------------------------------------------------------------------------
    1.79 +// Executes the post processing step on the given imported data.
    1.80 +void FixInfacingNormalsProcess::Execute( aiScene* pScene)
    1.81 +{
    1.82 +	DefaultLogger::get()->debug("FixInfacingNormalsProcess begin");
    1.83 +
    1.84 +	bool bHas = false;
    1.85 +	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
    1.86 +		if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
    1.87 +
    1.88 +	if (bHas)
    1.89 +		 DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. Found issues.");
    1.90 +	else DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. No changes to the scene.");
    1.91 +}
    1.92 +
    1.93 +// ------------------------------------------------------------------------------------------------
    1.94 +// Apply the step to the mesh
    1.95 +bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
    1.96 +{
    1.97 +	ai_assert(NULL != pcMesh);
    1.98 +
    1.99 +	// Nothing to do if there are no model normals
   1.100 +	if (!pcMesh->HasNormals())return false;
   1.101 +
   1.102 +	// Compute the bounding box of both the model vertices + normals and
   1.103 +	// the umodified model vertices. Then check whether the first BB
   1.104 +	// is smaller than the second. In this case we can assume that the
   1.105 +	// normals need to be flipped, although there are a few special cases ..
   1.106 +	// convex, concave, planar models ...
   1.107 +
   1.108 +	aiVector3D vMin0 (1e10f,1e10f,1e10f);
   1.109 +	aiVector3D vMin1 (1e10f,1e10f,1e10f);
   1.110 +	aiVector3D vMax0 (-1e10f,-1e10f,-1e10f);
   1.111 +	aiVector3D vMax1 (-1e10f,-1e10f,-1e10f);
   1.112 +
   1.113 +	for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
   1.114 +	{
   1.115 +		vMin1.x = std::min(vMin1.x,pcMesh->mVertices[i].x);
   1.116 +		vMin1.y = std::min(vMin1.y,pcMesh->mVertices[i].y);
   1.117 +		vMin1.z = std::min(vMin1.z,pcMesh->mVertices[i].z);
   1.118 +
   1.119 +		vMax1.x = std::max(vMax1.x,pcMesh->mVertices[i].x);
   1.120 +		vMax1.y = std::max(vMax1.y,pcMesh->mVertices[i].y);
   1.121 +		vMax1.z = std::max(vMax1.z,pcMesh->mVertices[i].z);
   1.122 +
   1.123 +		const aiVector3D vWithNormal = pcMesh->mVertices[i] + pcMesh->mNormals[i];
   1.124 +
   1.125 +		vMin0.x = std::min(vMin0.x,vWithNormal.x);
   1.126 +		vMin0.y = std::min(vMin0.y,vWithNormal.y);
   1.127 +		vMin0.z = std::min(vMin0.z,vWithNormal.z);
   1.128 +
   1.129 +		vMax0.x = std::max(vMax0.x,vWithNormal.x);
   1.130 +		vMax0.y = std::max(vMax0.y,vWithNormal.y);
   1.131 +		vMax0.z = std::max(vMax0.z,vWithNormal.z);
   1.132 +	}
   1.133 +
   1.134 +	const float fDelta0_x = (vMax0.x - vMin0.x);
   1.135 +	const float fDelta0_y = (vMax0.y - vMin0.y);
   1.136 +	const float fDelta0_z = (vMax0.z - vMin0.z);
   1.137 +
   1.138 +	const float fDelta1_x = (vMax1.x - vMin1.x);
   1.139 +	const float fDelta1_y = (vMax1.y - vMin1.y);
   1.140 +	const float fDelta1_z = (vMax1.z - vMin1.z);
   1.141 +
   1.142 +	// Check whether the boxes are overlapping
   1.143 +	if ((fDelta0_x > 0.0f) != (fDelta1_x > 0.0f))return false;
   1.144 +	if ((fDelta0_y > 0.0f) != (fDelta1_y > 0.0f))return false;
   1.145 +	if ((fDelta0_z > 0.0f) != (fDelta1_z > 0.0f))return false;
   1.146 +
   1.147 +	// Check whether this is a planar surface
   1.148 +	const float fDelta1_yz = fDelta1_y * fDelta1_z;
   1.149 +
   1.150 +	if (fDelta1_x < 0.05f * sqrtf( fDelta1_yz ))return false;
   1.151 +	if (fDelta1_y < 0.05f * sqrtf( fDelta1_z * fDelta1_x ))return false;
   1.152 +	if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false;
   1.153 +
   1.154 +	// now compare the volumes of the bounding boxes
   1.155 +	if (::fabsf(fDelta0_x * fDelta1_yz) <
   1.156 +		::fabsf(fDelta1_x * fDelta1_y * fDelta1_z))
   1.157 +	{
   1.158 +		if (!DefaultLogger::isNullLogger())
   1.159 +		{
   1.160 +			char buffer[128]; // should be sufficiently large
   1.161 +			::sprintf(buffer,"Mesh %i: Normals are facing inwards (or the mesh is planar)",index);
   1.162 +			DefaultLogger::get()->info(buffer);
   1.163 +		}
   1.164 +
   1.165 +		// Invert normals
   1.166 +		for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
   1.167 +			pcMesh->mNormals[i] *= -1.0f;
   1.168 +
   1.169 +		// ... and flip faces
   1.170 +		for (unsigned int i = 0; i < pcMesh->mNumFaces;++i)
   1.171 +		{
   1.172 +			aiFace& face = pcMesh->mFaces[i];
   1.173 +			for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
   1.174 +				std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
   1.175 +		}
   1.176 +		return true;
   1.177 +	}
   1.178 +	return false;
   1.179 +}