Cloth simulation

Share with us how are you using the powerrrr of the force

Moderator: Alain

Cloth simulation

Postby Brain » Thu Mar 15, 2007 5:27 pm

I've started "messing" around with Newton and here are some screens of a cloth simulation i made this afternood/evening. still needs some tweaking, but works pretty ok . i've set linear and angular dumping at 0.8 but it still "wiggles" a lot, any ideas how to improve this?


Image
Image
Image
Image
Image
Image
Brain
 
Posts: 7
Joined: Sun Feb 26, 2006 3:21 pm
Location: Romania

Postby Julio Jerez » Thu Mar 15, 2007 5:42 pm

how are you doing that? :o
I guess as proof of concept it OK :)
Newton constraint solver is too expensive for cloth simulation. But the math of cloth simulation are embedded in solver.

This is what I would do.
I would try to get it as good as I can possible can just as a prove of concept or prototype but never for production.
1.6 Archemidea will add a constraint particle solver that will be used for soft bodies, cloth and fluids. It will be much faster for those things.

I assume you are using ball and socket for the simulation, and if that's is truth then you can play with joint stiftness.
However I do not think it will be stable enough because the angular dof intruduce lot of instability, but you do not loss anything trying.

I had implemented cloth on comercial games before, do not worried Newton will have cloth, the reason It does not yet is because there are higher priorites in the pipe.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Postby Brain » Thu Mar 15, 2007 5:56 pm

i'm not using any joints, i'm doing things the "usual" way cloth sim. is done: with springs. i connect the nodes (rigid spheres whose collisions and movement is taken care of by Newton) with springs that add an elastic force based on the distance between the nodes (F=(+/-)x*k).that keeps the nodes together and makes movement somewhat natural. rendering looks ugly for now (just a quad grid...). i achieved some good stability by increasing the size of the spheres (nodes) to 0.1 and adding some more mass (1.0) and using smth like 100-200N/m for the spring constant.
Brain
 
Posts: 7
Joined: Sun Feb 26, 2006 3:21 pm
Location: Romania

Postby Julio Jerez » Thu Mar 15, 2007 6:16 pm

Ha ok, still good experiment. :D
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Postby bakura10 » Fri Mar 16, 2007 1:16 pm

Great :). I tried to do that with Newton Playground by creating some boxes and connect them with nodes, but it was awfully slow ! Can we have a video ? :d.
bakura10
 
Posts: 30
Joined: Sun Sep 17, 2006 11:39 am
Location: France

Postby walaber » Sat Mar 17, 2007 1:59 am

i did something similar for my trampoline game as well, but I ended up using thin boxes to connect the nodes together, to get better coverage when interacting with other bodies.
Independent game developer of (mostly) physics-based games. Creator of "JellyCar" and lead designer of "Where's My Water?"
User avatar
walaber
Moderator
Moderator
 
Posts: 393
Joined: Wed Mar 17, 2004 3:40 am
Location: California, USA

video available

Postby Brain » Sat Mar 17, 2007 6:05 am

here is the video: http://www.youtube.com/watch?v=xo_n9q1KWgE .
the low fps (~10) is because i also render the level&other things (with lost of shaders on my lousy fx 5500). real performance is about 120 fps on my machine (athlon 2800+ ,512ddr).i don't have time for a demo,but i could post source code if anyone is interested.
Brain
 
Posts: 7
Joined: Sun Feb 26, 2006 3:21 pm
Location: Romania

Postby bakura10 » Sat Mar 17, 2007 6:50 am

Really really great 8)
bakura10
 
Posts: 30
Joined: Sun Sep 17, 2006 11:39 am
Location: France

last screens: stress test

Postby Brain » Sun Mar 18, 2007 6:34 am

last post/screenshots , stress test: 10,000 (100x100 nodes), the cloth hangs over half the level :)
Image
wireframe:
Image
wireframe+node objects:
Image
Brain
 
Posts: 7
Joined: Sun Feb 26, 2006 3:21 pm
Location: Romania

Postby bakura10 » Sun Mar 18, 2007 6:41 am

Really really great. It is fast ?
bakura10
 
Posts: 30
Joined: Sun Sep 17, 2006 11:39 am
Location: France

Postby Brain » Sun Mar 18, 2007 6:49 am

i'm not sure (?). i get ~8 fps with 10,000 nodes (much more than i would ever use) and >100 fps with up to 1000 nodes (still a lot). so i guess it's ok.
Brain
 
Posts: 7
Joined: Sun Feb 26, 2006 3:21 pm
Location: Romania

Postby bakura10 » Sun Mar 18, 2007 7:01 am

100 fps, it's quite fast :).
bakura10
 
Posts: 30
Joined: Sun Sep 17, 2006 11:39 am
Location: France

source code

Postby Marcelo Nunes » Thu Apr 12, 2007 12:05 pm

