nuclear@0: /* nuclear@0: --------------------------------------------------------------------------- nuclear@0: Open Asset Import Library (assimp) nuclear@0: --------------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the following nuclear@0: conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: --------------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file Generation of normal vectors basing on smoothing groups */ nuclear@0: nuclear@0: #ifndef AI_SMOOTHINGGROUPS_INL_INCLUDED nuclear@0: #define AI_SMOOTHINGGROUPS_INL_INCLUDED nuclear@0: nuclear@0: // internal headers nuclear@0: #include "SGSpatialSort.h" nuclear@0: nuclear@0: // CRT header nuclear@0: #include nuclear@0: nuclear@0: using namespace Assimp; nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: template nuclear@0: void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups& sMesh) nuclear@0: { nuclear@0: // First generate face normals nuclear@0: sMesh.mNormals.resize(sMesh.mPositions.size(),aiVector3D()); nuclear@0: for( unsigned int a = 0; a < sMesh.mFaces.size(); a++) nuclear@0: { nuclear@0: T& face = sMesh.mFaces[a]; nuclear@0: nuclear@0: aiVector3D* pV1 = &sMesh.mPositions[face.mIndices[0]]; nuclear@0: aiVector3D* pV2 = &sMesh.mPositions[face.mIndices[1]]; nuclear@0: aiVector3D* pV3 = &sMesh.mPositions[face.mIndices[2]]; nuclear@0: nuclear@0: aiVector3D pDelta1 = *pV2 - *pV1; nuclear@0: aiVector3D pDelta2 = *pV3 - *pV1; nuclear@0: aiVector3D vNor = pDelta1 ^ pDelta2; nuclear@0: nuclear@0: for (unsigned int c = 0; c < 3;++c) nuclear@0: sMesh.mNormals[face.mIndices[c]] = vNor; nuclear@0: } nuclear@0: nuclear@0: // calculate the position bounds so we have a reliable epsilon to check position differences against nuclear@0: aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f); nuclear@0: for( unsigned int a = 0; a < sMesh.mPositions.size(); a++) nuclear@0: { nuclear@0: minVec.x = std::min( minVec.x, sMesh.mPositions[a].x); nuclear@0: minVec.y = std::min( minVec.y, sMesh.mPositions[a].y); nuclear@0: minVec.z = std::min( minVec.z, sMesh.mPositions[a].z); nuclear@0: maxVec.x = std::max( maxVec.x, sMesh.mPositions[a].x); nuclear@0: maxVec.y = std::max( maxVec.y, sMesh.mPositions[a].y); nuclear@0: maxVec.z = std::max( maxVec.z, sMesh.mPositions[a].z); nuclear@0: } nuclear@0: const float posEpsilon = (maxVec - minVec).Length() * 1e-5f; nuclear@0: std::vector avNormals; nuclear@0: avNormals.resize(sMesh.mNormals.size()); nuclear@0: nuclear@0: // now generate the spatial sort tree nuclear@0: SGSpatialSort sSort; nuclear@0: for( typename std::vector::iterator i = sMesh.mFaces.begin(); nuclear@0: i != sMesh.mFaces.end();++i) nuclear@0: { nuclear@0: for (unsigned int c = 0; c < 3;++c) nuclear@0: sSort.Add(sMesh.mPositions[(*i).mIndices[c]],(*i).mIndices[c],(*i).iSmoothGroup); nuclear@0: } nuclear@0: sSort.Prepare(); nuclear@0: nuclear@0: std::vector vertexDone(sMesh.mPositions.size(),false); nuclear@0: for( typename std::vector::iterator i = sMesh.mFaces.begin(); nuclear@0: i != sMesh.mFaces.end();++i) nuclear@0: { nuclear@0: std::vector poResult; nuclear@0: for (unsigned int c = 0; c < 3;++c) nuclear@0: { nuclear@0: register unsigned int idx = (*i).mIndices[c]; nuclear@0: if (vertexDone[idx])continue; nuclear@0: nuclear@0: sSort.FindPositions(sMesh.mPositions[idx],(*i).iSmoothGroup, nuclear@0: posEpsilon,poResult); nuclear@0: nuclear@0: aiVector3D vNormals; nuclear@0: for (std::vector::const_iterator nuclear@0: a = poResult.begin(); nuclear@0: a != poResult.end();++a) nuclear@0: { nuclear@0: vNormals += sMesh.mNormals[(*a)]; nuclear@0: } nuclear@0: vNormals.Normalize(); nuclear@0: nuclear@0: // write back into all affected normals nuclear@0: for (std::vector::const_iterator nuclear@0: a = poResult.begin(); nuclear@0: a != poResult.end();++a) nuclear@0: { nuclear@0: idx = *a; nuclear@0: avNormals [idx] = vNormals; nuclear@0: vertexDone[idx] = true; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: sMesh.mNormals = avNormals; nuclear@0: } nuclear@0: nuclear@0: #endif // !! AI_SMOOTHINGGROUPS_INL_INCLUDED