/*
  Cloth Physics
  www.lewpen.com
*/

#define WIN32_LEAN_AND_MEAN

#include <math.h>

#include	"qe_ogl.h"


double x[64][64], y[64][64], z[64][64];
double nx[64][64], ny[64][64], nz[64][64];

int spheres = 5;
double ssx[5], ssy[5], ssz[5], ssr[5];
double sx[5], sy[5], sz[5], sr[5];

double dist[5][5];

BOOL DrawMe = FALSE;

double r1=0, r2=0;

double a = 0;



double sphere_x[16][16];
double sphere_y[16][16];
double sphere_z[16][16];

void Sphere(double sx, double sy, double sz, double sr)
{
  int i, j;
  double x, y, z;

  for(j=0; j<16; j++) for(i=0; i<16; i++) {
    x = sr*sin(i*3.14159/16);
    y = sr*cos(i*3.14159/16);
    z = 0;

    //  Rotate about y axis

    double nx = z*sin(j*3.14159/8) + x*cos(j*3.14159/8);
    double ny = y;
    double nz = z*cos(j*3.14159/8) - x*sin(j*3.14159/8);

    sphere_x[j][i] = sx+nx;
    sphere_y[j][i] = sy+ny;
    sphere_z[j][i] = sz+nz;
  }

  double r, g, b;
  int ii, jj;

  for(j=0; j<16; j++) for(i=0; i<16; i++) {

    ii = (i+1)&15;
    jj = (j+1)&15;

    if(((i^j)&1) == 0) {
      r = 1.0; g = 1.0; b = 1.0;
    } else {
      r = 1.0; g = 0.0; b = 0.0;
    }

    glBegin(GL_TRIANGLE_STRIP);
      glColor3f(r, g, b);
      glVertex3f(sphere_x[ j][ i], sphere_y[ j][ i], sphere_z[ j][ i]);
      glVertex3f(sphere_x[ j][ii], sphere_y[ j][ii], sphere_z[ j][ii]);
      glVertex3f(sphere_x[jj][ i], sphere_y[jj][ i], sphere_z[jj][ i]);
      glVertex3f(sphere_x[jj][ii], sphere_y[jj][ii], sphere_z[jj][ii]);
    glEnd();

  }
   
}



void Initialise()
{
  int i, j;

  for(j=0; j<32; j++) for(i=0; i<32; i++) {
    x[j][i] = (i-16)*0.1;
    y[j][i] = 1.5;
    z[j][i] = (j-16)*0.1;
  }

  for(j=0; j<5; j++) for(i=0; i<5; i++) {
    dist[j][i] = sqrt((2-i)*(2-i) + (2-j)*(2-j));
  }

  ssx[0] =  0.9; ssy[0] = -0.7; ssz[0] =  0.9; ssr[0] = 0.5;
  ssx[1] =  0.2; ssy[1] = -0.4; ssz[1] = -0.8; ssr[1] = 0.5;
  ssx[2] = -0.4; ssy[2] = -0.3; ssz[2] =  0.6; ssr[2] = 0.5;
  ssx[3] = -0.3; ssy[3] = -1.7; ssz[3] = -0.7; ssr[3] = 0.5;
  ssx[4] = -0.6; ssy[4] = -1.2; ssz[4] = -0.3; ssr[4] = 0.5;
  spheres = 5;

}




