test.cpp

C++ source for Polychorons, 686 lines. Raw file

#define WIN32_LEAN_AND_MEAN


/*

http://en.wikipedia.org/wiki/Schlegel_diagram
http://en.wikipedia.org/wiki/Stereographic_projection
http://en.wikipedia.org/wiki/Image:Cantitruncated_tesseract.png

http://en.wikipedia.org/wiki/User:Rocchini

*/


#include <math.h>

#include	"qe_ogl.h"
#include "mmsystem.h"

double r1=0, r2=0;
BOOL DrawMe = TRUE;

#define LENGTH 400

double ax[1000], ay[1000], az[1000];
double ax1[1000], ay1[1000], az1[1000];
double ax2[1000], ay2[1000], az2[1000];



//---- INCLUDE COMMON FILES




GLuint	texture[1];


template <class T>
class Pair
{
private:
	T p[2];
public:
	Pair()
	{
	}

	Pair( T a, T b )
	{
		p[0] = a;
		p[1] = b;
	}

	T a() { return p[0]; }
	T b() { return p[1]; }
};



class Colour
{
private:
	double c[4];

public:
	Colour( double r, double g, double b, double a = 1.0 )
	{
		c[0] = r;
		c[1] = g;
		c[2] = b;
		c[3] = a;
	}

	double r() { return c[0]; }
	double g() { return c[1]; }
	double b() { return c[2]; }
	double a() { return c[3]; }
};



class vec3
{
private:
	double p[3];

public:
	vec3()
	{
		p[0] = p[1] = p[2] = 0;
	}

	vec3( double x, double y, double z )
	{
		p[0] = x;
		p[1] = y;
		p[2] = z;
	}

	double x() { return p[0]; }
	double y() { return p[1]; }
	double z() { return p[2]; }

	double length2()
	{
		return p[0]*p[0] + p[1]*p[1] + p[2]*p[2];
	}

	double length()
	{
		return sqrt( length2() );
	}
};



class vec4
{
private:
	double p[4];

public:

	vec4()
	{
		p[0] = p[1] = p[2] = p[3] = 0;
	}

	vec4( double x, double y, double z, double w )
	{
		p[0] = x;
		p[1] = y;
		p[2] = z;
		p[3] = w;
	}

	double x() { return p[0]; }
	double y() { return p[1]; }
	double z() { return p[2]; }
	double w() { return p[3]; }

	vec4 normalise()
	{
		double d = sqrt( p[0]*p[0] + p[1]*p[1] + p[2]*p[2] + p[3]*p[3] );

		if( d == 0 )
		{
			return vec4();
		}

		d = 1.0 / d;

		return vec4
		(
			p[0] * d,
			p[1] * d,
			p[2] * d,
			p[3] * d
		);
	}

	vec4 interpolate( vec4 b, double d )
	{
		return vec4
		(
			p[0] * (1.0-d) + b.p[0] * d,
			p[1] * (1.0-d) + b.p[1] * d,
			p[2] * (1.0-d) + b.p[2] * d,
			p[3] * (1.0-d) + b.p[3] * d
		);
	}

	vec3 stereographicProjection()
	{
		double oo1mz = 1.0 / ( 1.0 - p[3] );

		return vec3
		(
			p[0] * oo1mz,
			p[1] * oo1mz,
			p[2] * oo1mz
		);
	}

	vec4 rotate( int axis1, int axis2, double r )
	{
		vec4 a = *this;

		if( axis1 >= 0 && axis1 < 4 && axis2 >= 0 && axis2 < 4 )
		{
			a.p[ axis1 ] = p[ axis1 ] * sin(r) + p[ axis2 ] * cos(r);
			a.p[ axis2 ] = p[ axis1 ] * cos(r) - p[ axis2 ] * sin(r);
		}

		return a;
	}

	vec4 rotate6( double r[6] )
	{
		return
			rotate( 0, 1, r[0] ).
			rotate( 0, 2, r[1] ).
			rotate( 0, 3, r[2] ).
			rotate( 1, 2, r[3] ).
			rotate( 1, 3, r[4] ).
			rotate( 2, 3, r[5] );
	}
};





//---- Cube

