/** \file elbeem/intern/mvmcoords.cpp * \ingroup elbeem */ /****************************************************************************** * // El'Beem - the visual lattice boltzmann freesurface simulator // All code distributed as part of El'Beem is covered by the version 2 of the // GNU General Public License. See the file COPYING for details. // // Copyright 2008 Nils Thuerey , Richard Keiser, Mark Pauly, Ulrich Ruede // * * Mean Value Mesh Coords class * *****************************************************************************/ #include "mvmcoords.h" #include #if defined(_MSC_VER) && _MSC_VER > 1600 // std::greater #include #endif using std::vector; void MeanValueMeshCoords::clear() { mVertices.resize(0); mNumVerts = 0; } void MeanValueMeshCoords::calculateMVMCs(vector &reference_vertices, vector &tris, vector &points, gfxReal numweights) { clear(); mvmTransferPoint tds; int mem = 0; int i = 0; mNumVerts = (int)reference_vertices.size(); for (vector::iterator iter = points.begin(); iter != points.end(); ++iter, ++i) { /* if(i%(points.size()/10)==1) debMsgStd("MeanValueMeshCoords::calculateMVMCs",DM_MSG,"Computing weights, points: "< &reference_vertices, vector& tris, mvmTransferPoint& tds, gfxReal numweights) { const bool mvmFullDebug=false; //const ntlVec3Gfx cEPS = 1.0e-6; const mvmFloat cEPS = 1.0e-14; //mvmFloat d[3], s[3], phi[3],c[3]; ntlVec3d u[3],c,d,s,phi; int indices[3]; for (int i = 0; i < (int)reference_vertices.size(); ++i) { tds.weights.push_back(mvmIndexWeight(i, 0.0)); } // for each triangle //for (vector::iterator iter = tris.begin(); iter != tris.end();) { for(int t=0; t<(int)tris.size(); t++) { for (int i = 0; i < 3; ++i) { //, ++iter) { indices[i] = tris[t].getPoints()[i]; u[i] = vec2D(reference_vertices[ indices[i] ]-tds.lastpos); d[i] = normalize(u[i]); //.normalize(); //assert(d[i] != 0.); if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","t"< ignore it"); continue; } const mvmFloat u0x = u[0][0]; const mvmFloat u0y = u[0][1]; const mvmFloat u0z = u[0][2]; const mvmFloat u1x = u[1][0]; const mvmFloat u1y = u[1][1]; const mvmFloat u1z = u[1][2]; const mvmFloat u2x = u[2][0]; const mvmFloat u2y = u[2][1]; const mvmFloat u2z = u[2][2]; mvmFloat det = u0x*u1y*u2z - u0x*u1z*u2y + u0y*u1z*u2x - u0y*u1x*u2z + u0z*u1x*u2y - u0z*u1y*u2x; //assert(det != 0.); if (det < 0.) { s[0] = -s[0]; s[1] = -s[1]; s[2] = -s[2]; } tds.weights[indices[0]].weight += (phi[0]-c[1]*phi[2]-c[2]*phi[1])/(d[0]*sin(phi[1])*s[2]); tds.weights[indices[1]].weight += (phi[1]-c[2]*phi[0]-c[0]*phi[2])/(d[1]*sin(phi[2])*s[0]); tds.weights[indices[2]].weight += (phi[2]-c[0]*phi[1]-c[1]*phi[0])/(d[2]*sin(phi[0])*s[1]); if(mvmFullDebug) { errMsg("MeanValueMeshCoords::computeWeights","i"<0.)&& (numweights<1.) ) { //if( ((int)tds.weights.size() > maxNumWeights) && (maxNumWeights > 0) ) { int maxNumWeights = (int)(tds.weights.size()*numweights); if(maxNumWeights<=0) maxNumWeights = 1; std::sort(tds.weights.begin(), tds.weights.end(), std::greater()); // only use maxNumWeights-th largest weights tds.weights.resize(maxNumWeights); } // normalize weights mvmFloat totalWeight = 0.; for (vector::const_iterator witer = tds.weights.begin(); witer != tds.weights.end(); ++witer) { totalWeight += witer->weight; } mvmFloat invTotalWeight; if (totalWeight == 0.) { if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","totalWeight == 0"); invTotalWeight = 0.0; } else { invTotalWeight = 1.0/totalWeight; } for (vector::iterator viter = tds.weights.begin(); viter != tds.weights.end(); ++viter) { viter->weight *= invTotalWeight; //assert(finite(viter->weight) != 0); if(!finite(viter->weight)) viter->weight=0.; } } void MeanValueMeshCoords::transfer(vector &vertices, vector& displacements) { displacements.resize(0); //debMsgStd("MeanValueMeshCoords::transfer",DM_MSG,"vertices:"<::iterator titer = mVertices.begin(); titer != mVertices.end(); ++titer) { mvmTransferPoint &tds = *titer; ntlVec3Gfx newpos(0.0); for (vector::iterator witer = tds.weights.begin(); witer != tds.weights.end(); ++witer) { newpos += vertices[witer->index] * witer->weight; //errMsg("transfer","np"<index]<<" w"<< witer->weight); } displacements.push_back(newpos); //displacements.push_back(newpos - tds.lastpos); //tds.lastpos = newpos; } }