void Mesh::samplePosition(const Point2f &sample, Point3f &p, Normal3f &n) const { Point2f reusableSample = sample; //get a random face uint32_t faceIndex = m_dpdf->sampleReuse(reusableSample(0)); // sample the triangle of the face Point2f uv = Warp::squareToTriangle(reusableSample); //get the vertex index uint32_t i0 = m_F(0, faceIndex), i1 = m_F(1, faceIndex), i2 = m_F(2, faceIndex); //get the points Point3f p0 = m_V.col(i0), p1 = m_V.col(i1), p2 = m_V.col(i2); //compute the edge vectors Vector3f edge1 = (p1 - p0); Vector3f edge2 = (p2 - p0); Vector3f e1 = uv(0) * edge1; Vector3f e2 = uv(1) * edge2; //compute the new point p = p0 + e1 + e2; //compute the normal base on baycentric coordinates //get the vertex normals if(m_N.cols() > 3) { Normal3f n0 = m_N.col(i0), n1 = m_N.col(i1), n2 = m_N.col(i2); Vector3f w0 = p0 - p; Vector3f w1 = p1 - p; Vector3f w2 = p2 - p; float area = (edge1.cross(edge2)).norm(); if(area != 0.0f){ float u = (w0.cross(w1)).norm() / area; float v = (w1.cross(w2)).norm() / area; n = (1.0f - u - v) * n0 + v * n1 + u * n2; n.normalized(); } else { n = (e1.cross(e2)).normalized(); } } else { //no normals provided n = (e1.cross(e2)).normalized(); if(isnan(n.sum())){ cout << "Normal is nan" << endl; cout << "e1 " << e1 << endl; cout << "e2 " << e2 << endl; } } //n = uv(0) * n0 + uv(1) * n1 + (1.0f - uv(0) - uv(1)) * n2; }
float Mesh::surfaceArea(uint32_t index) const { uint32_t i0 = m_F(0, index), i1 = m_F(1, index), i2 = m_F(2, index); const Point3f p0 = m_V.col(i0), p1 = m_V.col(i1), p2 = m_V.col(i2); return 0.5f * Vector3f((p1 - p0).cross(p2 - p0)).norm(); }
void BoysFunction::setx(double x) { if (x <= 50){ m_F(m_nMax) = tabulated(m_nMax, x); } else { m_F(m_nMax) = asymptotic(m_nMax, x); } double ex = exp(-x); for(int n = m_nMax; n > 0; n--){ m_F(n-1) = (2*x*m_F(n) + ex)/(2*n - 1); } }
bool Mesh::rayIntersect(uint32_t index, const Ray3f &ray, float &u, float &v, float &t) const { uint32_t i0 = m_F(0, index), i1 = m_F(1, index), i2 = m_F(2, index); const Point3f p0 = m_V.col(i0), p1 = m_V.col(i1), p2 = m_V.col(i2); /* Find vectors for two edges sharing v[0] */ Vector3f edge1 = p1 - p0, edge2 = p2 - p0; /* Begin calculating determinant - also used to calculate U parameter */ Vector3f pvec = ray.d.cross(edge2); /* If determinant is near zero, ray lies in plane of triangle */ float det = edge1.dot(pvec); if (det > -1e-8f && det < 1e-8f) return false; float inv_det = 1.0f / det; /* Calculate distance from v[0] to ray origin */ Vector3f tvec = ray.o - p0; /* Calculate U parameter and test bounds */ u = tvec.dot(pvec) * inv_det; if (u < 0.0 || u > 1.0) return false; /* Prepare to test V parameter */ Vector3f qvec = tvec.cross(edge1); /* Calculate V parameter and test bounds */ v = ray.d.dot(qvec) * inv_det; if (v < 0.0 || u + v > 1.0) return false; /* Ray intersects triangle -> compute t */ t = edge2.dot(qvec) * inv_det; return t >= ray.mint && t <= ray.maxt; }
Point3f Mesh::getCentroid(uint32_t index) const { return (1.0f / 3.0f) * (m_V.col(m_F(0, index)) + m_V.col(m_F(1, index)) + m_V.col(m_F(2, index))); }
BoundingBox3f Mesh::getBoundingBox(uint32_t index) const { BoundingBox3f result(m_V.col(m_F(0, index))); result.expandBy(m_V.col(m_F(1, index))); result.expandBy(m_V.col(m_F(2, index))); return result; }
double BoysFunction::returnValue(int n) { return m_F(n); }
//------------------------------------------------------------------------------ void PD_OSP::calculateForces(const std::pair<int, int> &idCol) { const int pId = idCol.first; const int col_i = idCol.second; const double a_i = m_data(col_i, m_indexA); const double b_i = m_data(col_i, m_indexB); const double d_i = m_data(col_i, m_indexD); const double theta_i = m_data(col_i, m_indexTheta); vector<pair<int, vector<double>>> & PDconnections = m_particles.pdConnections(pId); double r_i[3]; double r0_i[3]; double f_i[3]; for(int d=0; d<m_dim; d++) { f_i[d] = 0; r_i[d] = m_r(d, col_i); r0_i[d] = m_r0(d, col_i); } const int nConnections = PDconnections.size(); double dr_ij[3]; double thetaNew = 0; for(int l_j=0; l_j<nConnections; l_j++) { auto &con = PDconnections[l_j]; if(con.second[m_indexConnected] <= 0.5) continue; const int id_j = con.first; const int j = m_pIds[id_j]; const double a_j = m_data(j, m_indexA); const double b_j = m_data(j, m_indexB); const double d_j = m_data(j, m_indexD); const double theta_j = m_data(j, m_indexTheta); const double vol_j = m_data(j, m_indexVolume); const double dr0 = con.second[m_indexDr0]; const double volumeScaling = con.second[m_indexVolumeScaling]; const double a_ij = 0.5*(a_i + a_j); const double b_ij = 0.5*(b_i + b_j); const double d_ij = 0.5*(d_i + d_j); const double Gd_ij = con.second[m_indexForceScalingDilation]; const double Gb_ij = con.second[m_indexForceScalingBond]; double dr2 = 0; double A_ij = 0; // The lambda-factor for(int d=0; d<m_dim; d++) { dr_ij[d] = m_r(d, j) - r_i[d]; dr2 += dr_ij[d]*dr_ij[d]; A_ij += dr_ij[d]*(m_r0(d, j) - r0_i[d]); } const double dr = sqrt(dr2); A_ij /= (dr0*dr); double ds = dr - dr0; // To avoid roundoff errors if (fabs(ds) < THRESHOLD) ds = 0.0; const double s = ds/dr0; const double fbond = (a_ij*d_ij*Gd_ij*A_ij/dr0*(theta_i + theta_j) + b_ij*Gb_ij*s) *vol_j*volumeScaling/dr; for(int d=0; d<m_dim; d++) { f_i[d] += dr_ij[d]*fbond; } thetaNew += d_ij*s*A_ij*vol_j*volumeScaling; con.second[m_indexStretch] = s; } for(int d=0; d<m_dim; d++) { m_F(d, col_i) += m_delta*f_i[d]; } m_data(col_i, m_indexThetaNew) = m_delta*thetaNew; }
//------------------------------------------------------------------------------ void PD_LPS_porosity_adrmc::calculateForces(const int id, const int i) { const double theta_i = m_data(i, m_iTheta); const double m_i = m_data(i, m_iMass); const double a_i = m_data(i, m_iA); const double b_i = m_data(i, m_iA); vector<pair<int, vector<double>>> &PDconnections = m_particles.pdConnections(id); const int nConnections = PDconnections.size(); double dr0_ij[m_dim]; double dr_ij[m_dim]; _F.zeros(); double thetaNew = 0; int nConnected = 0; //---------------------------------- // TMP - standard stress calc from // m_data(i, m_indexStress[0]) = 0; // m_data(i, m_indexStress[1]) = 0; // m_data(i, m_indexStress[2]) = 0; //---------------------------------- for (int l_j = 0; l_j < nConnections; l_j++) { auto &con = PDconnections[l_j]; if (con.second[m_iConnected] <= 0.5) continue; const int id_j = con.first; const int j = m_idToCol_v[id_j]; const double m_j = m_data(j, m_iMass); const double theta_j = m_data(j, m_iTheta); const double vol_j = m_data(j, m_iVolume); const double dr0 = con.second[m_iDr0]; const double volumeScaling = con.second[m_iVolumeScaling]; const double vol = vol_j * volumeScaling; const double w = weightFunction(dr0); const double a_j = m_data(j, m_iA); const double b_j = m_data(j, m_iB); double dr2 = 0; for (int d = 0; d < m_dim; d++) { dr0_ij[d] = m_r0(j, d) - m_r0(i, d); dr_ij[d] = m_r(j, d) - m_r(i, d); dr2 += dr_ij[d] * dr_ij[d]; } const double dr = sqrt(dr2); const double ds = dr - dr0; double bond = (b_i * theta_i / m_i + b_j * theta_j / m_j) * dr0; bond += (a_i / m_i + a_j / m_j) * ds; bond *= w * vol / dr; thetaNew += w * dr0 * ds * vol; for (int d = 0; d < m_dim; d++) { m_F(i, d) += dr_ij[d] * bond; for (int d2 = 0; d2 < m_dim; d2++) { _F(d, d2) += w * dr_ij[d] * dr0_ij[d2] * vol; } } con.second[m_iStretch] = ds / dr0; //---------------------------------- // TMP - standard stres calc from // m_data(i, m_indexStress[0]) += 0.5*dr_ij[0]*dr_ij[0]*bond; // m_data(i, m_indexStress[1]) += 0.5*dr_ij[1]*dr_ij[1]*bond; // m_data(i, m_indexStress[2]) += 0.5*dr_ij[0]*dr_ij[1]*bond; //---------------------------------- nConnected++; } if (nConnections <= 3) { m_data(i, m_iThetaNew) = 0; } else { m_data(i, m_iThetaNew) = m_dim / m_i * thetaNew; } //---------------------------------- // TMP - standard stres calc from //---------------------------------- // if(nConnected > 5) { // computeStress(id, i, nConnected); // } computeStress(id, i, nConnected); //-------------------- m_continueState = false; }
//------------------------------------------------------------------------------ void PD_LPS::calculateForces(const std::pair<int, int> &idCol) { const int pId = idCol.first; const int i = idCol.second; const double theta_i = m_data(i, m_iTheta); const double m_i = m_data(i, m_iMass); double alpha; if(m_dim == 3) alpha = 15*m_mu; else alpha = 8*m_mu; const double c = (3*m_k - 5*m_mu); vector<pair<int, vector<double>>> & PDconnections = m_particles.pdConnections(pId); double r_i[m_dim]; double r0_i[m_dim]; double f_i[m_dim]; for(int d=0; d<m_dim; d++) { f_i[d] = 0; r_i[d] = m_r(d, i); r0_i[d] = m_r0(d, i); } const int nConnections = PDconnections.size(); double dr_ij[m_dim]; double thetaNew = 0; for(int l_j=0; l_j<nConnections; l_j++) { auto &con = PDconnections[l_j]; if(con.second[m_iConnected] <= 0.5) continue; const int id_j = con.first; const int j = m_pIds[id_j]; const double m_j = m_data(j, m_iMass); const double theta_j = m_data(j, m_iTheta); const double vol_j = m_data(j, m_iVolume); const double dr0 = con.second[m_iDr0]; const double volumeScaling = con.second[m_iVolumeScaling]; const double gb_ij = con.second[m_iForceScalingBond]; const double gd_ij = con.second[m_iForceScalingDilation]; double dr2 = 0; for(int d=0; d<m_dim; d++) { dr_ij[d] = m_r(d, j) - r_i[d]; dr2 += dr_ij[d]*dr_ij[d]; } const double dr = sqrt(dr2); const double ds = dr - dr0; double bond = gd_ij*c*(theta_i/m_i + theta_j/m_j)*dr0; bond += gb_ij*alpha*(1./m_i + 1./m_j)*ds; bond *= vol_j*volumeScaling/dr; thetaNew += dr0*ds*vol_j*volumeScaling; for(int d=0; d<m_dim; d++) { m_F(d, i) += dr_ij[d]*bond; } con.second[m_iStretch] = ds/dr0; } m_data(i, m_iThetaNew) = m_dim/m_i*thetaNew; }