void Cube(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2, GLfloat r, GLfloat g, GLfloat b)
{
  glColor3f(r, g, b);

  glBegin(GL_TRIANGLE_FAN);
    glVertex3f(x1, y1, z1);
    glVertex3f(x1, y1, z2);
    glVertex3f(x2, y1, z2);
    glVertex3f(x2, y1, z1);
  glEnd();

  glBegin(GL_TRIANGLE_FAN);
    glVertex3f(x2, y2, z1);
    glVertex3f(x2, y2, z2);
    glVertex3f(x1, y2, z2);
    glVertex3f(x1, y2, z1);
  glEnd();

  glColor3f(r*0.95, g*0.95, b*0.95);

  glBegin(GL_TRIANGLE_FAN);
    glVertex3f(x1, y2, z1);
    glVertex3f(x1, y2, z2);
    glVertex3f(x1, y1, z2);
    glVertex3f(x1, y1, z1);
  glEnd();

  glBegin(GL_TRIANGLE_FAN);
    glVertex3f(x2, y1, z1);
    glVertex3f(x2, y1, z2);
    glVertex3f(x2, y2, z2);
    glVertex3f(x2, y2, z1);
  glEnd();

  glColor3f(r*0.90, g*0.90, b*0.90);

  glBegin(GL_TRIANGLE_FAN);
    glVertex3f(x2, y1, z1);
    glVertex3f(x2, y2, z1);
    glVertex3f(x1, y2, z1);
    glVertex3f(x1, y1, z1);
  glEnd();

  glBegin(GL_TRIANGLE_FAN);
    glVertex3f(x1, y1, z2);
    glVertex3f(x1, y2, z2);
    glVertex3f(x2, y2, z2);
    glVertex3f(x2, y1, z2);
  glEnd();

}


void Cube( vec3 pos, double size, Colour col )
{
	Cube
	(
		pos.x()-size, pos.y()-size, pos.z()-size,
		pos.x()+size, pos.y()+size, pos.z()+size,
		col.r(), col.g(), col.b()
	);
}





void getviewpoint(double *mx, double *my, double *mz, double r1, double r2)
{
  double vx = 0, vy = 0, vz = 0;

  double wx, wy, wz;

//  r1 = -r1;
//  r2 = -r2;

    vx = 0;
    vy = 0;
    vz = 15;

    wx = vx;
    wy = vy*cos(0.2*r2*3.14159/180)-vz*sin(0.2*r2*3.14159/180);
    wz = -(vy*sin(0.2*r2*3.14159/180)+vz*cos(0.2*r2*3.14159/180));

    vx = wx*cos(0.2*r1*3.14159/180)-wz*sin(0.2*r1*3.14159/180);
    vy = wy;
    vz = -(wx*sin(0.2*r1*3.14159/180)+wz*cos(0.2*r1*3.14159/180));

  *mx = vx; *my = vy; *mz = vz;
}



void getscreenpoint(double *mx, double *my, double *mz, double w1, double w2, double w3, double r1, double r2)
{
  double vx = 0, vy = 0, vz = 0;

  double wx, wy, wz;

  r1 = -r1;
  r2 = -r2;

  vx = wx*cos(0.2*r1*3.14159/180)-wz*sin(0.2*r1*3.14159/180);
  vy = wy;
  vz = -(wx*sin(0.2*r1*3.14159/180)+wz*cos(0.2*r1*3.14159/180));

  wx = vx;
  wy = vy*cos(0.2*r2*3.14159/180)-vz*sin(0.2*r2*3.14159/180);
  wz = -(vy*sin(0.2*r2*3.14159/180)+vz*cos(0.2*r2*3.14159/180));

  *mx = wx; *my = wy; *mz = wz;
}




double getStereographicVolume( vec3 a )
{
	double d = 1.0 + a.length2();
	return ( d*d ) / 8.0;
}



double cubeRoot( double a )
{
	return exp( log(a) / 3.0 );
}



void drawSchlegalThickLine( vec4 a, vec4 b )
{
	for( int i=0; i<=100; i++ )
	{
		vec3 p = a.interpolate( b, i*0.01 ).normalise().stereographicProjection();
		double v = getStereographicVolume( p );
		double l = cubeRoot( v ) * 0.03;
		
		Cube( p, l, Colour( 0.3, 0.6, 0.9 ) );
	}
}

