// Wild Magic Source Code // David Eberly // http://www.geometrictools.com // Copyright (c) 1998-2007 // // This library is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation; either version 2.1 of the License, or (at // your option) any later version. The license is available for reading at // either of the locations: // http://www.gnu.org/copyleft/lgpl.html // http://www.geometrictools.com/License/WildMagicLicense.pdf // The license applies to versions 0 through 4 of Wild Magic. // // Version: 4.0.0 (2006/06/28) #include "Wm4FoundationPCH.h" #include "Wm4MeshSmoother.h" namespace Wm4 { //---------------------------------------------------------------------------- template MeshSmoother::MeshSmoother () { m_iVQuantity = 0; m_akVertex = nullptr; m_iTQuantity = 0; m_aiIndex = nullptr; m_akNormal = nullptr; m_akMean = nullptr; m_aiNeighborCount = nullptr; } //---------------------------------------------------------------------------- template MeshSmoother::MeshSmoother (int iVQuantity, Vector3* akVertex, int iTQuantity, const int* aiIndex) { m_akVertex = nullptr; m_akNormal = nullptr; m_aiIndex = nullptr; m_akMean = nullptr; m_aiNeighborCount = nullptr; Create(iVQuantity,akVertex,iTQuantity,aiIndex); } //---------------------------------------------------------------------------- template MeshSmoother::~MeshSmoother () { Destroy(); } //---------------------------------------------------------------------------- template void MeshSmoother::Create (int iVQuantity, Vector3* akVertex, int iTQuantity, const int* aiIndex) { // remove previously allocated smoother data Destroy(); m_iVQuantity = iVQuantity; m_akVertex = akVertex; m_iTQuantity = iTQuantity; m_aiIndex = aiIndex; m_akNormal = WM4_NEW Vector3[m_iVQuantity]; m_akMean = WM4_NEW Vector3[m_iVQuantity]; m_aiNeighborCount = WM4_NEW int[m_iVQuantity]; // count the number of vertex neighbors memset(m_aiNeighborCount,0,m_iVQuantity*sizeof(int)); const int* piIndex = m_aiIndex; for (int i = 0; i < m_iTQuantity; i++) { m_aiNeighborCount[*piIndex++] += 2; m_aiNeighborCount[*piIndex++] += 2; m_aiNeighborCount[*piIndex++] += 2; } } //---------------------------------------------------------------------------- template void MeshSmoother::Destroy () { WM4_DELETE[] m_akNormal; WM4_DELETE[] m_akMean; WM4_DELETE[] m_aiNeighborCount; } //---------------------------------------------------------------------------- template void MeshSmoother::Update (Real fTime) { std::fill_n(m_akNormal,m_iVQuantity,Vector3{0,0,0}); std::fill_n(m_akMean,m_iVQuantity,Vector3{0,0,0}); const int* piIndex = m_aiIndex; int i; for (i = 0; i < m_iTQuantity; i++) { int iV0 = *piIndex++; int iV1 = *piIndex++; int iV2 = *piIndex++; Vector3& rkV0 = m_akVertex[iV0]; Vector3& rkV1 = m_akVertex[iV1]; Vector3& rkV2 = m_akVertex[iV2]; Vector3 kEdge1 = rkV1 - rkV0; Vector3 kEdge2 = rkV2 - rkV0; Vector3 kNormal = kEdge1.Cross(kEdge2); m_akNormal[iV0] += kNormal; m_akNormal[iV1] += kNormal; m_akNormal[iV2] += kNormal; m_akMean[iV0] += rkV1 + rkV2; m_akMean[iV1] += rkV2 + rkV0; m_akMean[iV2] += rkV0 + rkV1; } for (i = 0; i < m_iVQuantity; i++) { m_akNormal[i].Normalize(); m_akMean[i] /= (Real)m_aiNeighborCount[i]; } for (i = 0; i < m_iVQuantity; i++) { if (VertexInfluenced(i,fTime)) { Vector3 kLocalDiff = m_akMean[i] - m_akVertex[i]; Vector3 kSurfaceNormal = kLocalDiff.Dot(m_akNormal[i]) * m_akNormal[i]; Vector3 kTangent = kLocalDiff - kSurfaceNormal; Real fTWeight = GetTangentWeight(i,fTime); Real fNWeight = GetNormalWeight(i,fTime); m_akVertex[i] += fTWeight*kTangent + fNWeight*m_akNormal[i]; } } } //---------------------------------------------------------------------------- template bool MeshSmoother::VertexInfluenced (int, Real) { return true; } //---------------------------------------------------------------------------- template Real MeshSmoother::GetTangentWeight (int, Real) { return (Real)0.5; } //---------------------------------------------------------------------------- template Real MeshSmoother::GetNormalWeight (int, Real) { return (Real)0.0; } //---------------------------------------------------------------------------- template int MeshSmoother::GetVQuantity () const { return m_iVQuantity; } //---------------------------------------------------------------------------- template const Vector3* MeshSmoother::GetVertices () const { return m_akVertex; } //---------------------------------------------------------------------------- template int MeshSmoother::GetTQuantity () const { return m_iTQuantity; } //---------------------------------------------------------------------------- template const int* MeshSmoother::GetIndices () const { return m_aiIndex; } //---------------------------------------------------------------------------- template const Vector3* MeshSmoother::GetNormals () const { return m_akNormal; } //---------------------------------------------------------------------------- template const Vector3* MeshSmoother::GetMeans () const { return m_akMean; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // explicit instantiation //---------------------------------------------------------------------------- template WM4_FOUNDATION_ITEM class MeshSmoother; template WM4_FOUNDATION_ITEM class MeshSmoother; //---------------------------------------------------------------------------- }