It showed frantic, could you please post the code, i´m in devlopment of a 3d shoot´n´up and this appeared to be perfect for a jelly enemy i was thinking about, the game was in the irrlicht forum at:

http://irrlicht.sourceforge.net/phpBB2/ ... highlight=

if you could post your code i´ll be thankfully..
Marcelo Nunes
 

Postby Brain » Mon Apr 16, 2007 5:04 am

in a few days i'll upload some code, because i'm busy at the moment and i need to clean the source a bit.
Brain
 
Posts: 7
Joined: Sun Feb 26, 2006 3:21 pm
Location: Romania

Postby Brain » Wed May 09, 2007 7:13 am

sorry for the delay, here's the code (some classes missing, but the cloth stuff is there and easy to modify):

Code: Select all

class CNewtonSpring
{
public:
        float l;    //initial lenght
        float k;    //elasticity constant
        CNewtonBody *b0,*b1;    //the two bodies connected by the spring

        void Init(float l,float k,CNewtonBody *b0,CNewtonBody *b1);   //initialize
        void Force();   //calculate and apply force on the connected bodies
};

class CNewtonCloth
{
public:
        float pos[3];
        int nr_nod,nr_spring;

        CNewtonBody *nod;   //the nodes (small bodies)
        CNewtonSpring *spring;  //the springs connecting the nodes

         ~CNewtonCloth()
        {
            delete [] nod;
            delete [] spring;
        }

        void Init(float pos[3],int nr_nod);
        void Debug();
};


//adds a force to a body at the specified point (in global space)
void CNewtonBody::AddGlobalForce (CVector3 Force,CVector3 Point)   

{

  float matrix[4][4];

  CVector3 Rvec;



  NewtonBodyGetMatrix(body, &matrix[0][0]);



  Rvec.x=Point.x-matrix[3][0];

  Rvec.y=Point.y-matrix[3][1];

  Rvec.z=Point.z-matrix[3][2];



  CVector3 Torque = Cross (Rvec, Force);

  force[0]+=Force.x;

  force[1]+=Force.y;

  force[2]+=Force.z;

  torque[0]+=Torque.x;

  torque[1]+=Torque.y;

  torque[2]+=Torque.z;

}

/************************************************
*
*       CNewtonSpring & CNewtonCloth class functions
*
************************************************/

void CNewtonSpring::Init(float l,float k,CNewtonBody *b0,CNewtonBody *b1)
{
  this->l=l;
  this->k=k;
  this->b0=b0;
  this->b1=b1;
}

void CNewtonSpring::Force()
{
  CVector3 p[2];      //spatial position of the bodies b0 and b1
  CVector3 v,Fe[2];   //vector from b0->b1 and forces F1/F2
  float d;            //distance between b0 and b1
  float F;            //the force magnitude
  float matrix[4][4]; //transform matrix

  NewtonBodyGetMatrix(b0->body, &matrix[0][0]);
  p[0].x=matrix[3][0];
  p[0].y=matrix[3][1];
  p[0].z=matrix[3][2];

  NewtonBodyGetMatrix(b1->body, &matrix[0][0]);
  p[1].x=matrix[3][0];
  p[1].y=matrix[3][1];
  p[1].z=matrix[3][2];

  v.x=p[1].x-p[0].x;
  v.y=p[1].y-p[0].y;
  v.z=p[1].z-p[0].z;

  d=Magnitude(v);
  v=Normalize(v);
  F=-(l-d)*k;

  Fe[0].x=F*v.x;
  Fe[0].y=F*v.y;
  Fe[0].z=F*v.z;

  Fe[1].x=-F*v.x;
  Fe[1].y=-F*v.y;
  Fe[1].z=-F*v.z;

//    log("d=%f\n",d);
  //log("l=%f\n",l);

  b0->AddGlobalForce(Fe[0],p[0]);
  b1->AddGlobalForce(Fe[1],p[1]);

}