void drawSchlegalPoint( vec4 a )
{
	vec3 p = a.normalise().stereographicProjection();
	double v = getStereographicVolume( p );
	double l = cubeRoot( v ) * 0.2;
	
	Cube( p, l, Colour( 0.9, 0.6, 0.0 ) );
}



#define MAX_POINTS 1000
#define MAX_LINES  1000

int numPoints = 0;
int numLines = 0;

vec4 points[ MAX_POINTS ];
Pair<int> lines[ MAX_LINES ];




void drawSchlegelShape2()
{
	bool done[256] = {false};

	//  Draw points

	for( int i=0; i<16; i++ )
	{
		int i0 = (i&1) >> 0;
		int i1 = (i&2) >> 1;
		int i2 = (i&4) >> 2;
		int i3 = (i&8) >> 3;

		vec4 a = vec4( 2.0*i0-1.0, 2.0*i1-1.0, 2.0*i2-1.0, 2.0*i3-1.0 );
		drawSchlegalPoint( a );
	}

	//  Draw lines

	for( int j=0; j<16; j++ )
	{
		int j0 = (j&1) >> 0;
		int j1 = (j&2) >> 1;
		int j2 = (j&4) >> 2;
		int j3 = (j&8) >> 3;

		vec4 b = vec4( 2.0*j0-1.0, 2.0*j1-1.0, 2.0*j2-1.0, 2.0*j3-1.0 );

		for( int i=0; i<16; i++ )
		{
			int i0 = (i&1) >> 0;
			int i1 = (i&2) >> 1;
			int i2 = (i&4) >> 2;
			int i3 = (i&8) >> 3;
		
			vec4 a = vec4( 2.0*i0-1.0, 2.0*i1-1.0, 2.0*i2-1.0, 2.0*i3-1.0 );

			int k = i^j;

			if( !done[ (j<<4)+i ] )
			{
				if( k == 1 || k == 2 || k == 4 || k == 8 )
				{
					drawSchlegalThickLine( a, b );
				}

				done[ (j<<4)+i ] = done[ (i<<4)+j ] = true;
			}
		}
	}

}


void drawSchlegelShape( double r[6] )
{
	vec4 *tpoints = new vec4[ numPoints ];

	for( int i=0; i<numPoints; i++ )
	{
		tpoints[i] = points[i].rotate6( r );

		drawSchlegalPoint( tpoints[i] );
	}

	for( int i=0; i<numLines; i++ )
	{
		drawSchlegalThickLine( tpoints[ lines[i].a() ], tpoints[ lines[i].b() ] );
	}

	delete[] tpoints;
}



void defineSchlegelShape()
{
	bool done[256] = {false};

	//  Draw points

	for( int i=0; i<16; i++ )
	{
		int i0 = (i&1) >> 0;
		int i1 = (i&2) >> 1;
		int i2 = (i&4) >> 2;
		int i3 = (i&8) >> 3;

		points[ numPoints++ ] = vec4( 2.0*i0-1.0, 2.0*i1-1.0, 2.0*i2-1.0, 2.0*i3-1.0 );
	}

	//  Draw lines

	for( int j=0; j<16; j++ )
	{
		int j0 = (j&1) >> 0;
		int j1 = (j&2) >> 1;
		int j2 = (j&4) >> 2;
		int j3 = (j&8) >> 3;

		vec4 b = vec4( 2.0*j0-1.0, 2.0*j1-1.0, 2.0*j2-1.0, 2.0*j3-1.0 );

		for( int i=0; i<16; i++ )
		{
			int i0 = (i&1) >> 0;
			int i1 = (i&2) >> 1;
			int i2 = (i&4) >> 2;
			int i3 = (i&8) >> 3;
		
			vec4 a = vec4( 2.0*i0-1.0, 2.0*i1-1.0, 2.0*i2-1.0, 2.0*i3-1.0 );

			int k = i^j;

			if( !done[ (j<<4)+i ] )
			{
				if( k == 1 || k == 2 || k == 4 || k == 8 )
				{
					lines[ numLines++ ] = Pair<int>( i, j );
				}

				done[ (j<<4)+i ] = done[ (i<<4)+j ] = true;
			}
		}
	}

}





