
Moderator: Alain


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 );
}Users browsing this forum: No registered users and 1 guest