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);
}