void Balloon::update() { // update position & speed Eigen::MatrixXd X_n(m_positions.rows(), m_positions.cols()); Eigen::MatrixXd V_n(m_speeds.rows(), m_speeds.cols()); for(int i=0; i<m_positions.rows(); i++) { Eigen::Vector3d v_n; Eigen::Vector3d x_p = m_positions.row(i); Eigen::Vector3d v_p = m_speeds.row(i); Eigen::Vector3d f_p = m_forces.row(i); if(true) { // v_n = ((m_mass-m_step*(-c*m_adjacency_list[i].size()))*v_p +(f_p-c*v_p)*m_step)/(m_mass-m_step*(-c*m_adjacency_list[i].size())-m_step*m_step*(-k*m_adjacency_list[i].size())); // v_n = ((m_mass-m_step*(-c))*v_p + f_p)/(m_mass-m_step*(-c)-m_step*m_step*(-k)); v_n = ((m_mass-m_step*(-d))*v_p + f_p-d*v_p)/(m_mass-m_step*(-d)-m_step*m_step*(-k)); // v_n = ((m_mass-m_step*(-d))*v_p +(f_p-d*v_p)*m_step)/(m_mass-m_step*(-d)-m_step*m_step*(-k*m_adjacency_list[i].size())); } { v_n = v_p + m_step / m_mass * f_p; } X_n.row(i) = x_p + m_step * v_n; V_n.row(i) = v_n; } m_positions = X_n; m_speeds = V_n; checkfloor(); calcAveRadius(); m_forces = Eigen::MatrixXd::Zero(m_positions.rows(), m_positions.cols()); if(!isActive) { // m_air_pressure /= 5.0; for(int i=0; i<m_positions.rows(); i++) { m_forces.row(i) += m_mass * g * Eigen::Vector3d(0,0,-1); } for(int i=0; i<m_faces.rows(); i++) { if(m_faceactive(i) == 0) { for(int j=0; j<3; j++) { std::vector<int> faceids = m_vertextoface[m_faces(i,j)]; for(int k=0; k<faceids.size(); k++) { m_threshold_ratio(m_facetoedge(faceids[k],0)) /= 2.0; m_threshold_ratio(m_facetoedge(faceids[k],1)) /= 2.0; m_threshold_ratio(m_facetoedge(faceids[k],2)) /= 2.0; } } } } } // check activity for(int i=0; i<m_edges.rows(); i++) { if(m_edgeactive(i) == 1) { Eigen::Vector3d l = m_positions.row(m_edges(i,0)) - m_positions.row(m_edges(i,1)); if(l.norm() > m_edgelength(i)*threshold_ratio) { m_edgeactive(i) = 0; m_faceactive(m_edgetoface(i,0)) = 0; m_faceactive(m_edgetoface(i,1)) = 0; isActive = false; } } } // calc forces for(int i=0; i<m_edges.rows(); i++) { if(m_edgeactive(i) == 1) { Eigen::Vector3d f_n = Eigen::Vector3d(0,0,0); Eigen::Vector3d x_1 = m_positions.row(m_edges(i,0)); Eigen::Vector3d x_2 = m_positions.row(m_edges(i,1)); Eigen::Vector3d v_1 = m_speeds.row(m_edges(i,0)); Eigen::Vector3d v_2 = m_speeds.row(m_edges(i,1)); if((x_1-x_2).norm()>m_edgelength(i)){ f_n -= k*((x_1 - x_2).norm() - m_edgelength(i))*(x_1 - x_2).normalized(); } else{ f_n -= 1.0*k*((x_1 - x_2).norm() - m_edgelength(i))*(x_1 - x_2).normalized(); } f_n -= c*((v_1 - v_2).dot((x_1 - x_2).normalized()))*(x_1 - x_2).normalized(); m_forces.row(m_edges(i,0)) += f_n; m_forces.row(m_edges(i,1)) += -f_n; } } computeNormals(); if(useWater) { m_forces += m_air_pressure * m_normals / (double)m_average_radius; // std::cout << "p_force" << m_air_pressure * (double)m_average_radius*(double)m_average_radius*4.0*M_PI/m_num_point<< std::endl; } { m_forces += m_air_pressure * m_normals / (double)m_average_radius; // std::cout << "p_force" << m_air_pressure / (double)m_average_radius << std::endl; } }
void Mesh::clean() { uint i, j, idist=0; Vector a, b, c, m; double mdist=0.; arr Tc(T.d0, 3); //tri centers arr Tn(T.d0, 3); //tri normals uintA Vt(V.d0); intA VT(V.d0, 100); //tri-neighbors to a vertex Vt.setZero(); VT=-1; for(i=0; i<T.d0; i++) { a.set(&V(T(i, 0), 0)); b.set(&V(T(i, 1), 0)); c.set(&V(T(i, 2), 0)); //tri center m=(a+b+c)/3.; Tc(i, 0)=m.x; Tc(i, 1)=m.y; Tc(i, 2)=m.z; //farthest tri if(m.length()>mdist) { mdist=m.length(); idist=i; } //tri normal b-=a; c-=a; a=b^c; a.normalize(); Tn(i, 0)=a.x; Tn(i, 1)=a.y; Tn(i, 2)=a.z; //vertex neighbor count j=T(i, 0); VT(j, Vt(j))=i; Vt(j)++; j=T(i, 1); VT(j, Vt(j))=i; Vt(j)++; j=T(i, 2); VT(j, Vt(j))=i; Vt(j)++; } //step through tri list and flip them if necessary boolA Tisok(T.d0); Tisok=false; uintA Tok; //contains the list of all tris that are ok oriented uintA Tnew(T.d0, T.d1); Tok.append(idist); Tisok(idist)=true; int A=0, B=0, D; uint r, k, l; intA neighbors; for(k=0; k<Tok.N; k++) { i=Tok(k); Tnew(k, 0)=T(i, 0); Tnew(k, 1)=T(i, 1); Tnew(k, 2)=T(i, 2); for(r=0; r<3; r++) { if(r==0) { A=T(i, 0); B=T(i, 1); /*C=T(i, 2);*/ } if(r==1) { A=T(i, 1); B=T(i, 2); /*C=T(i, 0);*/ } if(r==2) { A=T(i, 2); B=T(i, 0); /*C=T(i, 1);*/ } //check all triangles that share A & B setSection(neighbors, VT[A], VT[B]); neighbors.removeAllValues(-1); if(neighbors.N>2) MT_MSG("edge shared by more than 2 triangles " <<neighbors); neighbors.removeValue(i); //if(!neighbors.N) cout <<"mesh.clean warning: edge has only one triangle that shares it" <<endl; //orient them correctly for(l=0; l<neighbors.N; l++) { j=neighbors(l); //j is a neighboring triangle sharing A & B D=-1; //align the neighboring triangle and let D be its 3rd vertex if((int)T(j, 0)==A && (int)T(j, 1)==B) D=T(j, 2); if((int)T(j, 0)==A && (int)T(j, 2)==B) D=T(j, 1); if((int)T(j, 1)==A && (int)T(j, 2)==B) D=T(j, 0); if((int)T(j, 1)==A && (int)T(j, 0)==B) D=T(j, 2); if((int)T(j, 2)==A && (int)T(j, 0)==B) D=T(j, 1); if((int)T(j, 2)==A && (int)T(j, 1)==B) D=T(j, 0); if(D==-1) HALT("dammit"); //determine orientation if(!Tisok(j)) { T(j, 0)=B; T(j, 1)=A; T(j, 2)=D; Tok.append(j); Tisok(j)=true; } else { //check if consistent! } } #if 0 //compute their rotation if(neighbors.N>1) { double phi, phimax; int jmax=-1; Vector ni, nj; for(l=0; l<neighbors.N; l++) { j=neighbors(l); //j is a neighboring triangle sharing A & B a.set(&V(T(i, 0), 0)); b.set(&V(T(i, 1), 0)); c.set(&V(T(i, 2), 0)); b-=a; c-=a; a=b^c; a.normalize(); ni = a; a.set(&V(T(j, 0), 0)); b.set(&V(T(j, 1), 0)); c.set(&V(T(j, 2), 0)); b-=a; c-=a; a=b^c; a.normalize(); nj = a; Quaternion q; q.setDiff(ni, -nj); q.getDeg(phi, c); a.set(&V(A, 0)); b.set(&V(B, 0)); if(c*(a-b) < 0.) phi+=180.; if(jmax==-1 || phi>phimax) { jmax=j; phimax=phi; } } if(!Tisok(jmax)) { Tok.append(jmax); Tisok(jmax)=true; } } else { j = neighbors(0); if(!Tisok(j)) { Tok.append(j); Tisok(j)=true; } } #endif } } if(k<T.d0) { cout <<"mesh.clean warning: not all triangles connected: " <<k <<"<" <<T.d0 <<endl; cout <<"WARNING: cutting of all non-connected triangles!!" <<endl; Tnew.resizeCopy(k, 3); T=Tnew; deleteUnusedVertices(); } computeNormals(); }
//Returns the normal at (x, z) Vec3f getNormal(int x, int z) { if (!computedNormals) { computeNormals(); } return normals[z][x]; }
bool ccQuadric::buildUp() { if (m_drawPrecision < MIN_DRAWING_PRECISION) return false; unsigned vertCount = m_drawPrecision*m_drawPrecision; unsigned triCount = (m_drawPrecision-1)*(m_drawPrecision-1)*2; if (!init(vertCount,true,triCount,0)) { ccLog::Error("[ccQuadric::buildUp] Not enough memory"); return false; } ccPointCloud* verts = vertices(); assert(verts); assert(verts->hasNormals()); CCVector2 areaSize = m_maxCorner - m_minCorner; PointCoordinateType stepX = areaSize.x/static_cast<PointCoordinateType>(m_drawPrecision-1); PointCoordinateType stepY = areaSize.y/static_cast<PointCoordinateType>(m_drawPrecision-1); m_minZ = m_minZ = 0; for (unsigned x=0; x<m_drawPrecision; ++x) { CCVector3 P(m_minCorner.x + stepX * x, 0, 0); for (unsigned y=0; y<m_drawPrecision; ++y) { P.y = m_minCorner.y + stepY * y; P.z = m_eq[0] + m_eq[1]*P.x + m_eq[2]*P.y + m_eq[3]*P.x*P.x + m_eq[4]*P.x*P.y + m_eq[5]*P.y*P.y; //compute the min and max heights of the quadric! if (x != 0 || y != 0) { if (m_minZ > P.z) m_minZ = P.z; else if (m_maxZ < P.z) m_maxZ = P.z; } else { m_minZ = m_maxZ = P.z; } verts->addPoint(P); //normal --> TODO: is there a simple way to deduce it from the equation? //CCVector3 N; //N.x = m_eq[1] + 2*m_eq[3]*P.x + m_eq[4]*P.y; //N.y = m_eq[2] + 2*m_eq[5]*P.y + m_eq[4]*P.x; //N.z = -PC_ONE; //N.normalize(); //verts->addNorm(N); if (x != 0 && y != 0) { unsigned iA = (x-1) * m_drawPrecision + y-1; unsigned iB = iA + 1; unsigned iC = iA + m_drawPrecision; unsigned iD = iB + m_drawPrecision; addTriangle(iA,iC,iB); addTriangle(iB,iC,iD); } } } computeNormals(true); return true; }
/* Constructs a mesh out of the specified MeshData */ Mesh::Mesh(const MeshData &data) { m_nVertices = data.vertices.size(); m_nNormals = data.normals.size(); m_nUVs = data.uvs.size(); m_nTriangles = data.triangles.size(); ASSERT(m_nVertices > 0); ASSERT(m_nTriangles > 0); ASSERT(m_nUVs >= 0); m_vertices = new Vertex[m_nVertices]; m_normals = new Normal[m_nNormals]; m_uvs = new UV[m_nUVs]; m_triangles = new MeshTriangle[m_nTriangles]; // TODO: heuristic for choosing MeshTriangle or MeshTriangleFast //if (m_nTriangles > (1 << 15)) { // m_triangles = new MeshTriangle[m_nTriangles]; //} else { // m_triangles = new MeshTriangleFast[m_nTriangles]; //} /* Copy data over from other mesh */ if (m_nVertices > 0) memcpy(m_vertices, &data.vertices[0], sizeof(Vertex) * m_nVertices); if (m_nNormals > 0) memcpy(m_normals, &data.normals[0], sizeof(Normal) * m_nNormals); if (m_nUVs > 0) memcpy(m_uvs, &data.uvs[0], sizeof(UV) * m_nUVs); if (m_nTriangles > 0) memcpy(m_triangles, &data.triangles[0], sizeof(MeshTriangle) * m_nTriangles); /*for(unsigned i = m_nVertices; i--;) m_vertices[i] = data.vertices[i]; for(unsigned i = m_nNormals; i--;) m_normals[i] = data.normals[i]; for(unsigned i = m_nUVs; i--;) m_uvs[i] = data.uvs[i];*/ for(unsigned i = m_nTriangles; i--;) { //m_triangles[i] = data.triangles[i]; m_triangles[i].mesh = this; /*if (m_triangles[i].A >= m_nVertices) cerr << i << ", A, " << m_triangles[i].A << endl; if (m_triangles[i].B >= m_nVertices) cerr << i << ", B, " << m_triangles[i].B << endl; if (m_triangles[i].C >= m_nVertices) cerr << i << ", C, " << m_triangles[i].C << endl;*/ ASSERT(m_triangles[i].A < m_nVertices); ASSERT(m_triangles[i].B < m_nVertices); ASSERT(m_triangles[i].C < m_nVertices); if (m_nNormals > 0) { ASSERT(m_triangles[i].nA < m_nNormals); ASSERT(m_triangles[i].nB < m_nNormals); ASSERT(m_triangles[i].nC < m_nNormals); } if (m_nUVs > 0) { ASSERT(m_triangles[i].tA < m_nUVs); ASSERT(m_triangles[i].tB < m_nUVs); ASSERT(m_triangles[i].tC < m_nUVs); } } if (0 == m_nNormals) computeNormals(); m_batch = 0; m_spatialAccel = NULL; }