void GameDraw()
{
  int i, j, ii, jj, k, kk;

  double r, g, b;
  double d, dd;

  //  Move spheres

  for(i=0; i<5; i++) {
    sx[i] = ssx[i];
    sy[i] = ssy[i];
    sz[i] = ssz[i];
    sr[i] = ssr[i];
  }

  a ++;

  sy[0] = ssy[0] - 1.16*cos(-a*3.14159*0.0007722-0.5947);
  sy[1] = ssy[1] - 1.67*cos(-a*3.14159*0.0006224+0.1344);
  sy[2] = ssy[2] - 1.42*sin(-a*3.14159*0.0004629+0.6143);
  sy[3] = ssy[3] + 1.55*cos(-a*3.14159*0.0003726-0.8941);
  sy[4] = ssy[4] - 1.71*cos(-a*3.14159*0.0001722-0.7228);

  //  Move cloth

  double mx, my, mz;
  double vx, vy, vz;

  for(k=0; k<15; k++) {

  for(j=0; j<32; j++) {
    for(i=0; i<32; i++) {

      mx = 0; my = -0.001; mz = 0;

      for(jj=j-1; jj<=j+1; jj++) if(jj>=0 && jj<32) {
        for(ii=i-1; ii<=i+1; ii++) if(ii>=0 && ii<32) if(ii != i || jj != j) {
          vx = x[jj][ii] - x[j][i];
          vy = y[jj][ii] - y[j][i];
          vz = z[jj][ii] - z[j][i];

          d = vx*vx+vy*vy+vz*vz;
          dd = 0.03 * (sqrt(d)-0.1*dist[2+jj-j][2+ii-i])/(d);

          mx += vx*dd;
          my += vy*dd;
          mz += vz*dd;
        }
      }

      nx[j][i] = x[j][i] + mx; ny[j][i] = y[j][i] + my; nz[j][i] = z[j][i] + mz;

      //  Floor collision

      if(ny[j][i] < -2.999) ny[j][i] = -2.999;

      //  Sphere collision

      for(kk = 0; kk<spheres; kk++) {
        d = (nx[j][i]-sx[kk])*(nx[j][i]-sx[kk]) + (ny[j][i]-sy[kk])*(ny[j][i]-sy[kk]) + (nz[j][i]-sz[kk])*(nz[j][i]-sz[kk]);
        if(d < sr[kk]*sr[kk]) {
          d = sr[kk]/sqrt(d);
          nx[j][i] = (nx[j][i]-sx[kk])*d + sx[kk];
          ny[j][i] = (ny[j][i]-sy[kk])*d + sy[kk];
          nz[j][i] = (nz[j][i]-sz[kk])*d + sz[kk];
        }
      }

    }
  }

  for(j=0; j<32; j++) for(i=0; i<32; i++) {
    x[j][i] = nx[j][i];
    y[j][i] = ny[j][i];
    z[j][i] = nz[j][i];
  }

  }

  //  Draw spheres

  for(k = 0; k<spheres; k++) {
    Sphere(sx[k], sy[k], sz[k], sr[k]-0.01);
  }

  //  Draw floor

  for(j=0; j<8; j++) {
    for(i=0; i<8; i++) {

      if(((i^j)&1) == 0) {
        r = 0.9; g = 0.9; b = 0.9;
      } else {
        r = 0.1; g = 0.1; b = 0.1;
      }

      glBegin(GL_TRIANGLE_STRIP);
        glColor3f(r, g, b);
        glVertex3f(0.5*(i-4), -3, 0.5*(j-4));
        glVertex3f(0.5*(i-3), -3, 0.5*(j-4));
        glVertex3f(0.5*(i-4), -3, 0.5*(j-3));
        glVertex3f(0.5*(i-3), -3, 0.5*(j-3));
      glEnd();

    }
  }

  //  Draw cloth

  for(j=0; j<31; j++) {
    for(i=0; i<31; i++) {

      if(((i^j)&1) == 0) {
        r = 1.0; g = 1.0; b = 0.0;
      } else {
        r = 0.0; g = 0.0; b = 1.0;
      }

      glBegin(GL_TRIANGLE_STRIP);
        glColor3f(r, g, b); glVertex3f(x[j  ][i  ], y[j  ][i  ], z[j  ][i  ]);
        glColor3f(r, g, b); glVertex3f(x[j  ][i+1], y[j  ][i+1], z[j  ][i+1]);
        glColor3f(r, g, b); glVertex3f(x[j+1][i  ], y[j+1][i  ], z[j+1][i  ]);
        glColor3f(r, g, b); glVertex3f(x[j+1][i+1], y[j+1][i+1], z[j+1][i+1]);
      glEnd();

    }
  }

}



void GameMain()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glTranslatef(0.f, 0.f, -5.f);

	glRotatef(-r2*0.2, 1.0, 0.0, 0.0);
	glRotatef(-r1*0.2, 0.0, 1.0, 0.0);

	GameDraw();
	SwapBuffers (gl_dc);
}