void CNewtonCloth::Init(float pos[3],int nr_nod)   //initializes the cloth object (position and number of nodes)
{
  float p[3],s[3],spring_lenght=0.3f,size,spring_constant;
  int i,j,k,k1,k2,k3;
  int nr=(int)sqrt((float)nr_nod);    //nodes/side (considering a square patch)

  this->nr_nod=nr_nod;
  this->pos[0]=pos[0];
  this->pos[1]=pos[1];
  this->pos[2]=pos[2];

  //the nodes are small spheres with this radius
  s[0]=0.2f;
  s[1]=0.2f;
  s[2]=0.2f;
  size=nr*(s[0]+spring_lenght);

  /** the fiber structure (* means node, /|\ means spring)
  *--*--*--*
  |\/|\/|\/|
  *--*--*--*
  .......... 
  **/

  nod=new CNewtonBody[nr_nod];  //create nodes
  spring=new CNewtonSpring[2*nr*(nr-1)+2*(nr-1)*(nr-1)];    //create springs

  //initialize nodes as a plane paralell with XOZ (Y=cst.) - temp
  for (i=0;i<nr;i++)
    for (j=0;j<nr;j++)
      {
        k=nr*i+j;
        p[0]=pos[0]+(-size/2.0f)+j*(s[0]+spring_lenght);
        p[1]=pos[1];
        p[2]=pos[2]+(-size/2.0f)+i*(s[0]+spring_lenght);

        nod[k].Init(s,1.0f,p,CLOTH,true);   //initialize the node obj

        physics.AddSphere(&nod[k]);
        NewtonBodySetLinearDamping(nod[k].body,0.8f);   //TEST
        float ang_damp[3]={0.8f,0.8f,0.8f};
        NewtonBodySetAngularDamping (nod[k].body,ang_damp);
      }

  //init springs
  k=0;
  spring_constant=260.0f;    //k=260 N/m  (play with this for various effects)
  for (i=0;i<nr-1;i++)     
    for (j=0;j<nr-1;j++)
      {
        k1=nr*i+j;
        k2=nr*i+j+1;
        spring[k].Init(s[0]+spring_lenght,spring_constant,&nod[k1],&nod[k2]);   //connect adjacent bodies

        if (j==nr-2) //connect last column
          {
            k++;
            k3=nr*(i+1)+j+1;
            spring[k].Init(s[0]+spring_lenght,spring_constant,&nod[k2],&nod[k3]);
          }

        k++;
        k2=nr*(i+1)+j;
        spring[k].Init(s[0]+spring_lenght,spring_constant,&nod[k1],&nod[k2]);

        if (i==nr-2)    //connect last row
          {
            k++;
            k3=nr*(i+1)+j+1;
            spring[k].Init(s[0]+spring_lenght,spring_constant,&nod[k2],&nod[k3]);
          }

        //connect diagonal neighbours
        if (j>0 && j<=nr-2)   
          {
            k++;
            k2=nr*(i+1)+j-1;
            spring[k].Init(s[0]+spring_lenght,spring_constant,&nod[k1],&nod[k2]);

            k++;
            k2=nr*(i+1)+j+1;
            spring[k].Init(s[0]+spring_lenght,spring_constant,&nod[k1],&nod[k2]);
          }
        else
          if (j==0)   
            {
              k++;
              k2=nr*(i+1)+j+1;
              spring[k].Init(s[0]+spring_lenght,spring_constant,&nod[k1],&nod[k2]);
            }
        if (j==nr-2)   
              {
                k++;
                k2=nr*i+j+1;
                k3=nr*(i+1)+j;
                spring[k].Init(s[0]+spring_lenght,spring_constant,&nod[k2],&nod[k3]);
              }


        k++;
      }

  nr_spring=k;

}

void CNewtonCloth::Debug()   //simulates and draws the cloth
{
  float matrix[4][4];

    //apply spring forces (move to Update() function) - temp
   
    for (int i=0;i<nr_spring;i++) spring[i].Force();

    int nr=(int)sqrt((float)nr_nod);
    int k=0,k1,k2,k3;

   //draw as quads

    glDisable(GL_CULL_FACE);
    glActiveTextureARB(GL_TEXTURE0_ARB);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,tex_manager.textures[4].texID);
    //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    //glLineWidth(2.0f);

    for (int i=0;i<nr-1;i++)
    for (int j=0;j<nr-1;j++)
    {
        k=nr*i+j;
        k1=nr*i+j+1;
        k2=nr*(i+1)+j+1;
        k3=nr*(i+1)+j;

        glPushMatrix();
        glColor3f(1,1,1);
        glBegin(GL_QUADS);
        glTexCoord2f(0,0);
        NewtonBodyGetMatrix(nod[k].body, &matrix[0][0]);
        glVertex3f(matrix[3][0],matrix[3][1],matrix[3][2]);

        glTexCoord2f(0,1);
        NewtonBodyGetMatrix(nod[k1].body, &matrix[0][0]);
        glVertex3f(matrix[3][0],matrix[3][1],matrix[3][2]);

        glTexCoord2f(1,1);
        NewtonBodyGetMatrix(nod[k2].body, &matrix[0][0]);
        glVertex3f(matrix[3][0],matrix[3][1],matrix[3][2]);

        glTexCoord2f(1,0);
        NewtonBodyGetMatrix(nod[k3].body, &matrix[0][0]);
        glVertex3f(matrix[3][0],matrix[3][1],matrix[3][2]);
        glEnd();
        glPopMatrix();
    }
    glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
}
Brain
 
Posts: 7
Joined: Sun Feb 26, 2006 3:21 pm
Location: Romania

Next

Return to User Gallery

Who is online

Users browsing this forum: No registered users and 14 guests

cron