test.cpp
C++ source for City Block, 791 lines. Raw file
#define WIN32_LEAN_AND_MEAN
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include "qe_ogl.h"
bool drawBlack = false;
//---- ZSYSTEM TEST VERSION 0.1 ----------------------------------------------//
//---- ZSYSTEM TYPES ---------------------------------------------------------//
typedef struct _ZS_RAND {
unsigned int a, b, c, d;
} ZS_RAND;
//---- ZSYSTEM DATA ----------------------------------------------------------//
int zs_cubes = 0;
int zs_buildings = 0;
//---- ZSYSTEM FUNCTIONS -----------------------------------------------------//
//---- ZS_Rand_Create --------------------------------------------------------//
ZS_RAND *ZS_Rand_Create(int seed)
{
ZS_RAND *r = (ZS_RAND *)malloc(sizeof(ZS_RAND));
if(!r) return NULL;
r->a = seed + 0x87123631;
r->b = seed * 3;
r->c = seed + 0x72319631;
r->d = seed ^ 0x24121531;
return r;
}
//---- ZS_Rand_Delete --------------------------------------------------------//
void ZS_Rand_Delete(ZS_RAND *r)
{
if(!r) return;
free(r);
}
//---- ZS_Rand ---------------------------------------------------------------//
unsigned int ZS_Rand(ZS_RAND *r, unsigned int max)
{
r->d ^= (r->c<<9) + (r->a>>7) + (r->d&r->a);
r->a += r->b>>1;
r->b += r->c^0xF0F0A05;
r->c += r->d;
r->d += 0x35136613;
unsigned int v = ( (r->a*7 + r->c*6)^((r->b<<13)-(r->d>>3)) );
if(max == 0) return v;
return v % max;
}
//---- ZS_Rand_Tween ---------------------------------------------------------//
double ZS_Rand_Tween(ZS_RAND *r, double min, double max)
{
double t = min + ZS_Rand(r, 1000000)*0.000001*(max-min);
return t;
}
//---- ZSYSTEM OBJECT: CUBE --------------------------------------------------//
void Cube(double x1, double y1, double z1, double x2, double y2, double z2, double r, double g, double b)
{
zs_cubes ++;
/*
int rr, gg, bb;
rr = zs_cubes*787;
gg = (zs_cubes*17)^815;
bb = ((zs_cubes*91)|812)/3;
r = (rr%1000)*0.001;
g = (gg%1000)*0.001;
b = (bb%1000)*0.001;
*/
/*
double d;
d = 1.0-(0.0005*x1*0.0005*x1+0.0005*z1*0.0005*z1);
if(d < 0) return;
r *= d; g *= d; b *= d;
*/
if(!drawBlack) glColor3f(r, g, b); else glColor3f(0, 0, 0);
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();
if(!drawBlack) glColor3f(r*0.95, g*0.95, b*0.95); else glColor3f(0, 0, 0);
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();
if(!drawBlack) glColor3f(r*0.90, g*0.90, b*0.90); else glColor3f(0, 0, 0);
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 Cube2(double x1, double y1, double z1, double x2, double y2, double z2, double r, double g, double b)
{
int i, j;
for(j=-4; j<=4; j++)
for(i=-4; i<=4; i++)
Cube2(x1+i*500, y1, z1+j*500, x2+i*500, y2, z2+j*500, r, g, b);
}
//---- ZSYSTEM OBJECT: BUILDING ----------------------------------------------//
void Building(unsigned int seed, double x1, double z1, double x2, double z2, double y)
{
zs_buildings ++;
ZS_RAND *rand = ZS_Rand_Create(seed);
int i, j, ii, jj;
double x, z, w, h, d;
int r = ZS_Rand(rand, 100);
double lit = ZS_Rand_Tween(rand, 0.8, 1.0);
if((x2-x1) < 10 || (z2-z1) < 10) {
// Nothing - too small
} else if(r < 40) {
// Basic building
Cube(x1, y, z1, x2, y+ZS_Rand_Tween(rand, 10, 50), z2, 0.8*lit, 0.8*lit, 0.8*lit);
} else if(r < 60) {
// Building with array of blocks on top
h = ZS_Rand_Tween(rand, 20, 70);
Cube(x1, y, z1, x2, y+h, z2, 0.75, 0.75, 0.75);
ii = 1+ZS_Rand(rand, (int)((x2-x1)/3)-1);
jj = 1+ZS_Rand(rand, (int)((z2-z1)/3)-1);
w = (x2-x1)/ii;
d = (z2-z1)/jj;
for(j=0; j<jj; j++) {
for(i=0; i<ii; i++) {
if(ZS_Rand(rand, 100) < 95) Cube(x1+i*w+1, y+h, z1+j*d+1, x1+(i+1)*w-1, y+h+0.5, z1+(j+1)*d-1, 0.6*lit, 0.6*lit, 0.6*lit);
}
}
} else if(r < 90) {
// Building with smaller block on top
h = ZS_Rand_Tween(rand, 20, 70);
Cube(x1, y, z1, x2, y+h, z2, 0.65*lit, 0.65*lit, 0.65*lit);
w = ZS_Rand_Tween(rand, (x2-x1)/6, (x2-x1)/3);
d = ZS_Rand_Tween(rand, (z2-z1)/6, (z2-z1)/3);
if(d > w*1.5) d = w*1.5;
if(w > d*1.5) w = d*1.5;
Building(ZS_Rand(rand, 0), x1+w, z1+d, x2-w, z2-d, y+h);
} else {
// Building with array of long blocks
h = ZS_Rand_Tween(rand, 10, 40);
Cube(x1, y, z1, x2, y+h, z2, 0.8*lit, 0.8*lit, 0.8*lit);
if(x2-x1 > z2-z1) {
ii = ZS_Rand(rand, (int)((x2-x1)/3));
if(ii > 0) {
w = (x2-x1)/ii;
for(i=0; i<ii; i++) {
Cube(x1+i*w+1, y+h, z1+1, x1+(i+1)*w-1, y+h+1, z2-1, 0.7*lit, 0.7*lit, 0.7*lit);
}
}
} else {
ii = ZS_Rand(rand, (int)((z2-z1)/3));
if(ii > 0) {
d = (z2-z1)/ii;
for(i=0; i<ii; i++) {
Cube(x1+1, y+h, z1+i*d+1, x2-1, y+h+1, z1+(i+1)*d-1, 0.7*lit, 0.7*lit, 0.7*lit);
}
}
}
}
ZS_Rand_Delete(rand);
}
//---- ZSYSTEM OBJECT: BLOCK -------------------------------------------------//
void Block(unsigned int seed, double x1, double z1, double x2, double z2)
{
ZS_RAND *rand = ZS_Rand_Create(seed);
// Put base
Cube(x1+3, 0, z1+3, x2-3, 0.1, z2-3, 0.5, 0.5, 0.5);
// Put buildings
int r = ZS_Rand(rand, 100);
if(r < 10) {
// No buildings
Building(ZS_Rand(rand, 0), x1+8, z1+8, x2-8, z2-8, 0.1);
} else if(r < 40) {
// Symmetrical array of buildings
Building(ZS_Rand(rand, 0), x1+8, z1+8, (x2+x1)/2-4, z2-8, 0.1);
Building(ZS_Rand(rand, 0), (x2+x1)/2+4, z1+8, x2-8, z2-8, 0.1);
} else if(r < 80) {
// Randomly placed buildings
Building(ZS_Rand(rand, 0), x1+8, z1+8, x2-8, z2-8, 0.1);
} else {
// One big building
Building(ZS_Rand(rand, 0), x1+8, z1+8, x2-8, z2-8, 0.1);
}
ZS_Rand_Delete(rand);
}
//---- ZSYSTEM OBJECT: ROAD --------------------------------------------------//
void Road(unsigned int seed, double x1, double z1, double x2, double z2)
{
ZS_RAND *rand = ZS_Rand_Create(seed);
// Put base
// Put dashes
int i, ii;
double x, y, z;
if(x2-x1 > z2-z1) {
z=0.5*(z1+z2);
for(x=x1; x<x2-1; x+=2) {
Cube(x, 0, z-0.05, x+1, 0.01, z+0.05, 1, 1, 1);
}
for(z=z; z<z2; z+=0.4) {
Cube(x1, 0, z, x1+0.10, 0.01, z+0.2, 1, 1, 1);
Cube(x1+0.30, 0, z, x1+0.40, 0.01, z+0.2, 1, 1, 1);
}
} else {
x=0.5*(x1+x2);
for(z=z1; z<z2-1; z+=2) {
Cube(x-0.05, 0, z, x+0.05, 0.01, z+1, 1, 1, 1);
}
for(x=x; x<x2; x+=0.4) {
Cube(x, 0, z2-0.40, x+0.2, 0.01, z2-0.30, 1, 1, 1);
Cube(x, 0, z2-0.10, x+0.2, 0.01, z2-0.00, 1, 1, 1);
}
}
ZS_Rand_Delete(rand);
}
//---- ZSYSTEM OBJECT: SUBURB ------------------------------------------------//
void Suburb(unsigned int seed, double x1, double z1, double x2, double z2, int iter)
{
ZS_RAND *rand = ZS_Rand_Create(seed);
//- Check size
BOOL smallx, smallz, smallrand;
double x, z;
smallx = (x2-x1) < 70;
smallz = (z2-z1) < 70;
smallrand = (ZS_Rand(rand, 100) < 20 && x2-x1 < 100 && z2-z1 < 100) || iter > 10;
if(smallrand) {
Block(ZS_Rand(rand, 0), x1, z1, x2, z2);
} else if(smallx && smallz) {
Block(ZS_Rand(rand, 0), x1, z1, x2, z2);
} else if(smallx) {
z = ZS_Rand_Tween(rand, z1+23, z2-23);
Suburb(ZS_Rand(rand, 0), x1, z1, x2, z, iter+1);
Suburb(ZS_Rand(rand, 0), x1, z, x2, z2, iter+1);
// Road(ZS_Rand(rand, 0), x1+3, z-3, x2-3, z+3);
} else if(smallz) {
x = ZS_Rand_Tween(rand, x1+23, x2-23);
Suburb(ZS_Rand(rand, 0), x1, z1, x, z2, iter+1);
Suburb(ZS_Rand(rand, 0), x, z1, x2, z2, iter+1);
// Road(ZS_Rand(rand, 0), x-3, z1+3, x+3, z2-3);
} else {
x = ZS_Rand_Tween(rand, x1+23, x2-15);
z = ZS_Rand_Tween(rand, z1+23, z2-15);
Suburb(ZS_Rand(rand, 0), x1, z1, x, z, iter+1);
Suburb(ZS_Rand(rand, 0), x, z1, x2, z, iter+1);
Suburb(ZS_Rand(rand, 0), x1, z, x, z2, iter+1);
Suburb(ZS_Rand(rand, 0), x, z, x2, z2, iter+1);
// Road(ZS_Rand(rand, 0), x-3, z1+3, x+3, z-3);
// Road(ZS_Rand(rand, 0), x-3, z+3, x+3, z2-3);
// Road(ZS_Rand(rand, 0), x1+3, z-3, x-3, z+3);
// Road(ZS_Rand(rand, 0), x+3, z-3, x2-3, z+3);
Cube(x-1, 0, z-1, x+1, 0.01, z+1, 0.4, 0.4, 0.4);
}
ZS_Rand_Delete(rand);
}
//---- ZSYSTEM OBJECT: CITY --------------------------------------------------//
void City(unsigned int seed, double x1, double z1, double x2, double z2)
{
ZS_RAND *rand = ZS_Rand_Create(seed);
// Place floor poly
// Cube(x1, -1, z1, x2, 0, z2, 0.1, 0.1, 0.1);
// Divide into blocks
Suburb(ZS_Rand(rand, 0), x1, z1, x2, z2, 0);
ZS_Rand_Delete(rand);
}
//---- TERRAIN STUFF ---------------------------------------------------------//
bool terrain_startup = false;
//---- Terrain_Startup
void Terrain_Startup()
{
if(terrain_startup) return;
terrain_startup = true;
//- Do any startup stuff
}
//---- Terrain_PosRand
// Returns numbers distributed [0.0, 1.0) seeded by two floats
float Terrain_PosRand(float x, float z)
{
unsigned int a = x*984729;
unsigned int b = z*735161;
unsigned int r = (a^b)-(a*b) + ((a >> 10)&(b << 2)) - ((a << 2)|(b >> 9));
return (r%18378276)/18378276.0;
}
//---- Terrain_GetHeight
// Gets the height of the terrain at the given point
float Terrain_GetHeight(float x, float z)
{
float scale = 20;
float sx = scale*((int)(x/scale));
float sz = scale*((int)(z/scale));
float r00, r01, r10, r11;
int i;
//- Binary split in fractal terrain to find heights around wanted pos
r00 = Terrain_PosRand(sx, sz);
r01 = Terrain_PosRand(sx+scale, sz);
r10 = Terrain_PosRand(sx, sz+scale);
r11 = Terrain_PosRand(sx+scale, sz+scale);
float hscale = 1;
for(i=0; i<15; i++) {
scale *= 0.5;
//- If it's less than half way then bring the window back else move it forward
float nr00, nr01, nr10, nr11;
if(sx+scale > x) {
if(sz+scale > z) {
nr00 = r00;
nr01 = 0.5*(r00+r01) + hscale*Terrain_PosRand(sx+scale, sz);
nr10 = 0.5*(r00+r10) + hscale*Terrain_PosRand(sx, sz+scale);
nr11 = 0.5*(r00+r11) + hscale*Terrain_PosRand(sx+scale, sz+scale);
} else {
nr00 = 0.5*(r00+r10) + hscale*Terrain_PosRand(sx, sz+scale);
nr01 = 0.5*(r00+r11) + hscale*Terrain_PosRand(sx+scale, sz+scale);
nr10 = r10;
nr11 = 0.5*(r10+r11) + hscale*Terrain_PosRand(sx+scale, sz+scale*2);
sz += scale;
}
} else {
if(sz+scale > z) {
nr00 = 0.5*(r00+r01) + hscale*Terrain_PosRand(sx+scale, sz);
nr01 = r01;
nr10 = 0.5*(r00+r11) + hscale*Terrain_PosRand(sx+scale, sz+scale);
nr11 = 0.5*(r01+r11) + hscale*Terrain_PosRand(sx+scale*2, sz+scale);
sx += scale;
} else {
nr00 = 0.5*(r00+r11) + hscale*Terrain_PosRand(sx+scale, sz+scale);
nr01 = 0.5*(r01+r11) + hscale*Terrain_PosRand(sx+scale*2, sz+scale);
nr10 = 0.5*(r10+r11) + hscale*Terrain_PosRand(sx+scale, sz+scale*2);
nr11 = r11;
sx += scale; sz += scale;
}
}
r00 = nr00; r01 = nr01; r10 = nr10; r11 = nr11;
hscale *= 0.2;
}
//- TODO: Bilinear filter to get height
float r = r00;
//- Return height
return 10*r;
}
//---- Terrain_DrawSquare
void Terrain_DrawSquare(float x, float y, float z)
{
if(x < 0 || z < 0) return;
float h00 = Terrain_GetHeight(x, z);
float h01 = Terrain_GetHeight(x+1, z);
float h10 = Terrain_GetHeight(x, z+1);
float h11 = Terrain_GetHeight(x+1, z+1);
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.3, 0.3, 0.3);
glVertex3f(x, h00, z);
glColor3f(0.6, 0.6, 0.6);
glVertex3f(x+1, h01, z);
glColor3f(0.9, 0.9, 0.9);
glVertex3f(x+1, h11, z+1);
glColor3f(0.6, 0.6, 0.6);
glVertex3f(x, h10, z+1);
glEnd();
/*
glBegin(GL_TRIANGLE_FAN);
glColor3f(h00, h00, h00); glVertex3f(x, 0, z);
glColor3f(h01, h01, h01); glVertex3f(x+1, 0, z);
glColor3f(h11, h11, h11); glVertex3f(x+1, 0, z+1);
glColor3f(h10, h10, h10); glVertex3f(x, 0, z+1);
glEnd();
*/
}
//---- Terrain_DrawShape
void Terrain_DrawTri(float x1, float z1, float x2, float z2, float x3, float z3)
{
float h1 = Terrain_GetHeight(x1, z1);
float h2 = Terrain_GetHeight(x2, z2);
float h3 = Terrain_GetHeight(x3, z3);
/*
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.3, 0.3, 0.3);
glVertex3f(x1, h1, z1);
glColor3f(0.6, 0.6, 0.6);
glVertex3f(x2, h2, z2);
glColor3f(0.9, 0.9, 0.9);
glVertex3f(x3, h3, z3);
glEnd();
*/
glBegin(GL_TRIANGLE_FAN);
glColor3f(h1, h1, h1);
glVertex3f(x1, 0, z1);
glColor3f(h2, h2, h2);
glVertex3f(x2, 0, z2);
glColor3f(h3, h3, h3);
glVertex3f(x3, 0, z3);
glEnd();
}
//---- Terrain_GetPoint
void Terrain_GetPoint(int i, int j, float xo, float zo, float *x, float *z)
{
float d = i+i*(i-1)/14;
float a = j*3.14159/16;
*x = xo+d*sin(a); *z = zo+d*cos(a);
}
//---- Terrain_Draw
// Draws the terrain in openGL at the given position
void Terrain_Draw(float x, float y, float z)
{
int i, j;
/*
for(j=-30; j<=30; j++) for(i=-30; i<=30; i++) Terrain_DrawSquare(x+i, 0, z+j);
*/
for(j=0; j<=80; j++) for(i=0; i<=80; i++) Terrain_DrawSquare(x+i, 0, z+j);
/*
float x00, z00, x01, z01, x10, z10, x11, z11;
for(j=0; j<32; j++) {
for(i=1; i<20; i++) {
Terrain_GetPoint(i , j , x, z, &x00, &z00);
Terrain_GetPoint(i+1, j , x, z, &x01, &z01);
Terrain_GetPoint(i , j+1, x, z, &x10, &z10);
Terrain_GetPoint(i+1, j+1, x, z, &x11, &z11);
Terrain_DrawTri(x00, z00, x01, z01, x11, z11);
Terrain_DrawTri(x11, z11, x10, z10, x00, z00);
}
}
*/
}
//---- OLD OPENGL STUFF ------------------------------------------------------//
void Initialise()
{
}
void GameDraw(HWND hwnd)
{
static k=0;
int citysize = 500;
// k++;
int i=0, j=0;
zs_cubes = 0;
zs_buildings = 0;
// for(j=-2; j<=2; j++) for(i=-2; i<=2; i++)
City(0xA749F86C + (i<<17) + (j<<5) + k, -citysize/2 + i*citysize, -citysize/2 + j*citysize, citysize/2 + i*citysize, citysize/2 + j*citysize);
static int t = 0;
if(GetTickCount()-t > 500) {
t = GetTickCount();
char buf[50];
sprintf(buf, "City: %d buildings, %d cubes", zs_buildings, zs_cubes);
SetWindowText(hwnd, buf);
}
}
double r1=20/0.2, r2=-50/0.2;
double x=0, y=200, z=0;
int moving = 0;
void GameMain(HWND hwnd)
{
static int s = 0;
int t = GetTickCount();
int timediff = t-s;
if(timediff > 200) timediff = 200;
s = t;
{
double vx = 0, vy = 0, vz = -timediff*0.03*moving;
double wx, wy, wz;
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));
x += vx; y += vy; z += vz;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawBlack = false;
glLoadIdentity();
glRotatef(-r2*0.2, 1.0, 0.0, 0.0);
glRotatef(-r1*0.2, 0.0, 1.0, 0.0);
glTranslatef(-x, -y, -z);
GameDraw(hwnd);
/*
drawBlack = true;
glLoadIdentity();
glTranslatef(-1, 0, -10);
glRotatef(-r2*0.2, 1.0, 0.0, 0.0);
glRotatef(-r1*0.2, 0.0, 1.0, 0.0);
glTranslatef(-x, -y, -z);
GameDraw(hwnd);
glLoadIdentity();
glTranslatef( 1, 0, -10);
glRotatef(-r2*0.2, 1.0, 0.0, 0.0);
glRotatef(-r1*0.2, 0.0, 1.0, 0.0);
glTranslatef(-x, -y, -z);
GameDraw(hwnd);
glLoadIdentity();
glTranslatef(0, -1, -10);
glRotatef(-r2*0.2, 1.0, 0.0, 0.0);
glRotatef(-r1*0.2, 0.0, 1.0, 0.0);
glTranslatef(-x, -y, -z);
GameDraw(hwnd);
glLoadIdentity();
glTranslatef(0, 1, -10);
glRotatef(-r2*0.2, 1.0, 0.0, 0.0);
glRotatef(-r1*0.2, 0.0, 1.0, 0.0);
glTranslatef(-x, -y, -z);
GameDraw(hwnd);
*/
SwapBuffers(gl_dc);
}
//---- END OF FILE -----------------------------------------------------------//