Пример #1
0
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;
    }

}
Пример #2
0
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();
}
Пример #3
0
		//Returns the normal at (x, z)
		Vec3f getNormal(int x, int z) {
			if (!computedNormals) {
				computeNormals();
			}
			return normals[z][x];
		}
Пример #4
0
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;
}
Пример #5
0
/* 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;
}