void Initialise()
{
  static bool already_called = false;

  if( already_called ) return;

  already_called = true;


  //- Create the shape

  defineSchlegelShape();

  //- Create the texture for the floor

  //  from nehe.06

  glGenTextures(1, &texture[0]);					// Create The Texture

	// Typical Texture Generation Using Data From The Bitmap

	glBindTexture(GL_TEXTURE_2D, texture[0]);
	
  unsigned char data[256*256*3];


  unsigned char c;

  int i=0,j=0;

  for( j=0; j<256; j++ ) for( i=0; i<256; i++ )
  {
    c = i^j;
    data[ (i+256*j)*3+0 ] = c;
    data[ (i+256*j)*3+1 ] = c;
    data[ (i+256*j)*3+2 ] = c;
  }

  glTexImage2D
  (
    GL_TEXTURE_2D,
    0,    //  LOD zero
    3,    //  3 components - red, green, blue
    256,  //  width
    256,  // height
    0,
    GL_RGB,
    GL_UNSIGNED_BYTE,
    data
  );




  //- global parameters for texturing

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );


	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations

}






void GameDraw()
{
  int i, j;

  int time = timeGetTime();
  double mx, my, mz;

  mx = 5.0*sin(time*3.14159/7516);
  my = 5.0*sin(time*3.14159/4351);
  mz = 5.0*sin(time*3.14159/6892);


  double r[6] =
  {
	  2 * time*3.14159 /  7233.0,
	  2 * time*3.14159 /  9215.0,
	  2 * time*3.14159 / 15245.0,
	  2 * time*3.14159 /  6347.0,
	  2 * time*3.14159 / 13746.0,
	  2 * time*3.14159 /  7843.0
  };



  //- Draw the thing below the floor
  
  glPushMatrix();
  glTranslatef( 0, -2, 0 );
//  drawSchlegelShape( r[6] );
  glPopMatrix();


  //- Draw floor (semi-transparent to simulate reflection)

  glEnable(GL_BLEND);

	  glEnable(GL_TEXTURE_2D);							// Enable Texture Mapping ( NEW )

    // draw a textured floor
	  glBindTexture(GL_TEXTURE_2D, texture[0]);

    glColor4f( 0.3, 0.3, 0.3, 0.9 );

  //  time = 0;

	double distance_moved = 0;

    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	  glBegin(GL_QUADS);
		  // Front Face
		  glTexCoord2f(   0.0f + distance_moved*(20.0/100.0),   0.0f ); glVertex3f( -500.0f, 0.0f,  500.0f );
		  glTexCoord2f( 200.0f + distance_moved*(20.0/100.0),   0.0f ); glVertex3f(  500.0f, 0.0f,  500.0f );
		  glTexCoord2f( 200.0f + distance_moved*(20.0/100.0), 200.0f ); glVertex3f(  500.0f, 0.0f, -500.0f );
		  glTexCoord2f(   0.0f + distance_moved*(20.0/100.0), 200.0f ); glVertex3f( -500.0f, 0.0f, -500.0f );
	  glEnd();

	  glDisable(GL_TEXTURE_2D);							// Enable Texture Mapping ( NEW )

  glDisable(GL_BLEND);



  //- Draw the thing above the floor
  
  glPushMatrix();
  glTranslatef( 5, 2, 0 );
  drawSchlegelShape( r );
  glPopMatrix();



  //- Draw a non animated thing
  
  glPushMatrix();
  glTranslatef( -5, 2, 0 );
  drawSchlegelShape2();
  glPopMatrix();
}





void GameMain()
{
  Initialise();

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glTranslatef(0.f, 0.f, -15.f);

	glRotatef(-r2*0.2, 1.0, 0.0, 0.0);
	glRotatef(-r1*0.2, 0.0, 1.0, 0.0);

	glTranslatef(0.f, -2.f, 0.f);

	GameDraw();
	SwapBuffers (gl_dc);
}