test.cpp
C++ source for Blobs2, 755 lines. Raw file
#define WIN32_LEAN_AND_MEAN
#include <math.h>
#include "qe_ogl.h"
#include "Pattern.h"
#include "mmsystem.h"
void oglcube(double x1, double y1, double z1, double x2, double y2, double z2, double r, double g, double b)
{
/*
double t = 7 + 2*sin(GetTickCount()*3.14159/16400);
double dd = sqrt(x1*x1+y1*y1+z1*z1);
double d = sin(t*dd);
// if(d < 0) return;
d += 1.3;
r *= d; g *= d; b *= d;
*/
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();
}
//---- CLASS DECLARATIONS ----------------------------------------------------//
class IsoObjectFunction;
class IsoObjectDraw;
class IsoObject;
class Stack;
class Queue;
class Cache;
//---- ISOOBJECTSIZE ---------------------------------------------------------//
class IsoObjectSize
{
protected:
//---- Render data
double size_x, size_y, size_z; // Size of bounding box
double scale; // Size of cubes
double start_x, start_y, start_z;
int count_x, count_y, count_z;
public:
//---- IsoObjectSize
IsoObjectSize()
{
SetSize(20, 20, 20);
SetScale(1);
}
//---- SetSize(x, y, z) - sets the dimensions of the bounding box
void SetSize(double x, double y, double z)
{
size_x = x; size_y = y; size_z = z;
count_x = size_x / scale;
count_y = size_y / scale;
count_z = size_z / scale;
start_x = -0.5 * count_x * scale;
start_y = -0.5 * count_y * scale;
start_z = -0.5 * count_z * scale;
}
//---- SetScale(scale) - sets the size of the cubes to divide the object into to render
void SetScale(double s)
{
scale = s;
}
};
//---- ISOOBJECTFUNCTION -----------------------------------------------------//
class IsoObjectFunction : IsoObjectSize
{
private:
Cache *fcache;
public:
double f_size;
//---- IsoObjectFunction
IsoObjectFunction()
{
fcache = new Cache();
}
protected:
//---- f(x, y, z) - isosurface function
double f(double x, double y, double z)
{
return x*x + y*y + z*z - f_size*f_size;
}
//---- IsSurface(x, y, z) - returns whether this cube contains a portion of the surface of the object
bool IsSurface(double x, double y, double z)
{
bool p0 = f(x , y , z ) < 0;
bool p1 = f(x+scale, y , z ) < 0;
bool p2 = f(x , y+scale, z ) < 0;
bool p3 = f(x+scale, y+scale, z ) < 0;
bool p4 = f(x , y , z+scale) < 0;
bool p5 = f(x+scale, y , z+scale) < 0;
bool p6 = f(x , y+scale, z+scale) < 0;
bool p7 = f(x+scale, y+scale, z+scale) < 0;
return !(p0 == p1 && p0 == p2 && p0 == p3 && p0 == p4 && p0 == p5 && p0 == p6 && p0 == p7);
}
};
//---- ISOOBJECTDRAW ---------------------------------------------------------//
class IsoObjectDraw : IsoObjectFunction
{
private:
//---- Stepping cubes algo data
IsoObject *o;
Cache fcache;
Queue *q[3];
Queue *drawqueue;
public:
//---- IsoObjectDraw(iso)
IsoObjectDraw(IsoObject *iso)
{
o = iso;
for(int i=0; i<3; i++) q[i] = new Queue();
drawqueue = new Queue();
}
private:
void queuecube(double x, double y, double z)
{
if(q[0]->Contains(x, y, z) || q[1]->Contains(x, y, z) || q[2]->Contains(x, y, z)) return;
if(!IsSurface(x, y, z)) return;
drawqueue.Push(x, y, z);
q[1]->Push(x, y, z);
}
protected:
//---- DrawSetup()
void DrawSetup()
{
int i;
// Clear queues
for(i=0; i<3; i++) q[i]->Init();
drawqueue.Init();
// Start from middle of blobs and find
double x = 0, y = 0, z = 0;
while(!IsSurface(x, y, z) && y < 20) y++;
if(y >= 80) return;
// Enqueue this item
q[0]->Push(x, y, z);
drawqueue.Push(x, y, z);
}
//---- DrawIterate()
void DrawIterate()
{
int x, y, z;
if(!q[0]->IsEmpty())
{
// Add all neighboring edge cubes to stack 1
q[1]->Init();
q[0]->First();
while(q[0]->Next(&x, &y, &z))
{
// Check all the cubes around this one
int i, j, k;
for(i=-1; i<=1; i++) for(j=-1; j<=1; j++) for(k=-1; k<=1; k++) if(i+j+k == 1 || i+j+k == -1)
queuecube(x+i, y+j, z+k);
}
// Shuffle queues so that q[0] is the neighbour
Queue *qq = q[0];
q[0] = q[1];
q[1] = q[2];
q[2] = qq;
// If we've collected the maximum no of cubes then stop
if(drawqueue.Num() >= maxcubes) q[0]->Init();
}
return !q[0]->IsEmpty();
}
//---- DrawRender()
void DrawRender()
{
int i;
int x, y, z;
//- Draw cubes
drawqueue.First();
while(drawqueue.Next(&x, &y, &z))
{
oglcube(x*scale, y*scale, z*scale, (x+1)*scale, (y+1)*scale, (z+1)*scale, 0.8, 0.4, 0.0);
}
}
//---- Draw
void Draw()
{
DrawSetup();
while(DrawIterate());
DrawRender();
}
};
//---- ISOOBJECT -------------------------------------------------------------//
class IsoObject : IsoObjectDraw
{
public:
//---- IsoObject() - sets default values
IsoObject()
{
}
//---- Draw() - Draws the object in the current OpenGL context
void Draw()
{
int i, j, k;
//- Number of cubes we can fit into each dimension
int cx = size_x / scale;
int cy = size_y / scale;
int cz = size_z / scale;
//- Initial point
double px = -0.5 * cx * scale;
double py = -0.5 * cy * scale;
double pz = -0.5 * cz * scale;
//- Vary object
f_size = 10.0 + 6.0*sin(GetTickCount()*0.0003);
//- TEMP: Draw bounding box
// oglcube(px, py, pz, -px, -py, -pz, 0.4, 0.6, 0.8);
//- Fill with cubes to show boundary
double s = 0.0 * scale;
double x, y, z;
z = pz;
for(k=0; k<cz; k++)
{
y = py;
for(j=0; j<cy; j++)
{
x = px;
for(i=0; i<cx; i++)
{
if(IsSurface(x, y, z)) oglcube(x+s, y+s, z+s, x+scale-s, y+scale-s, z+scale-s, (1.0*i)/cx, (1.0*j)/cy, (1.0*k)/cz);
x += scale;
}
y += scale;
}
z += scale;
}
}
};
//----------------------------------------------------------------------------//
//---- QUEUE
class Queue
{
#define QUEUE_SIZE 10000
public:
struct {
int x, y, z;
} queue[QUEUE_SIZE];
int queue_start;
int queue_num;
int queue_next;
Queue()
{
Init();
}
void Init()
{
queue_start = 0;
queue_num = 0;
}
bool Push(int x, int y, int z)
{
if(queue_num < QUEUE_SIZE)
{
int index = (queue_start + queue_num) % QUEUE_SIZE;
queue[index].x = x;
queue[index].y = y;
queue[index].z = z;
queue_num ++;
return true;
}
return false;
}
bool Pop(int *x, int *y, int *z)
{
if(queue_num > 0)
{
queue_num --;
int index = (queue_start + queue_num) % QUEUE_SIZE;
*x = queue[index].x;
*y = queue[index].y;
*z = queue[index].z;
return true;
}
return false;
}
bool Contains(int x, int y, int z)
{
for(int i=0; i<queue_num; i++)
{
int index = (queue_start + i) % QUEUE_SIZE;
if(queue[index].x == x && queue[index].y == y && queue[index].z == z) return true;
}
return false;
}
bool IsEmpty()
{
return queue_num == 0;
}
int Num()
{
return queue_num;
}
void First()
{
queue_next = 0;
}
bool Next(int *x, int *y, int *z)
{
if(queue_next >= queue_num) return false;
int index = (queue_start + queue_next) % QUEUE_SIZE;
*x = queue[index].x;
*y = queue[index].y;
*z = queue[index].z;
queue_next ++;
return true;
}
};
//---- STACK
class Stack
{
#define STACK_SIZE 10000
public:
struct {
int x, y, z;
} stack[STACK_SIZE];
int stack_num;
int stack_next;
Stack()
{
Init();
}
void Init()
{
stack_num = 0;
stack_next = 0;
}
bool Push(int x, int y, int z)
{
if(stack_num < STACK_SIZE)
{
stack[stack_num].x = x;
stack[stack_num].y = y;
stack[stack_num].z = z;
stack_num ++;
return true;
}
return false;
}
bool Pop(int *x, int *y, int *z)
{
if(stack_num > 0)
{
stack_num --;
*x = stack[stack_num].x;
*y = stack[stack_num].y;
*z = stack[stack_num].z;
return true;
}
return false;
}
bool Contains(int x, int y, int z)
{
for(int i=0; i<stack_num; i++)
{
if(stack[i].x == x && stack[i].y == y && stack[i].z == z) return true;
}
return false;
}
bool IsEmpty()
{
return stack_num == 0;
}
int Num()
{
return stack_num;
}
void First()
{
stack_next = 0;
}
bool Next(int *x, int *y, int *z)
{
if(stack_next >= stack_num) return false;
*x = stack[stack_next].x;
*y = stack[stack_next].y;
*z = stack[stack_next].z;
stack_next ++;
return true;
}
};
//---- CACHE
class Cache
{
public:
#define CACHE_SIZE 10000
struct {
bool inuse;
int x, y, z;
double v;
} cache[CACHE_SIZE];
Cache()
{
Flush();
}
bool Flush()
{
int i;
for(i=0; i<CACHE_SIZE; i++) cache[i].inuse = false;
}
inline int Hash(int x, int y, int z)
{
return (x<<2)^(y<<5)^(z);//( ((5*x*x)^(7*y*y)^(3*z*z))+((z&0x07FC5BFB)*0x376F)+((y&0x0FCF77F7)*0x8721)+((x&0x0F559CFD)*0xFC7B) ) & 0x00FFFFFF;
}
bool Get(int x, int y, int z, double *v)
{
int h = Hash(x, y, z) % CACHE_SIZE;
if(cache[h].inuse && cache[h].x == x && cache[h].y == y && cache[h].z == z)
{
*v = cache[h].v;
return true;
}
return false;
}
void Set(int x, int y, int z, double v)
{
int h = Hash(x, y, z) % CACHE_SIZE;
cache[h].inuse = true;
cache[h].x = x;
cache[h].y = y;
cache[h].z = z;
cache[h].v = v;
}
};
//---- DATA
double r1=0, r2=0;
BOOL DrawMe = TRUE;
PATTERN_A *a1, *a2, *a3, *a4, *a5;
PATTERN_RGB *rgb1, *rgb2, *rgb3, *rgb4, *rgb5;
bool restart = true;
double bx[10] = {- 0, -15, 17, -15, -12, - 9, 15, 17, - 1, 13};
double by[10] = { 0, 11, - 2, 4, 1, 5, - 5, -12, -11, - 3};
double bz[10] = {- 0, 3, 9, 9, - 5, 11, - 3, - 2, 9, 13};
//---- STEPPING CUBES
double f(int x, int y, int z)
{
/*
double d = sqrt(x*x + y*y + z*z);
if(d < 0.1) d = 0.1;
return d - 20;
*/
int i;
double d, dd=0;
if(!fcache.Get(x, y, z, &dd))
{
for(i=0; i<10; i++)
{
d = sqrt((x-bx[i])*(x-bx[i]) + (y-by[i])*(y-by[i]) + (z-bz[i])*(z-bz[i]));
if(d < 0.1) d = 0.1;
d = 1.0/d;
dd += d;
}
fcache.Set(x, y, z, dd);
}
return dd - 0.65;
}
void cube(int x, int y, int z)
{
oglcube(x*scale, y*scale, z*scale, (x+1)*scale, (y+1)*scale, (z+1)*scale, 0.8, 0.4, 0.0);
}
void draw()
{
int i, j, k;
/*
static int p = 0;
p++;
int w = 20;
for(k = -w; k < w; k++)
for(j = -w; j < w; j++)
for(i = -w; i < w; i++)
{
// if( ((i+j+k+p)&31) < 1 ) cube(i, j, k);
double t = sin(i*3.14159/17+p*3.14159/31 + 0.12451) +
sin(j*3.14159/16+p*3.14159/54 + 1.89214) +
sin(k*3.14159/15+p*3.14159/47 + 1.00298);
if(t > 0 && t < 0.25) cube(i, j, k);
}
*/
drawsteppingcubes();
}
//---- MAIN
void Initialise()
{
for(int i=0; i<3; i++) q[i] = new Queue();
}
IsoObject iso1;
void GameDraw()
{
iso1.Draw();
}
void GameMain()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.f, 0.f, (-10.0 + 6.0*sin(GetTickCount()*0.0003))*2);
glRotatef(-r2*0.2, 1.0, 0.0, 0.0);
glRotatef(-r1*0.2, 0.0, 1.0, 0.0);
GameDraw();
SwapBuffers(gl_dc);
}