test.cpp
C++ source for Reflective sphere with polygon rendering, 1434 lines. Raw file
#define WIN32_LEAN_AND_MEAN
/*
*/
#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];
#define DEFAULT_SUBDIVIDE_LEVEL 2
#define DEFAULT_REFLECTION_ITERATIONS 10
//---- 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]; }
Colour darker( double v = 0.8 )
{
return Colour( c[0]*v, c[1]*v, c[2]*v, c[3] );
}
Colour lighter( double v = 0.8 )
{
return Colour( 1.0*(1.0-v)+c[0]*v, 1.0*(1.0-v)+c[1]*v, 1.0*(1.0-v)+c[2]*v, c[3] );
}
Colour interpolate( Colour col, double v = 0.5 )
{
return Colour
(
c[0]*v+col.c[0]*(1.0-v),
c[1]*v+col.c[1]*(1.0-v),
c[2]*v+col.c[2]*(1.0-v),
c[3]*v+col.c[3]*(1.0-v)
);
}
};
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() );
}
double dot( vec3 a )
{
return p[0]*a.p[0] + p[1]*a.p[1] + p[2]*a.p[2];
}
vec3 cross( vec3 a )
{
return vec3
(
p[1]*a.p[2] - p[2]*a.p[1],
p[2]*a.p[0] - p[0]*a.p[2],
p[0]*a.p[1] - p[1]*a.p[0]
);
}
vec3 operator * ( vec3 a )
{
return cross( a );
}
vec3 add( vec3 a )
{
return vec3
(
p[0] + a.p[0],
p[1] + a.p[1],
p[2] + a.p[2]
);
}
vec3 operator + ( vec3 a )
{
return add( a );
}
vec3 sub( vec3 a )
{
return vec3
(
p[0] - a.p[0],
p[1] - a.p[1],
p[2] - a.p[2]
);
}
vec3 operator - ( vec3 a )
{
return sub( a );
}
vec3 scale( double d )
{
return vec3( p[0]*d, p[1]*d, p[2]*d );
}
vec3 operator * ( double d )
{
return scale( d );
}
vec3 operator / ( double d )
{
return scale( 1.0 / d );
}
vec3 normalise()
{
double l = length();
return l > 0 ? scale( 1.0 / l ) : vec3();
}
vec3 interpolate( vec3 b, double d )
{
return vec3
(
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
);
}
vec3 rotate( int axis1, int axis2, double r )
{
vec3 a = *this;
if( axis1 >= 0 && axis1 < 3 && axis2 >= 0 && axis2 < 3 )
{
a.p[ axis1 ] = p[ axis1 ] * sin(r) + p[ axis2 ] * cos(r);
a.p[ axis2 ] = p[ axis1 ] * cos(r) - p[ axis2 ] * sin(r);
}
return a;
}
};
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]; }
double length2()
{
return p[0]*p[0] + p[1]*p[1] + p[2]*p[2] + p[3]*p[3];
}
double length()
{
return sqrt( length2() );
}
double dot( vec4 a )
{
return p[0]*a.p[0] + p[1]*a.p[1] + p[2]*a.p[2] + p[3]*a.p[3];
}
vec4 add( vec4 a )
{
return vec4
(
p[0]+a.p[0],
p[1]+a.p[1],
p[2]+a.p[2],
p[3]+a.p[3]
);
}
vec4 operator + ( vec4 a )
{
return add( a );
}
vec4 sub( vec4 a )
{
return vec4
(
p[0] - a.p[0],
p[1] - a.p[1],
p[2] - a.p[2],
p[3] - a.p[3]
);
}
vec4 operator - ( vec4 a )
{
return sub( a );
}
vec4 scale( double d )
{
return vec4( p[0]*d, p[1]*d, p[2]*d, p[3]*d );
}
vec4 operator * ( double d )
{
return scale( d );
}
vec4 operator / ( double d )
{
return scale( 1.0 / d );
}
vec4 normalise()
{
double l = length();
return l > 0 ? scale( 1.0 / l ) : vec4();
}
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] );
}
};
vec3 viewPoint;
vec3 sphereOrigin( 0, 4, 0 );
double sphereRadius = 2.0;
class Plane3
{
private:
vec3 point, normal;
public:
Plane3( double dist, vec3 normal )
: point( normal*dist ), normal( normal )
{}
Plane3( vec3 point, vec3 normal )
: point( point ), normal( normal )
{}
Plane3( vec3 p1, vec3 p2, vec3 p3 )
: point( p1 ), normal( p2 * p3 )
{}
};
double sphere_x[16][17];
double sphere_y[16][17];
double sphere_z[16][17];
bool sphereDone = false;
void CreateSphere()
{
int i, j;
double x, y, z;
if( !sphereDone)
{
double sr = 1;
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] = nx;
sphere_y[j][i] = ny;
sphere_z[j][i] = nz;
}
sphereDone = true;
}
}
void Sphere(double sx, double sy, double sz, double sr, bool checks = true )
{
CreateSphere();
int i, j;
double r, g, b;
int ii, jj;
for(j=0; j<16; j++) for(i=0; i<16; i++) {
ii = (i+1);
jj = (j+1)&15;
if( checks )
{
if(((i^j)&1) == 0) {
r = 1.0; g = 1.0; b = 1.0;
glColor4f(r, g, b, 0.3 );
} else {
r = 1.0; g = 0.0; b = 0.0;
glColor4f(r, g, b, 0.3 );
}
}
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(sx+sphere_x[jj][ii]*sr, sy+sphere_y[jj][ii]*sr, sz+sphere_z[jj][ii]*sr);
glVertex3f(sx+sphere_x[ j][ii]*sr, sy+sphere_y[ j][ii]*sr, sz+sphere_z[ j][ii]*sr);
glVertex3f(sx+sphere_x[jj][ i]*sr, sy+sphere_y[jj][ i]*sr, sz+sphere_z[jj][ i]*sr);
glVertex3f(sx+sphere_x[ j][ i]*sr, sy+sphere_y[ j][ i]*sr, sz+sphere_z[ j][ i]*sr);
glEnd();
}
}
void Sphere( vec3 c, double r )
{
Sphere( c.x(), c.y(), c.z(), r );
}
vec3 SpherePoint( vec3 c, double r, int i, int j )
{
return vec3( c.x()+r*sphere_x[j][i], c.y()+r*sphere_y[j][i], c.z()+r*sphere_z[j][i] );
}
vec3 SphereNormal( int i, int j )
{
return vec3( sphere_x[j][i], sphere_y[j][i], sphere_z[j][i] ) * -1;
}
bool ReflectFloor( vec3 c, double r, vec3 n, vec3 &q, vec3 &rq )
{
vec3 p = c + n * r;
vec3 a = (p-viewPoint).normalise();
vec3 rv = (a - n*a.dot(n)*2.0 );
if( rv.y() >= 0 ) return false;
double t = -p.y() / rv.y();
q = p + rv * t;
rq = p + a * (q-p).length();
return true;
}
void glVertex( vec3 p )
{
glVertex3f( p.x(), p.y(), p.z() );
}
void SphereQuadSubdivide( vec3 c, double r, vec3 n1, vec3 n2, vec3 n3, vec3 n4, int level=2 )
{
vec3 q1, q2, q3, q4;
vec3 r1, r2, r3, r4;
bool ok1 = ReflectFloor( c, r, n1, q1, r1 );
bool ok2 = ReflectFloor( c, r, n2, q2, r2 );
bool ok3 = ReflectFloor( c, r, n3, q3, r3 );
bool ok4 = ReflectFloor( c, r, n4, q4, r4 );
if( ok1 && ok2 && ok3 && ok4 && level == 0 )
{
glBegin(GL_QUADS);
glTexCoord2f( q1.x()*0.1, q1.z()*0.1 ); glVertex( r1 );
glTexCoord2f( q2.x()*0.1, q2.z()*0.1 ); glVertex( r2 );
glTexCoord2f( q3.x()*0.1, q3.z()*0.1 ); glVertex( r3 );
glTexCoord2f( q4.x()*0.1, q4.z()*0.1 ); glVertex( r4 );
glEnd();
}
else if( (ok1 || ok2 || ok3 || ok4) && level > 0 )
{
vec3 n12 = ((n1+n2)*0.5).normalise();
vec3 n23 = ((n2+n3)*0.5).normalise();
vec3 n34 = ((n3+n4)*0.5).normalise();
vec3 n41 = ((n4+n1)*0.5).normalise();
vec3 nm = ((n1+n3)*0.5).normalise();
SphereQuadSubdivide( c, r, n1, n12, nm, n41, level-1 );
SphereQuadSubdivide( c, r, n12, n2, n23, nm, level-1 );
SphereQuadSubdivide( c, r, nm, n23, n3, n34, level-1 );
SphereQuadSubdivide( c, r, n41, nm, n34, n4, level-1 );
}
}
void SphereFloorReflection( vec3 c, double r )
{
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture[0] );
glColor4f( 1, 1, 1, 1 );
for( int j=0; j<16; j++ ) for( int i=0; i<16; i++ )
{
int ii = (i+1);
int jj = (j+1)&15;
vec3 n1 = SphereNormal( i, j );
vec3 n2 = SphereNormal( ii, j );
vec3 n3 = SphereNormal( ii, jj );
vec3 n4 = SphereNormal( i, jj );
SphereQuadSubdivide( c, r, n1, n2, n3, n4 );
}
glDisable( GL_TEXTURE_2D );
}
//---- getViewPoint
vec3 getViewPoint()
{
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));
return vec3( vx, vy+4.0, 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;
}
//---- NEAREST POINT
// Given a line starting at a and going to b, finds the nearest the line goes to point p
double getPointNearestDistance( vec3 a, vec3 b, vec3 p )
{
return ( (b-a) * (a-p) ).length() / (b-a).length();
}
vec3 getNearestPointOnLine( vec3 a, vec3 b, vec3 p )
{
vec3 d = b-a;
double t = d.dot( p-a ) / d.length2();
return a + d * t;
}
//---- REFLECTION
// o = view point
// c = centre of sphere
// r = radius of sphere
// p = position of point to reflect
// Returns true if there is a reflected point
bool reflectedPointExists( vec3 o, vec3 c, double r, vec3 p )
{
return (p-c).length2() >= r*r && ( getPointNearestDistance( o, p, c ) >= r || (p-o).length2() < (c-o).length2() );
}
// Returns the reflected point
vec3 getReflectedPointOnSphere( vec3 o, vec3 c, double r, vec3 p )
{
// s is the interpolated point
vec3 s0 = o;
vec3 s1 = getNearestPointOnLine( o, p, c );
int count = DEFAULT_REFLECTION_ITERATIONS;
while( true )
{
// Test point
vec3 s = (s0+s1) * 0.5;
// Direction from centre of sphere
vec3 n = (s-c).normalise();
// Map to surface of sphere
vec3 q = c + n * r;
// Get reflected p
vec3 a = q-o;
vec3 rv = (a - n*a.dot(n)*2.0 ).normalise(); // reflection vector from q
vec3 pv = (p-q).normalise(); // vector from q to p
double arv = a.dot( rv );
double apv = a.dot( pv );
count --;
if( arv == apv || count <= 0 )
{
return q;
}
else if( arv > apv )
{
s1 = s;
}
else
{
s0 = s;
}
}
}
vec3 getReflectedPoint( vec3 o, vec3 c, double r, vec3 p )
{
vec3 q = getReflectedPointOnSphere( o, c, r, p );
vec3 n = (q-c).normalise();
vec3 a = (q-o).normalise();
return q + a * (q-p).length();
}
//---- Triangle
void Triangle( vec3 a, vec3 b, vec3 c )
{
glBegin(GL_TRIANGLE_FAN);
glVertex3f( a.x(), a.y(), a.z() );
glVertex3f( b.x(), b.y(), b.z() );
glVertex3f( c.x(), c.y(), c.z() );
glEnd();
}
void ReflectedTriangle( vec3 a, vec3 b, vec3 c )
{
if( ! reflectedPointExists( viewPoint, sphereOrigin, sphereRadius, a ) ) return;
if( ! reflectedPointExists( viewPoint, sphereOrigin, sphereRadius, b ) ) return;
if( ! reflectedPointExists( viewPoint, sphereOrigin, sphereRadius, c ) ) return;
Triangle
(
getReflectedPoint( viewPoint, sphereOrigin, sphereRadius, a ),
getReflectedPoint( viewPoint, sphereOrigin, sphereRadius, b ),
getReflectedPoint( viewPoint, sphereOrigin, sphereRadius, c )
);
}
//---- ReflectedQuad
void ReflectedQuad( vec3 a, vec3 b, vec3 c, vec3 d )
{
ReflectedTriangle( a, b, c );
ReflectedTriangle( c, d, a );
}
//---- SubdividedReflectedQuad
void SubdividedReflectedQuad_Recurse( vec3 a, vec3 b, vec3 c, vec3 d, int level = DEFAULT_SUBDIVIDE_LEVEL )
{
if( level > 0 )
{
vec3 ab = (a+b) * 0.5;
vec3 bc = (b+c) * 0.5;
vec3 cd = (c+d) * 0.5;
vec3 da = (d+a) * 0.5;
vec3 m = (a+c) * 0.5;
SubdividedReflectedQuad_Recurse( a, ab, m, da, level-1 );
SubdividedReflectedQuad_Recurse( ab, b, bc, m, level-1 );
SubdividedReflectedQuad_Recurse( m, bc, c, cd, level-1 );
SubdividedReflectedQuad_Recurse( da, m, cd, d, level-1 );
}
else
{
ReflectedQuad( a, b, c, d );
}
}
void SubdividedReflectedQuad( vec3 a, vec3 b, vec3 c, vec3 d, Colour col, int level = DEFAULT_SUBDIVIDE_LEVEL )
{
glColor3f( col.r(), col.g(), col.b() );
SubdividedReflectedQuad_Recurse( a, b, c, d, level );
}
//---- ReflectedCube
void ReflectedCube( vec3 a, vec3 b, Colour col )
{
double x1 = b.x();
double y1 = b.y();
double z1 = b.z();
double x2 = a.x();
double y2 = a.y();
double z2 = a.z();
SubdividedReflectedQuad
(
vec3(x1, y1, z1),
vec3(x1, y1, z2),
vec3(x2, y1, z2),
vec3(x2, y1, z1),
col.lighter()
);
SubdividedReflectedQuad
(
vec3(x2, y2, z1),
vec3(x2, y2, z2),
vec3(x1, y2, z2),
vec3(x1, y2, z1),
col.lighter()
);
SubdividedReflectedQuad
(
vec3(x1, y2, z1),
vec3(x1, y2, z2),
vec3(x1, y1, z2),
vec3(x1, y1, z1),
col
);
SubdividedReflectedQuad
(
vec3(x2, y1, z1),
vec3(x2, y1, z2),
vec3(x2, y2, z2),
vec3(x2, y2, z1),
col
);
SubdividedReflectedQuad
(
vec3(x2, y1, z1),
vec3(x2, y2, z1),
vec3(x1, y2, z1),
vec3(x1, y1, z1),
col.darker()
);
SubdividedReflectedQuad
(
vec3(x1, y1, z2),
vec3(x1, y2, z2),
vec3(x2, y2, z2),
vec3(x2, y1, z2),
col.darker()
);
}
void ReflectedCube( vec3 c, double r, Colour col )
{
ReflectedCube( c - vec3(r,r,r), c + vec3(r,r,r), col );
}
void ReflectedSphere(double sx, double sy, double sz, double sr)
{
CreateSphere();
int i, j;
double r, g, b;
int ii, jj;
for(j=0; j<16; j++) for(i=0; i<16; i++) {
ii = (i+1);
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;
}
glColor4f(r, g, b, 1.0 );
ReflectedQuad
(
vec3(sx+sphere_x[ j][ii]*sr, sy+sphere_y[ j][ii]*sr, sz+sphere_z[ j][ii]*sr),
vec3(sx+sphere_x[jj][ii]*sr, sy+sphere_y[jj][ii]*sr, sz+sphere_z[jj][ii]*sr),
vec3(sx+sphere_x[jj][ i]*sr, sy+sphere_y[jj][ i]*sr, sz+sphere_z[jj][ i]*sr),
vec3(sx+sphere_x[ j][ i]*sr, sy+sphere_y[ j][ i]*sr, sz+sphere_z[ j][ i]*sr)
);
}
}
//---- Cube
void Cube(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2, GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
glColor4f(r/0.8, g/0.8, b/0.8,a);
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();
glColor4f(r, g, b,a);
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();
glColor4f(r*0.80, g*0.80, b*0.80,a);
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(), col.a()
);
}
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
);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
//- 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
//- Fog
GLfloat fogColor[4] = {0,0,0,1.0};
glFogi(GL_FOG_MODE, GL_LINEAR); // Fog Mode
glFogfv(GL_FOG_COLOR, fogColor); // Set Fog Color
glFogf(GL_FOG_DENSITY, 0.35f); // How Dense Will The Fog Be
glHint(GL_FOG_HINT, GL_DONT_CARE); // Fog Hint Value
glFogf(GL_FOG_START, 25.0f); // Fog Start Depth
glFogf(GL_FOG_END, 50.0f); // Fog End Depth
glEnable(GL_FOG); // Enables GL_FOG
//- Light
/*
GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 0.1f };
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 0.1f };
GLfloat LightPosition[]= { 5.0f, 10.0f, -2.0f, 1.0f };
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
glEnable(GL_LIGHT1);
glEnable( GL_LIGHTING );
*/
}
void ReflectedFloor()
{
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;
for( int i=9; i<12; i++ )
{
for( int j=9; j<12; j++ )
{
vec3 p1 = vec3( -500 + i*50.0, 0, -500 + j*50.0 );
vec3 p2 = vec3( -450 + i*50.0, 0, -500 + j*50.0 );
vec3 p3 = vec3( -450 + i*50.0, 0, -450 + j*50.0 );
vec3 p4 = vec3( -500 + i*50.0, 0, -450 + j*50.0 );
if( ! reflectedPointExists( viewPoint, sphereOrigin, sphereRadius, p1 ) ) continue;
if( ! reflectedPointExists( viewPoint, sphereOrigin, sphereRadius, p2 ) ) continue;
if( ! reflectedPointExists( viewPoint, sphereOrigin, sphereRadius, p3 ) ) continue;
if( ! reflectedPointExists( viewPoint, sphereOrigin, sphereRadius, p4 ) ) continue;
p1 = getReflectedPoint( viewPoint, sphereOrigin, sphereRadius, p1 );
p2 = getReflectedPoint( viewPoint, sphereOrigin, sphereRadius, p2 );
p3 = getReflectedPoint( viewPoint, sphereOrigin, sphereRadius, p3 );
p4 = getReflectedPoint( viewPoint, sphereOrigin, sphereRadius, p4 );
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f( 10.0f +i*10.0, 0.0f + j*10.0 ); glVertex3f( p3.x(), p3.y(), p3.z() );
glTexCoord2f( 10.0f +i*10.0, 10.0f + j*10.0 ); glVertex3f( p2.x(), p2.y(), p2.z() );
glTexCoord2f( 0.0f +i*10.0, 10.0f + j*10.0 ); glVertex3f( p1.x(), p1.y(), p1.z() );
glTexCoord2f( 0.0f +i*10.0, 0.0f + j*10.0 ); glVertex3f( p4.x(), p4.y(), p4.z() );
glEnd();
}
}
glDisable(GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
}
void GameDraw()
{
int i, j;
int time = timeGetTime();
double mx, my, mz;
mx = 4.3*sin(time*3.14159/7516);
my = 4.3*sin(time*3.14159/4351);
mz = 4.3*sin(time*3.14159/6892);
sphereOrigin = vec3( 0, 4 + 1.5*sin( 3.14159*time/6000 ), 0 );
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
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
};
// mx = 4;
// my = 3;
// mz = 2;
ReflectedCube( vec3( -4, 4+mx, mz ), 1, Colour( 0.8, 0.0, 0.0 ) );
ReflectedCube( vec3( -4, 5.5+mx, mz ), 0.5, Colour( 0.3, 0.6, 0.9 ) );
ReflectedCube( vec3( 4, 4+my, mx ), 1.5, Colour( 0.0, 0.6, 0.0 ) );
ReflectedSphere( mx, 4+mz, 5, 1.5 );
// Not working yet...
//ReflectedFloor();
SphereFloorReflection( sphereOrigin, sphereRadius );
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glColor4f( 1, 1, 1, 0.25 );
Sphere( sphereOrigin.x(), sphereOrigin.y(), sphereOrigin.z(), sphereRadius, false );
glDisable(GL_BLEND);
Cube( vec3( -4, 4+mx, mz ), 1, Colour( 0.8, 0.0, 0.0 ) );
Cube( vec3( -4, 5.5+mx, mz ), 0.5, Colour( 0.3, 0.6, 0.9 ) );
Cube( vec3( 4, 4+my, mx ), 1.5, Colour( 0.0, 0.6, 0.0 ) );
Sphere( mx, 4+mz, 5, 1.5 );
/*
vec3 pos = vec3( 5, 2+my, mx );
if( reflectedPointExists( viewPoint, sphereOrigin, sphereRadius, pos ) )
{
vec3 pos2 = getReflectedPointOnSphere( viewPoint, sphereOrigin, sphereRadius, pos );
Cube( pos2, 0.1, Colour( 0.8, 0, 0 ) );
}
glEnable(GL_BLEND);
Cube( pos, 1, Colour( 0.8, 0, 0, 0.4 ) );
glDisable(GL_BLEND);
*/
//- Draw floor
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
// draw a textured floor
glBindTexture(GL_TEXTURE_2D, texture[0]);
glColor4f( 0.7, 0.7, 0.7, 1.0 );
// time = 0;
double distance_moved = 0;
glBegin(GL_QUADS);
// Front Face
glTexCoord2f( -50.0f, -50.0f ); glVertex3f( -500.0f, 0.0f, -500.0f );
glTexCoord2f( 50.0f, -50.0f ); glVertex3f( 500.0f, 0.0f, -500.0f );
glTexCoord2f( 50.0f, 50.0f ); glVertex3f( 500.0f, 0.0f, 500.0f );
glTexCoord2f( -50.0f, 50.0f ); glVertex3f( -500.0f, 0.0f, 500.0f );
glEnd();
glDisable(GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
}
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, -4.f, 0.f);
viewPoint = getViewPoint();
GameDraw();
SwapBuffers (gl_dc);
}