mirror of https://github.com/skeeto/pixelcity.git
Initial check-in of project.
This commit is contained in:
parent
92c25d37b3
commit
948502769c
|
@ -0,0 +1,848 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Building.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This module contains the class to construct the buildings.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define MAX_VBUFFER 256
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
#include "building.h"
|
||||||
|
#include "deco.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
//This is used by the recursive roof builder to decide what items may be added.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ADDON_NONE,
|
||||||
|
ADDON_LOGO,
|
||||||
|
ADDON_TRIM,
|
||||||
|
ADDON_LIGHTS,
|
||||||
|
ADDON_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLvector vector_buffer[MAX_VBUFFER];
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This is the constructor for our building constructor.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CBuilding::CBuilding (int type, int x, int y, int height, int width, int depth, int seed, GLrgba color)
|
||||||
|
{
|
||||||
|
|
||||||
|
_x = x;
|
||||||
|
_y = y;
|
||||||
|
_width = width;
|
||||||
|
_depth = depth;
|
||||||
|
_height = height;
|
||||||
|
_center = glVector ((float)(_x + width / 2), 0.0f, (float)(_y + depth / 2));
|
||||||
|
_seed = seed;
|
||||||
|
_texture_type = RandomVal ();
|
||||||
|
_color = color;
|
||||||
|
_color.alpha = 0.1f;
|
||||||
|
_have_lights = false;
|
||||||
|
_have_logo = false;
|
||||||
|
_have_trim = false;
|
||||||
|
_roof_tiers = 0;
|
||||||
|
//Pick a color for logos & roof lights
|
||||||
|
//_trim_color = WorldLightColor (seed);
|
||||||
|
_trim_color = glRgbaFromHsl (0.5f, 1.0f, 0.9f);
|
||||||
|
_mesh = new CMesh; //The main textured mesh for the building
|
||||||
|
_mesh_flat = new CMesh; //Flat-color mesh for untextured detail items.
|
||||||
|
switch (type) {
|
||||||
|
case BUILDING_SIMPLE:
|
||||||
|
CreateSimple ();
|
||||||
|
break;
|
||||||
|
case BUILDING_MODERN:
|
||||||
|
CreateModern ();
|
||||||
|
break;
|
||||||
|
case BUILDING_TOWER:
|
||||||
|
CreateTower ();
|
||||||
|
break;
|
||||||
|
case BUILDING_BLOCKY:
|
||||||
|
CreateBlocky ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CBuilding::~CBuilding ()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (_mesh)
|
||||||
|
delete _mesh;
|
||||||
|
if (_mesh_flat)
|
||||||
|
delete _mesh_flat;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
unsigned CBuilding::Texture ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return TextureRandomBuilding (_texture_type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CBuilding::PolyCount ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return _mesh->PolyCount () + _mesh_flat->PolyCount ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::Render ()
|
||||||
|
{
|
||||||
|
|
||||||
|
glColor3fv (&_color.red);
|
||||||
|
_mesh->Render ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::RenderFlat (bool colored)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (colored)
|
||||||
|
glColor3fv (&_color.red);
|
||||||
|
_mesh_flat->Render ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::ConstructCube (int left, int right, int front, int back, int bottom, int top)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex p[10];
|
||||||
|
float x1, x2, z1, z2, y1, y2;
|
||||||
|
int i;
|
||||||
|
int index_list[10];
|
||||||
|
float u, v1, v2;
|
||||||
|
float mapping;
|
||||||
|
int base_index;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
height = top - bottom;
|
||||||
|
x1 = (float)left;
|
||||||
|
x2 = (float)right;
|
||||||
|
y1 = (float)bottom;
|
||||||
|
y2 = (float)top;
|
||||||
|
z1 = (float)front;
|
||||||
|
z2 = (float)back;
|
||||||
|
base_index = _mesh->VertexCount ();
|
||||||
|
|
||||||
|
mapping = (float)SEGMENTS_PER_TEXTURE;
|
||||||
|
u = (float)(RandomVal () % SEGMENTS_PER_TEXTURE) / (float)SEGMENTS_PER_TEXTURE;
|
||||||
|
v1 = (float)bottom / (float)mapping;
|
||||||
|
v2 = (float)top / (float)mapping;
|
||||||
|
|
||||||
|
p[0].position = glVector (x1, y1, z1); p[0].uv = glVector (u, v1);
|
||||||
|
p[1].position = glVector (x1, y2, z1); p[1].uv = glVector (u, v2);
|
||||||
|
u += (float)_width / mapping;
|
||||||
|
p[2].position = glVector (x2, y1, z1); p[2].uv = glVector (u, v1);
|
||||||
|
p[3].position = glVector (x2, y2, z1); p[3].uv = glVector (u, v2);
|
||||||
|
u += (float)_depth / mapping;
|
||||||
|
p[4].position = glVector (x2, y1, z2); p[4].uv = glVector (u, v1);
|
||||||
|
p[5].position = glVector (x2, y2, z2); p[5].uv = glVector (u, v2);
|
||||||
|
u += (float)_width / mapping;
|
||||||
|
p[6].position = glVector (x1, y1, z2); p[6].uv = glVector (u, v1);
|
||||||
|
p[7].position = glVector (x1, y2, z2); p[7].uv = glVector (u, v2);
|
||||||
|
u += (float)_width / mapping;
|
||||||
|
p[8].position = glVector (x1, y1, z1); p[8].uv = glVector (u, v1);
|
||||||
|
p[9].position = glVector (x1, y2, z1); p[9].uv = glVector (u, v2);
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
p[i].uv.x = (p[i].position.x + p[i].position.z) / (float)SEGMENTS_PER_TEXTURE;
|
||||||
|
_mesh->VertexAdd (p[i]);
|
||||||
|
index_list[i] = base_index + i;
|
||||||
|
}
|
||||||
|
_mesh->CubeAdd (&index_list[0]);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::ConstructCube (float left, float right, float front, float back, float bottom, float top)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex p[10];
|
||||||
|
float x1, x2, z1, z2, y1, y2;
|
||||||
|
int i;
|
||||||
|
int index_list[10];
|
||||||
|
int base_index;
|
||||||
|
|
||||||
|
x1 = left;
|
||||||
|
x2 = right;
|
||||||
|
y1 = bottom;
|
||||||
|
y2 = top;
|
||||||
|
z1 = front;
|
||||||
|
z2 = back;
|
||||||
|
base_index = _mesh_flat->VertexCount ();
|
||||||
|
|
||||||
|
p[0].position = glVector (x1, y1, z1); p[0].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[1].position = glVector (x1, y2, z1); p[1].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[2].position = glVector (x2, y1, z1); p[2].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[3].position = glVector (x2, y2, z1); p[3].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[4].position = glVector (x2, y1, z2); p[4].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[5].position = glVector (x2, y2, z2); p[5].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[6].position = glVector (x1, y1, z2); p[6].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[7].position = glVector (x1, y2, z2); p[7].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[8].position = glVector (x1, y1, z1); p[8].uv = glVector (0.0f, 0.0f);
|
||||||
|
p[9].position = glVector (x1, y2, z1); p[9].uv = glVector (0.0f, 0.0f);
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
p[i].uv.x = (p[i].position.x + p[i].position.z) / (float)SEGMENTS_PER_TEXTURE;
|
||||||
|
_mesh_flat->VertexAdd (p[i]);
|
||||||
|
index_list[i] = base_index + i;
|
||||||
|
}
|
||||||
|
_mesh_flat->CubeAdd (&index_list[0]);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This will take the given area and populate it with rooftop stuff like
|
||||||
|
air conditioners or light towers.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::ConstructRoof (float left, float right, float front, float back, float bottom)
|
||||||
|
{
|
||||||
|
|
||||||
|
int air_conditioners;
|
||||||
|
int i;
|
||||||
|
int width, depth, height;
|
||||||
|
int face;
|
||||||
|
int addon;
|
||||||
|
int max_tiers;
|
||||||
|
float ac_x;
|
||||||
|
float ac_y;
|
||||||
|
float ac_base;
|
||||||
|
float ac_size;
|
||||||
|
float ac_height;
|
||||||
|
float tower_height;
|
||||||
|
float logo_offset;
|
||||||
|
CDeco* d;
|
||||||
|
GLvector2 start, end;
|
||||||
|
|
||||||
|
_roof_tiers++;
|
||||||
|
max_tiers = _height / 10;
|
||||||
|
width = (int)(right - left);
|
||||||
|
depth = (int)(back - front);
|
||||||
|
height = 5 - _roof_tiers;
|
||||||
|
logo_offset = 0.2f;
|
||||||
|
//See if this building is special and worthy of fancy roof decorations.
|
||||||
|
if (bottom > 35.0f)
|
||||||
|
addon = RandomVal (ADDON_COUNT);
|
||||||
|
//Build the roof slab
|
||||||
|
ConstructCube (left, right, front, back, bottom, bottom + (float)height);
|
||||||
|
//Consider putting a logo on the roof, if it's tall enough
|
||||||
|
if (addon == ADDON_LOGO && !_have_logo) {
|
||||||
|
d = new CDeco;
|
||||||
|
if (width > depth)
|
||||||
|
face = COIN_FLIP ? NORTH : SOUTH;
|
||||||
|
else
|
||||||
|
face = COIN_FLIP ? EAST : WEST;
|
||||||
|
switch (face) {
|
||||||
|
case NORTH:
|
||||||
|
start = glVector ((float)left, (float)back + logo_offset);
|
||||||
|
end = glVector ((float)right, (float)back + logo_offset);
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
start = glVector ((float)right, (float)front - logo_offset);
|
||||||
|
end = glVector ((float)left, (float)front - logo_offset);
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
start = glVector ((float)right + logo_offset, (float)back);
|
||||||
|
end = glVector ((float)right + logo_offset, (float)front);
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
default:
|
||||||
|
start = glVector ((float)left - logo_offset, (float)front);
|
||||||
|
end = glVector ((float)left - logo_offset, (float)back);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
d->CreateLogo (start, end, bottom, WorldLogoIndex (), _trim_color);
|
||||||
|
_have_logo = true;
|
||||||
|
} else if (addon == ADDON_TRIM) {
|
||||||
|
d = new CDeco;
|
||||||
|
vector_buffer[0] = glVector (left, bottom, back);
|
||||||
|
vector_buffer[1] = glVector (left, bottom, front);
|
||||||
|
vector_buffer[2] = glVector (right, bottom, front);
|
||||||
|
vector_buffer[3] = glVector (right, bottom, back);
|
||||||
|
d->CreateLightTrim (vector_buffer, 4, (float)RandomVal (2) + 1.0f, _seed, _trim_color);
|
||||||
|
} else if (addon == ADDON_LIGHTS && !_have_lights) {
|
||||||
|
new CLight (glVector (left, (float)(bottom + 2), front), _trim_color, 2);
|
||||||
|
new CLight (glVector (right, (float)(bottom + 2), front), _trim_color, 2);
|
||||||
|
new CLight (glVector (right, (float)(bottom + 2), back), _trim_color, 2);
|
||||||
|
new CLight (glVector (left, (float)(bottom + 2), back), _trim_color, 2);
|
||||||
|
_have_lights = true;
|
||||||
|
}
|
||||||
|
bottom += (float)height;
|
||||||
|
//If the roof is big enough, consider making another layer
|
||||||
|
if (width > 7 && depth > 7 && _roof_tiers < max_tiers) {
|
||||||
|
ConstructRoof (left + 1, right - 1, front + 1, back - 1, bottom);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//1 air conditioner block for every 15 floors sounds reasonble
|
||||||
|
air_conditioners = _height / 15;
|
||||||
|
for (i = 0; i < air_conditioners; i++) {
|
||||||
|
ac_size = (float)(10 + RandomVal (30)) / 10;
|
||||||
|
ac_height = (float)RandomVal (20) / 10 + 1.0f;
|
||||||
|
ac_x = left + (float)RandomVal (width);
|
||||||
|
ac_y = front + (float)RandomVal (depth);
|
||||||
|
//make sure the unit doesn't hang off the right edge of the building
|
||||||
|
if (ac_x + ac_size > (float)right)
|
||||||
|
ac_x = (float)right - ac_size;
|
||||||
|
//make sure the unit doesn't hang off the back edge of the building
|
||||||
|
if (ac_y + ac_size > (float)back)
|
||||||
|
ac_y = (float)back - ac_size;
|
||||||
|
ac_base = (float)bottom;
|
||||||
|
//make sure it doesn't hang off the edge
|
||||||
|
ConstructCube (ac_x, ac_x + ac_size, ac_y, ac_y + ac_size, ac_base, ac_base + ac_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_height > 45) {
|
||||||
|
d = new CDeco;
|
||||||
|
tower_height = (float)(12 + RandomVal (8));
|
||||||
|
d->CreateRadioTower (glVector ((float)(left + right) / 2.0f, (float)bottom, (float)(front + back) / 2.0f), 15.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::ConstructSpike (int left, int right, int front, int back, int bottom, int top)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex p;
|
||||||
|
int index_list[6];
|
||||||
|
int i;
|
||||||
|
GLvector center;
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
index_list[i] = _mesh_flat->VertexCount () + i;
|
||||||
|
index_list[5] = index_list[1];
|
||||||
|
p.uv = glVector (0.0f, 0.0f);
|
||||||
|
center.x = ((float)left + (float)right) / 2.0f;
|
||||||
|
center.z = ((float)front + (float)back) / 2.0f;
|
||||||
|
p.position = glVector (center.x, (float)top, center.z);
|
||||||
|
_mesh_flat->VertexAdd (p);
|
||||||
|
|
||||||
|
p.position = glVector ((float)left, (float)bottom, (float)back);
|
||||||
|
_mesh_flat->VertexAdd (p);
|
||||||
|
|
||||||
|
p.position = glVector ((float)right, (float)bottom, (float)back);
|
||||||
|
_mesh_flat->VertexAdd (p);
|
||||||
|
|
||||||
|
p.position = glVector ((float)right, (float)bottom, (float)front);
|
||||||
|
_mesh_flat->VertexAdd (p);
|
||||||
|
|
||||||
|
p.position = glVector ((float)left, (float)bottom, (float)front);
|
||||||
|
_mesh_flat->VertexAdd (p);
|
||||||
|
|
||||||
|
_mesh_flat->FanAdd (&index_list[0], 6);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This builds an outer wall of a building, with blank (windowless) areas
|
||||||
|
deliberately left. It creates a chain of segments that alternate
|
||||||
|
between windowed and windowless, and it always makes sure the wall
|
||||||
|
is symetrical. window_groups tells it how many windows to place in a row.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float CBuilding::ConstructWall (int start_x, int start_y, int start_z, int direction, int length, int height, int window_groups, float uv_start, bool blank_corners)
|
||||||
|
{
|
||||||
|
|
||||||
|
int x, z;
|
||||||
|
int step_x, step_z;
|
||||||
|
int i;
|
||||||
|
int index_list[100];
|
||||||
|
int current_index;
|
||||||
|
int column;
|
||||||
|
int mid;
|
||||||
|
int odd;
|
||||||
|
GLvertex v;
|
||||||
|
bool blank;
|
||||||
|
bool last_blank;
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case NORTH:
|
||||||
|
step_z = 1; step_x = 0; break;
|
||||||
|
case WEST:
|
||||||
|
step_z = 0; step_x = -1; break;
|
||||||
|
case SOUTH:
|
||||||
|
step_z = -1; step_x = 0; break;
|
||||||
|
case EAST:
|
||||||
|
step_z = 0; step_x = 1; break;
|
||||||
|
}
|
||||||
|
x = start_x;;
|
||||||
|
z = start_z;
|
||||||
|
current_index = 0;
|
||||||
|
mid = (length / 2) - 1;
|
||||||
|
odd = 1 - (length % 2);
|
||||||
|
if (length % 2)
|
||||||
|
mid++;
|
||||||
|
//mid = (length / 2);
|
||||||
|
v.uv.x = (float)(x + z) / SEGMENTS_PER_TEXTURE;
|
||||||
|
v.uv.x = uv_start;
|
||||||
|
blank = false;
|
||||||
|
for (i = 0; i <= length; i++) {
|
||||||
|
//column counts up to the mid point, then back down, to make it symetrical
|
||||||
|
if (i <= mid)
|
||||||
|
column = i - odd;
|
||||||
|
else
|
||||||
|
column = (mid) - (i - (mid));
|
||||||
|
last_blank = blank;
|
||||||
|
blank = (column % window_groups) > window_groups / 2;
|
||||||
|
if (blank_corners && i == 0)
|
||||||
|
blank = true;
|
||||||
|
if (blank_corners && i == (length - 1))
|
||||||
|
blank = true;
|
||||||
|
if (last_blank != blank || i == 0 || i == length) {
|
||||||
|
v.position = glVector ((float)x, (float)start_y, (float)z);
|
||||||
|
v.uv.y = (float)start_y / SEGMENTS_PER_TEXTURE;
|
||||||
|
_mesh->VertexAdd (v);
|
||||||
|
index_list[current_index] = _mesh->VertexCount () - 1;
|
||||||
|
current_index++;
|
||||||
|
v.position.y = (float)(start_y + height);
|
||||||
|
v.uv.y = (float)(start_y + height) / SEGMENTS_PER_TEXTURE;;
|
||||||
|
_mesh->VertexAdd (v);
|
||||||
|
index_list[current_index] = _mesh->VertexCount () - 1;
|
||||||
|
current_index++;
|
||||||
|
}
|
||||||
|
//if (!blank && i != 0 && i != (length - 1))
|
||||||
|
if (!blank && i != length)
|
||||||
|
v.uv.x += 1.0f / SEGMENTS_PER_TEXTURE;
|
||||||
|
x += step_x;
|
||||||
|
z += step_z;
|
||||||
|
}
|
||||||
|
_mesh->QuadStripAdd (&index_list[0], current_index);
|
||||||
|
return v.uv.x;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int maxt;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This makes a big chunky building of intersecting cubes.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::CreateBlocky ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int min_height;
|
||||||
|
int left, right, front, back;
|
||||||
|
int max_left, max_right, max_front, max_back;
|
||||||
|
int height;
|
||||||
|
int mid_x, mid_z;
|
||||||
|
int half_depth, half_width;
|
||||||
|
int tiers;
|
||||||
|
int max_tiers;
|
||||||
|
int grouping;
|
||||||
|
float lid_height;
|
||||||
|
float uv_start;
|
||||||
|
bool skip;
|
||||||
|
bool blank_corners;
|
||||||
|
|
||||||
|
//Choose if the corners of the building are to be windowless.
|
||||||
|
blank_corners = COIN_FLIP;
|
||||||
|
//Choose a random column on our texture;
|
||||||
|
uv_start = (float)RandomVal (SEGMENTS_PER_TEXTURE) / SEGMENTS_PER_TEXTURE;
|
||||||
|
//Choose how the windows are grouped
|
||||||
|
grouping = 2 + RandomVal (4);
|
||||||
|
//Choose how tall the lid should be on top of each section
|
||||||
|
lid_height = (float)(RandomVal (3) + 1);
|
||||||
|
//find the center of the building.
|
||||||
|
mid_x = _x + _width / 2;
|
||||||
|
mid_z = _y + _depth / 2;
|
||||||
|
max_left = max_right = max_front = max_back = 1;
|
||||||
|
height = _height;
|
||||||
|
min_height = _height / 2;
|
||||||
|
min_height = 3;
|
||||||
|
half_depth = _depth / 2;
|
||||||
|
half_width = _width / 2;
|
||||||
|
tiers = 0;
|
||||||
|
if (_height > 40)
|
||||||
|
max_tiers = 15;
|
||||||
|
else if (_height > 30)
|
||||||
|
max_tiers = 10;
|
||||||
|
else if (_height > 20)
|
||||||
|
max_tiers = 5;
|
||||||
|
else if (_height > 10)
|
||||||
|
max_tiers = 2;
|
||||||
|
else
|
||||||
|
max_tiers = 1;
|
||||||
|
max_tiers = MIN (maxt, max_tiers);
|
||||||
|
maxt++;
|
||||||
|
maxt %= 8;
|
||||||
|
//We begin at the top of the building, and work our way down.
|
||||||
|
//Viewed from above, the sections of the building are randomly sized
|
||||||
|
//rectangles that ALWAYS include the center of the building somewhere within
|
||||||
|
//their area.
|
||||||
|
while (1) {
|
||||||
|
if (height < min_height)
|
||||||
|
break;
|
||||||
|
if (tiers >= max_tiers)
|
||||||
|
break;
|
||||||
|
//pick new locationsfor our four outer walls
|
||||||
|
left = (RandomVal () % half_width) + 1;
|
||||||
|
right = (RandomVal () % half_width) + 1;
|
||||||
|
front = (RandomVal () % half_depth) + 1;
|
||||||
|
back = (RandomVal () % half_depth) + 1;
|
||||||
|
skip = false;
|
||||||
|
//At least ONE of the walls must reach out beyond a previous maximum.
|
||||||
|
//Otherwise, this tier would be completely hidden within a previous one.
|
||||||
|
if (left <= max_left && right <= max_right && front <= max_front && back <= max_back)
|
||||||
|
skip = true;
|
||||||
|
//If any of the four walls is in the same position as the previous max,then
|
||||||
|
//skip this tier, or else the two walls will end up z-fightng.
|
||||||
|
if (left == max_left || right == max_right || front == max_front || back == max_back)
|
||||||
|
skip = true;
|
||||||
|
if (!skip) {
|
||||||
|
//if this is the top, then put some lights up here
|
||||||
|
max_left = MAX (left, max_left);
|
||||||
|
max_right = MAX (right, max_right);
|
||||||
|
max_front = MAX (front, max_front);
|
||||||
|
max_back = MAX (back, max_back);
|
||||||
|
//Now build the four walls of this part
|
||||||
|
uv_start = ConstructWall (mid_x - left, 0, mid_z + back, SOUTH, front + back, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
|
||||||
|
uv_start = ConstructWall (mid_x - left, 0, mid_z - front, EAST, right + left, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
|
||||||
|
uv_start = ConstructWall (mid_x + right, 0, mid_z - front, NORTH, front + back, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
|
||||||
|
uv_start = ConstructWall (mid_x + right, 0, mid_z + back, WEST, right + left, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
|
||||||
|
if (!tiers)
|
||||||
|
ConstructRoof ((float)(mid_x - left), (float)(mid_x + right), (float)(mid_z - front), (float)(mid_z + back), (float)height);
|
||||||
|
else //add a flat-color lid onto this section
|
||||||
|
ConstructCube ((float)(mid_x - left), (float)(mid_x + right), (float)(mid_z - front), (float)(mid_z + back), (float)height, (float)height + lid_height);
|
||||||
|
height -= (RandomVal () % 10) + 1;
|
||||||
|
tiers++;
|
||||||
|
}
|
||||||
|
height--;
|
||||||
|
}
|
||||||
|
ConstructCube (mid_x - half_width, mid_x + half_width, mid_z - half_depth, mid_z + half_depth, 0, 2);
|
||||||
|
_mesh->Compile ();
|
||||||
|
_mesh_flat->Compile ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
A single-cube building. Good for low-rise buildings and stuff that will be
|
||||||
|
far from the camera;
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::CreateSimple ()
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex p;
|
||||||
|
float x1, x2, z1, z2, y1, y2;
|
||||||
|
int index_list[] = {0,1,2,3,4,5,6,7,8,9,10};
|
||||||
|
float u, v1, v2;
|
||||||
|
float cap_height;
|
||||||
|
float ledge;
|
||||||
|
|
||||||
|
//How tall the flat-color roof is
|
||||||
|
cap_height = (float)(1 + RandomVal (4));
|
||||||
|
//how much the ledge sticks out
|
||||||
|
ledge = (float)RandomVal (10) / 30.0f;
|
||||||
|
|
||||||
|
x1 = (float)_x;
|
||||||
|
x2 = (float)(_x + _width);
|
||||||
|
y1 = (float)0.0f;
|
||||||
|
y2 = (float)_height;
|
||||||
|
z2 = (float)_y;
|
||||||
|
z1 = (float)(_y + _depth);
|
||||||
|
|
||||||
|
u = (float)(RandomVal (SEGMENTS_PER_TEXTURE)) / SEGMENTS_PER_TEXTURE;
|
||||||
|
v1 = (float)(RandomVal (SEGMENTS_PER_TEXTURE)) / SEGMENTS_PER_TEXTURE;
|
||||||
|
v2 = v1 + (float)_height * ONE_SEGMENT;
|
||||||
|
|
||||||
|
p.position = glVector (x1, y1, z1); p.uv = glVector (u, v1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x1, y2, z1); p.uv = glVector (u, v2);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
u += (float)_depth / SEGMENTS_PER_TEXTURE;
|
||||||
|
|
||||||
|
p.position = glVector (x1, y1, z2); p.uv = glVector (u, v1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x1, y2, z2); p.uv = glVector (u, v2);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
u += (float)_width / SEGMENTS_PER_TEXTURE;
|
||||||
|
|
||||||
|
p.position = glVector (x2, y1, z2); p.uv = glVector (u, v1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x2, y2, z2); p.uv = glVector (u, v2);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
u += (float)_depth / SEGMENTS_PER_TEXTURE;
|
||||||
|
|
||||||
|
p.position = glVector (x2, y1, z1); p.uv = glVector (u, v1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x2, y2, z1); p.uv = glVector (u, v2);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
u += (float)_depth / SEGMENTS_PER_TEXTURE;
|
||||||
|
|
||||||
|
p.position = glVector (x1, y1, z1); p.uv = glVector (u, v1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x1, y2, z1); p.uv = glVector (u, v2);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
|
||||||
|
_mesh->QuadStripAdd (index_list, 10);
|
||||||
|
ConstructCube (x1 - ledge, x2 + ledge, z2 - ledge, z1 + ledge, (float)_height, (float)_height + cap_height);
|
||||||
|
_mesh->Compile ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This makes a deformed cylinder building.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::CreateModern ()
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex p;
|
||||||
|
GLvector center;
|
||||||
|
GLvector pos;
|
||||||
|
GLvector2 radius;
|
||||||
|
GLvector2 start, end;
|
||||||
|
int angle;
|
||||||
|
int windows;
|
||||||
|
int cap_height;
|
||||||
|
int half_depth, half_width;
|
||||||
|
float dist;
|
||||||
|
float length;
|
||||||
|
int* index_list;
|
||||||
|
int points;
|
||||||
|
int skip_interval;
|
||||||
|
int skip_counter;
|
||||||
|
int skip_delta;
|
||||||
|
bool logo_done;
|
||||||
|
bool do_trim;
|
||||||
|
CDeco* d;
|
||||||
|
|
||||||
|
logo_done = false;
|
||||||
|
//How tall the windowless section on top will be.
|
||||||
|
cap_height = 1 + RandomVal (5);
|
||||||
|
//How many 10-degree segments to build before the next skip.
|
||||||
|
skip_interval = 1 + RandomVal (8);
|
||||||
|
//When a skip happens, how many degrees should be skipped
|
||||||
|
skip_delta = (1 + RandomVal (2)) * 30; //30 60 or 90
|
||||||
|
//See if this is eligible for fancy lighting trim on top
|
||||||
|
if (_height > 48 && RandomVal (3) == 0)
|
||||||
|
do_trim = true;
|
||||||
|
else
|
||||||
|
do_trim = false;
|
||||||
|
//Get the center and radius of the circle
|
||||||
|
half_depth = _depth / 2;
|
||||||
|
half_width = _width / 2;
|
||||||
|
center = glVector ((float)(_x + half_width), 0.0f, (float)(_y + half_depth));
|
||||||
|
radius = glVector ((float)half_width, (float)half_depth);
|
||||||
|
dist = 0;
|
||||||
|
windows = 0;
|
||||||
|
p.uv.x = 0.0f;
|
||||||
|
points = 0;
|
||||||
|
skip_counter = 0;
|
||||||
|
for (angle = 0; angle <= 360; angle += 10) {
|
||||||
|
if (skip_counter >= skip_interval && (angle + skip_delta < 360)) {
|
||||||
|
angle += skip_delta;
|
||||||
|
skip_counter = 0;
|
||||||
|
}
|
||||||
|
pos.x = center.x - sinf ((float)angle * DEGREES_TO_RADIANS) * radius.x;
|
||||||
|
pos.z = center.z + cosf ((float)angle * DEGREES_TO_RADIANS) * radius.y;
|
||||||
|
if (angle > 0 && skip_counter == 0) {
|
||||||
|
length = MathDistance (p.position.x, p.position.z, pos.x, pos.z);
|
||||||
|
windows += (int)length;
|
||||||
|
if (length > 10 && !logo_done) {
|
||||||
|
logo_done = true;
|
||||||
|
start = glVector (pos.x, pos.z);
|
||||||
|
end = glVector (p.position.x, p.position.z);
|
||||||
|
d = new CDeco;
|
||||||
|
d->CreateLogo (start, end, (float)_height, WorldLogoIndex (), RANDOM_COLOR);
|
||||||
|
}
|
||||||
|
} else if (skip_counter != 1)
|
||||||
|
windows++;
|
||||||
|
p.position = pos;
|
||||||
|
p.uv.x = (float)windows / (float)SEGMENTS_PER_TEXTURE;
|
||||||
|
p.uv.y = 0.0f;
|
||||||
|
p.position.y = 0.0f;
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position.y = (float)_height;
|
||||||
|
p.uv.y = (float)_height / (float)SEGMENTS_PER_TEXTURE;
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
_mesh_flat->VertexAdd (p);
|
||||||
|
p.position.y += (float)cap_height;
|
||||||
|
_mesh_flat->VertexAdd (p);
|
||||||
|
vector_buffer[points / 2] = p.position;
|
||||||
|
vector_buffer[points / 2].y = (float)_height + cap_height / 4;
|
||||||
|
points += 2;
|
||||||
|
skip_counter++;
|
||||||
|
}
|
||||||
|
//if this is a big building and it didn't get a logo, consider giving it a light strip
|
||||||
|
if (!logo_done && do_trim) {
|
||||||
|
d = new CDeco;
|
||||||
|
d->CreateLightTrim (vector_buffer, (points / 2) - 2, (float)cap_height / 2, _seed, RANDOM_COLOR);
|
||||||
|
}
|
||||||
|
index_list = new int[points];
|
||||||
|
//Add the outer walls
|
||||||
|
for (int i = 0; i < points; i++)
|
||||||
|
index_list[i] = i;
|
||||||
|
_mesh->QuadStripAdd (index_list, points);
|
||||||
|
_mesh_flat->QuadStripAdd (index_list, points);
|
||||||
|
//add the fan to cap the top of the buildings
|
||||||
|
for (i = 0; i < points / 2; i++)
|
||||||
|
index_list[i + 1] = points - (1 + i * 2);
|
||||||
|
p.position.x = _center.x;
|
||||||
|
p.position.z = _center.z;
|
||||||
|
_mesh_flat->VertexAdd (p);
|
||||||
|
index_list[0] = points;
|
||||||
|
_mesh_flat->FanAdd (index_list, 1 + points / 2);
|
||||||
|
delete index_list;
|
||||||
|
radius /= 2.0f;
|
||||||
|
//ConstructRoof ((int)(_center.x - radius), (int)(_center.x + radius), (int)(_center.z - radius), (int)(_center.z + radius), _height + cap_height);
|
||||||
|
_mesh->Compile ();
|
||||||
|
_mesh_flat->Compile ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CBuilding::CreateTower ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int left, right, front, back, bottom;
|
||||||
|
int section_height, section_width, section_depth;
|
||||||
|
int remaining_height;
|
||||||
|
int ledge_height;
|
||||||
|
int tier_fraction;
|
||||||
|
int grouping;
|
||||||
|
int foundation;
|
||||||
|
float ledge;
|
||||||
|
float uv_start;
|
||||||
|
bool blank_corners;
|
||||||
|
bool roof_spike;
|
||||||
|
bool narrowing;
|
||||||
|
bool tower;
|
||||||
|
|
||||||
|
//How much ledges protrude from the building
|
||||||
|
ledge = (float)RandomVal (3) * 0.25f;
|
||||||
|
//How tall the ledges are, in stories
|
||||||
|
ledge_height = RandomVal (3) + 1;
|
||||||
|
//How the windows are grouped
|
||||||
|
grouping = RandomVal (3) + 2;
|
||||||
|
//if the corners of the building have no windows
|
||||||
|
blank_corners = COIN_FLIP;
|
||||||
|
//if the roof is pointed or has infrastructure on it
|
||||||
|
roof_spike = RandomVal (3) == 0;
|
||||||
|
//What fraction of the remaining height should be given to each tier
|
||||||
|
tier_fraction = 2 + RandomVal (3);
|
||||||
|
//Does the tower get narrower towards the top?
|
||||||
|
narrowing = RandomVal (3) == 0;
|
||||||
|
//The height of the windowsless slab at the bottom
|
||||||
|
foundation = 2 + RandomVal (3);
|
||||||
|
//The odds that we'll have a big fancy spikey top
|
||||||
|
tower = RandomVal (5) != 0 && _height > 40;
|
||||||
|
//set our initial parameters
|
||||||
|
left = _x;
|
||||||
|
right = _x + _width;
|
||||||
|
front = _y;
|
||||||
|
back = _y + _depth;
|
||||||
|
bottom = 0;
|
||||||
|
//build the foundations.
|
||||||
|
ConstructCube ((float)left - ledge, (float)right + ledge, (float)front - ledge, (float)back + ledge, (float)bottom, (float)foundation);
|
||||||
|
bottom += foundation;
|
||||||
|
//now add tiers until we reach the top
|
||||||
|
while (1) {
|
||||||
|
remaining_height = _height - bottom;
|
||||||
|
section_depth = back - front;
|
||||||
|
section_width = right - left;
|
||||||
|
section_height = MAX (remaining_height / tier_fraction, 2);
|
||||||
|
if (remaining_height < 10)
|
||||||
|
section_height = remaining_height;
|
||||||
|
//Build the four walls
|
||||||
|
uv_start = (float)RandomVal (SEGMENTS_PER_TEXTURE) / SEGMENTS_PER_TEXTURE;
|
||||||
|
uv_start = ConstructWall (left, bottom, back, SOUTH, section_depth, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
|
||||||
|
uv_start = ConstructWall (left, bottom, front, EAST, section_width, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
|
||||||
|
uv_start = ConstructWall (right, bottom, front, NORTH, section_depth, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
|
||||||
|
uv_start = ConstructWall (right, bottom, back, WEST, section_width, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
|
||||||
|
bottom += section_height;
|
||||||
|
//Build the slab / ledges to cap this section.
|
||||||
|
if (bottom + ledge_height > _height)
|
||||||
|
break;
|
||||||
|
ConstructCube ((float)left - ledge, (float)right + ledge, (float)front - ledge, (float)back + ledge, (float)bottom, (float)(bottom + ledge_height));
|
||||||
|
bottom += ledge_height;
|
||||||
|
if (bottom > _height)
|
||||||
|
break;
|
||||||
|
if (ledge_height > 1 && narrowing)
|
||||||
|
ledge_height--;
|
||||||
|
if (narrowing) {
|
||||||
|
if (section_width > 7) {
|
||||||
|
left+=1;
|
||||||
|
right-=1;
|
||||||
|
}
|
||||||
|
if (section_depth > 7) {
|
||||||
|
front+=1;
|
||||||
|
back-=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConstructRoof ((float)left, (float)right, (float)front, (float)back, (float)bottom);
|
||||||
|
_mesh->Compile ();
|
||||||
|
_mesh_flat->Compile ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef ENTITY
|
||||||
|
#include "entity.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BUILDING_SIMPLE,
|
||||||
|
BUILDING_BLOCKY,
|
||||||
|
BUILDING_MODERN,
|
||||||
|
BUILDING_TOWER
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBuilding : public CEntity
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
int _x;
|
||||||
|
int _y;
|
||||||
|
int _width;
|
||||||
|
int _depth;
|
||||||
|
int _height;
|
||||||
|
int _texture_type;
|
||||||
|
int _seed;
|
||||||
|
int _roof_tiers;
|
||||||
|
GLrgba _color;
|
||||||
|
GLrgba _trim_color;
|
||||||
|
class CMesh* _mesh;
|
||||||
|
class CMesh* _mesh_flat;
|
||||||
|
bool _have_lights;
|
||||||
|
bool _have_trim;
|
||||||
|
bool _have_logo;
|
||||||
|
|
||||||
|
|
||||||
|
void CreateSimple ();
|
||||||
|
void CreateBlocky ();
|
||||||
|
void CreateModern ();
|
||||||
|
void CreateTower ();
|
||||||
|
|
||||||
|
float ConstructWall (int start_x, int start_y, int start_z, int direction, int length, int height, int window_groups, float uv_start, bool blank_corners);
|
||||||
|
void ConstructSpike (int left, int right, int front, int back, int bottom, int top);
|
||||||
|
void ConstructCube (int left, int right, int front, int back, int bottom, int top);
|
||||||
|
void ConstructCube (float left, float right, float front, float back, float bottom, float top);
|
||||||
|
void ConstructRoof (float left, float right, float front, float back, float bottom);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CBuilding (int type, int x, int y, int height, int width, int depth, int seed, GLrgba color);
|
||||||
|
~CBuilding ();
|
||||||
|
void Render (void);
|
||||||
|
int PolyCount ();
|
||||||
|
void RenderFlat (bool colored);
|
||||||
|
unsigned Texture ();
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,403 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Camera.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This tracks the position and oritentation of the camera. In screensaver
|
||||||
|
mode, it moves the camera around the world in order to create dramatic
|
||||||
|
views of the hot zone.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define EYE_HEIGHT 2.0f
|
||||||
|
#define MAX_PITCH 85
|
||||||
|
#define FLYCAM_CIRCUT 60000
|
||||||
|
#define FLYCAM_CIRCUT_HALF (FLYCAM_CIRCUT / 2)
|
||||||
|
#define FLYCAM_LEG (FLYCAM_CIRCUT / 4)
|
||||||
|
#define ONE_SECOND 1000
|
||||||
|
#define CAMERA_CHANGE_INTERVAL 15
|
||||||
|
#define CAMERA_CYCLE_LENGTH (CAMERA_MODES*CAMERA_CHANGE_INTERVAL)
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "glTypes.h"
|
||||||
|
#include "ini.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "world.h"
|
||||||
|
#include "win.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CAMERA_FLYCAM1,
|
||||||
|
CAMERA_ORBIT_INWARD,
|
||||||
|
CAMERA_ORBIT_OUTWARD,
|
||||||
|
CAMERA_ORBIT_ELLIPTICAL,
|
||||||
|
CAMERA_FLYCAM2,
|
||||||
|
CAMERA_SPEED,
|
||||||
|
CAMERA_SPIN,
|
||||||
|
CAMERA_FLYCAM3,
|
||||||
|
CAMERA_MODES
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLvector angle;
|
||||||
|
static GLvector position;
|
||||||
|
static GLvector auto_angle;
|
||||||
|
static GLvector auto_position;
|
||||||
|
static float distance;
|
||||||
|
static float movement;
|
||||||
|
static bool moving;
|
||||||
|
static bool cam_auto;
|
||||||
|
static float tracker;
|
||||||
|
static unsigned last_update;
|
||||||
|
static int camera_behavior;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
static GLvector flycam_position (unsigned t)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned leg;
|
||||||
|
float delta;
|
||||||
|
GLvector start, end;
|
||||||
|
GLbbox hot_zone;
|
||||||
|
|
||||||
|
hot_zone = WorldHotZone ();
|
||||||
|
t %= FLYCAM_CIRCUT;
|
||||||
|
leg = t / FLYCAM_LEG;
|
||||||
|
delta = (float)(t % FLYCAM_LEG) / FLYCAM_LEG;
|
||||||
|
switch (leg) {
|
||||||
|
case 0:
|
||||||
|
start = glVector (hot_zone.min.x, 25.0f, hot_zone.min.z);
|
||||||
|
end = glVector (hot_zone.min.x, 60.0f, hot_zone.max.z);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
start = glVector (hot_zone.min.x, 60.0f, hot_zone.max.z);
|
||||||
|
end = glVector (hot_zone.max.x, 25.0f, hot_zone.max.z);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
start = glVector (hot_zone.max.x, 25.0f, hot_zone.max.z);
|
||||||
|
end = glVector (hot_zone.max.x, 60.0f, hot_zone.min.z);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
start = glVector (hot_zone.max.x, 60.0f, hot_zone.min.z);
|
||||||
|
end = glVector (hot_zone.min.x, 25.0f, hot_zone.min.z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delta = MathScalarCurve (delta);
|
||||||
|
return glVectorInterpolate (start, end, delta);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void do_auto_cam ()
|
||||||
|
{
|
||||||
|
|
||||||
|
float dist;
|
||||||
|
unsigned t;
|
||||||
|
unsigned elapsed;
|
||||||
|
unsigned now;
|
||||||
|
int behavior;
|
||||||
|
GLvector target;
|
||||||
|
|
||||||
|
now = GetTickCount ();
|
||||||
|
elapsed = now - last_update;
|
||||||
|
elapsed = MIN (elapsed, 1000); //limit to 1 second worth of time
|
||||||
|
if (elapsed == 0)
|
||||||
|
return;
|
||||||
|
last_update = now;
|
||||||
|
t = time (NULL) % CAMERA_CYCLE_LENGTH;
|
||||||
|
#if SCREENSAVER
|
||||||
|
behavior = t / CAMERA_CHANGE_INTERVAL;
|
||||||
|
#else
|
||||||
|
behavior = camera_behavior;
|
||||||
|
#endif
|
||||||
|
tracker += (float)elapsed / 100.0f;
|
||||||
|
//behavior = CAMERA_FLYCAM1;
|
||||||
|
switch (behavior) {
|
||||||
|
case CAMERA_ORBIT_INWARD:
|
||||||
|
auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 150.0f;
|
||||||
|
auto_position.y = 60.0f;
|
||||||
|
auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 150.0f;
|
||||||
|
target = glVector (WORLD_HALF, 40.0f, WORLD_HALF);
|
||||||
|
break;
|
||||||
|
case CAMERA_ORBIT_OUTWARD:
|
||||||
|
auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 250.0f;
|
||||||
|
auto_position.y = 60.0f;
|
||||||
|
auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 250.0f;
|
||||||
|
target = glVector (WORLD_HALF, 30.0f, WORLD_HALF);
|
||||||
|
break;
|
||||||
|
case CAMERA_ORBIT_ELLIPTICAL:
|
||||||
|
dist = 150.0f + sinf (tracker * DEGREES_TO_RADIANS / 1.1f) * 50;
|
||||||
|
auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * dist;
|
||||||
|
auto_position.y = 60.0f;
|
||||||
|
auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * dist;
|
||||||
|
target = glVector (WORLD_HALF, 50.0f, WORLD_HALF);
|
||||||
|
break;
|
||||||
|
case CAMERA_FLYCAM1:
|
||||||
|
case CAMERA_FLYCAM2:
|
||||||
|
case CAMERA_FLYCAM3:
|
||||||
|
auto_position = (flycam_position (now) + flycam_position (now + 4000)) / 2.0f;
|
||||||
|
target = flycam_position (now + FLYCAM_CIRCUT_HALF - ONE_SECOND * 3);
|
||||||
|
break;
|
||||||
|
case CAMERA_SPEED:
|
||||||
|
auto_position = (flycam_position (now) + flycam_position (now + 500)) / 2.0f;
|
||||||
|
target = flycam_position (now + ONE_SECOND * 5);
|
||||||
|
auto_position.y /= 2;
|
||||||
|
target.y /= 2;
|
||||||
|
break;
|
||||||
|
case CAMERA_SPIN:
|
||||||
|
default:
|
||||||
|
target.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 300.0f;
|
||||||
|
target.y = 30.0f;
|
||||||
|
target.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 300.0f;
|
||||||
|
auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 50.0f;
|
||||||
|
auto_position.y = 60.0f;
|
||||||
|
auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 50.0f;
|
||||||
|
}
|
||||||
|
dist = MathDistance (auto_position.x, auto_position.z, target.x, target.z);
|
||||||
|
auto_angle.y = MathAngle (-MathAngle (auto_position.x, auto_position.z, target.x, target.z));
|
||||||
|
auto_angle.x = 90.0f + MathAngle (0, auto_position.y, dist, target.y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraAutoToggle ()
|
||||||
|
{
|
||||||
|
|
||||||
|
cam_auto = !cam_auto;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraNextBehavior ()
|
||||||
|
{
|
||||||
|
|
||||||
|
camera_behavior++;
|
||||||
|
camera_behavior %= CAMERA_MODES;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraYaw (float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
moving = true;
|
||||||
|
angle.y -= delta;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraPitch (float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
moving = true;
|
||||||
|
angle.x -= delta;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraPan (float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
float move_x, move_y;
|
||||||
|
|
||||||
|
moving = true;
|
||||||
|
move_x = (float)sin (-angle.y * DEGREES_TO_RADIANS) / 10.0f;
|
||||||
|
move_y = (float)cos (-angle.y * DEGREES_TO_RADIANS) / 10.0f;
|
||||||
|
position.x -= move_y * delta;
|
||||||
|
position.z -= -move_x * delta;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraForward (float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
float move_x, move_y;
|
||||||
|
|
||||||
|
moving = true;
|
||||||
|
move_y = (float)sin (-angle.y * DEGREES_TO_RADIANS) / 10.0f;
|
||||||
|
move_x = (float)cos (-angle.y * DEGREES_TO_RADIANS) / 10.0f;
|
||||||
|
position.x -= move_y * delta;
|
||||||
|
position.z -= move_x * delta;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraSelectionPitch (float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraSelectionZoom (float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraSelectionYaw (float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector CameraPosition (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (cam_auto)
|
||||||
|
return auto_position;
|
||||||
|
return position;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraReset ()
|
||||||
|
{
|
||||||
|
|
||||||
|
position.y = 50.0f;
|
||||||
|
position.x = WORLD_HALF;
|
||||||
|
position.z = WORLD_HALF;
|
||||||
|
angle.x = 0.0f;
|
||||||
|
angle.y = 0.0f;
|
||||||
|
angle.z = 0.0f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraPositionSet (GLvector new_pos)
|
||||||
|
{
|
||||||
|
|
||||||
|
position = new_pos;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector CameraAngle (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (cam_auto)
|
||||||
|
return auto_angle;
|
||||||
|
return angle;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraAngleSet (GLvector new_angle)
|
||||||
|
{
|
||||||
|
|
||||||
|
angle = new_angle;
|
||||||
|
angle.x = CLAMP (angle.x, -80.0f, 80.0f);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraInit (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
angle = IniVector ("CameraAngle");
|
||||||
|
position = IniVector ("CameraPosition");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraUpdate (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if SCREENSAVER
|
||||||
|
cam_auto = true;
|
||||||
|
#endif
|
||||||
|
if (cam_auto)
|
||||||
|
do_auto_cam ();
|
||||||
|
if (moving)
|
||||||
|
movement *= 1.1f;
|
||||||
|
else
|
||||||
|
movement = 0.0f;
|
||||||
|
movement = CLAMP (movement, 0.01f, 1.0f);
|
||||||
|
|
||||||
|
if (angle.y < 0.0f)
|
||||||
|
angle.y = 360.0f - (float)fmod (fabs (angle.y), 360.0f);
|
||||||
|
angle.y = (float)fmod (angle.y, 360.0f);
|
||||||
|
angle.x = CLAMP (angle.x, -MAX_PITCH, MAX_PITCH);
|
||||||
|
moving = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CameraTerm (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
//just store our most recent position in the ini
|
||||||
|
IniVectorSet ("CameraAngle", angle);
|
||||||
|
IniVectorSet ("CameraPosition", position);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef TYPES
|
||||||
|
#include "glTypes.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GLvector CameraAngle (void);
|
||||||
|
void CameraAngleSet (GLvector new_angle);
|
||||||
|
void CameraAutoToggle ();
|
||||||
|
float CameraDistance (void);
|
||||||
|
void CameraDistanceSet (float new_distance);
|
||||||
|
void CameraInit (void);
|
||||||
|
void CameraNextBehavior (void);
|
||||||
|
GLvector CameraPosition (void);
|
||||||
|
void CameraPositionSet (GLvector new_pos);
|
||||||
|
void CameraReset ();
|
||||||
|
void CameraUpdate (void);
|
||||||
|
void CameraTerm (void);
|
||||||
|
|
||||||
|
void CameraForward (float delta);
|
||||||
|
void CameraSelectionPitch (float delta_y);
|
||||||
|
void CameraSelectionYaw (float delta_x);
|
||||||
|
void CameraSelectionZoom (float delta_y);
|
||||||
|
void CameraPan (float delta_x);
|
||||||
|
void CameraPitch (float delta_y);
|
||||||
|
void CameraYaw (float delta_x);
|
|
@ -0,0 +1,322 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Car.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This creates the little two-triangle cars and moves them around the map.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define DEAD_ZONE 200
|
||||||
|
#define STUCK_TIME 230
|
||||||
|
#define UPDATE_INTERVAL 50 //milliseconds
|
||||||
|
#define MOVEMENT_SPEED 0.61f
|
||||||
|
#define CAR_SIZE 3.0f
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include <gl\glu.h>
|
||||||
|
#include <gl\glaux.h>
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
#include "building.h"
|
||||||
|
#include "car.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "world.h"
|
||||||
|
#include "visible.h"
|
||||||
|
|
||||||
|
static GLvector direction[] =
|
||||||
|
{
|
||||||
|
0.0f, 0.0f, -1.0f,
|
||||||
|
1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
-1.0f, 0.0f, 0.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dangles[] = { 0, 90, 180, 270};
|
||||||
|
|
||||||
|
static GLvector2 angles[360];
|
||||||
|
static bool angles_done;
|
||||||
|
static unsigned char carmap[WORLD_SIZE][WORLD_SIZE];
|
||||||
|
static CCar* head;
|
||||||
|
static unsigned next_update;
|
||||||
|
static int count;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CarCount ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CarClear ()
|
||||||
|
{
|
||||||
|
|
||||||
|
CCar* c;
|
||||||
|
|
||||||
|
for (c = head; c; c = c->m_next)
|
||||||
|
c->Park ();
|
||||||
|
ZeroMemory (carmap, sizeof (carmap));
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CarRender ()
|
||||||
|
{
|
||||||
|
|
||||||
|
CCar* c;
|
||||||
|
|
||||||
|
if (!angles_done) {
|
||||||
|
for (int i = 0 ;i < 360; i++) {
|
||||||
|
angles[i].x = cosf ((float)i * DEGREES_TO_RADIANS) * CAR_SIZE;
|
||||||
|
angles[i].y = sinf ((float)i * DEGREES_TO_RADIANS) * CAR_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glDepthMask (false);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glBlendFunc (GL_ONE, GL_ONE);
|
||||||
|
glBindTexture (GL_TEXTURE_2D, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_HEADLIGHT));
|
||||||
|
for (c = head; c; c = c->m_next)
|
||||||
|
c->Render ();
|
||||||
|
glDepthMask (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CarUpdate ()
|
||||||
|
{
|
||||||
|
|
||||||
|
CCar* c;
|
||||||
|
unsigned now;
|
||||||
|
|
||||||
|
if (!TextureReady () || !EntityReady ())
|
||||||
|
return;
|
||||||
|
now = GetTickCount ();
|
||||||
|
if (next_update > now)
|
||||||
|
return;
|
||||||
|
next_update = now + UPDATE_INTERVAL;
|
||||||
|
for (c = head; c; c = c->m_next)
|
||||||
|
c->Update ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CCar::CCar ()
|
||||||
|
{
|
||||||
|
|
||||||
|
m_ready = false;
|
||||||
|
m_next = head;
|
||||||
|
head = this;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool CCar::TestPosition (int row, int col)
|
||||||
|
{
|
||||||
|
|
||||||
|
//test the given position and see if it's already occupied
|
||||||
|
if (carmap[row][col])
|
||||||
|
return false;
|
||||||
|
//now make sure that the lane is going the right direction
|
||||||
|
if (WorldCell (row, col) != WorldCell (m_row, m_col))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CCar::Update (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
int new_row, new_col;
|
||||||
|
GLvector old_pos;
|
||||||
|
GLvector camera;
|
||||||
|
|
||||||
|
//If the car isn't ready, place it on the map and get it moving
|
||||||
|
camera = CameraPosition ();
|
||||||
|
if (!m_ready) {
|
||||||
|
//if the car isn't ready, we need to place it somewhere on the map
|
||||||
|
m_row = DEAD_ZONE + RandomVal (WORLD_SIZE - DEAD_ZONE * 2);
|
||||||
|
m_col = DEAD_ZONE + RandomVal (WORLD_SIZE - DEAD_ZONE * 2);
|
||||||
|
//if there is already a car here, forget it.
|
||||||
|
if (carmap[m_row][m_col] > 0)
|
||||||
|
return;
|
||||||
|
//if this spot is not a road, forget it
|
||||||
|
if (!(WorldCell (m_row, m_col) & CLAIM_ROAD))
|
||||||
|
return;
|
||||||
|
if (!Visible (glVector ((float)m_row, 0.0f, (float)m_col)))
|
||||||
|
return;
|
||||||
|
//good spot. place the car
|
||||||
|
m_position = glVector ((float)m_row, 0.1f, (float)m_col);
|
||||||
|
m_drive_position = m_position;
|
||||||
|
m_ready = true;
|
||||||
|
if (WorldCell (m_row, m_col) & MAP_ROAD_NORTH)
|
||||||
|
m_direction = NORTH;
|
||||||
|
if (WorldCell (m_row, m_col) & MAP_ROAD_EAST)
|
||||||
|
m_direction = EAST;
|
||||||
|
if (WorldCell (m_row, m_col) & MAP_ROAD_SOUTH)
|
||||||
|
m_direction = SOUTH;
|
||||||
|
if (WorldCell (m_row, m_col) & MAP_ROAD_WEST)
|
||||||
|
m_direction = WEST;
|
||||||
|
m_drive_angle = dangles[m_direction];
|
||||||
|
m_max_speed = (float)(4 + RandomVal (6)) / 10.0f;
|
||||||
|
m_speed = 0.0f;
|
||||||
|
m_change = 3;
|
||||||
|
m_stuck = 0;
|
||||||
|
carmap[m_row][m_col]++;
|
||||||
|
}
|
||||||
|
//take the car off the map and move it
|
||||||
|
carmap[m_row][m_col]--;
|
||||||
|
old_pos = m_position;
|
||||||
|
m_speed += m_max_speed * 0.05f;
|
||||||
|
m_speed = MIN (m_speed, m_max_speed);
|
||||||
|
m_position += direction[m_direction] * MOVEMENT_SPEED * m_speed;
|
||||||
|
//If the car has moved out of view, there's no need to keep simulating it.
|
||||||
|
if (!Visible (glVector ((float)m_row, 0.0f, (float)m_col)))
|
||||||
|
m_ready = false;
|
||||||
|
//if the car is far away, remove it. We use manhattan units because buildings almost always
|
||||||
|
//block views of cars on the diagonal.
|
||||||
|
if (fabs (camera.x - m_position.x) + fabs (camera.z - m_position.z) > RenderFogDistance ())
|
||||||
|
m_ready = false;
|
||||||
|
//if the car gets too close to the edge of the map, take it out of play
|
||||||
|
if (m_position.x < DEAD_ZONE || m_position.x > (WORLD_SIZE - DEAD_ZONE))
|
||||||
|
m_ready = false;
|
||||||
|
if (m_position.z < DEAD_ZONE || m_position.z > (WORLD_SIZE - DEAD_ZONE))
|
||||||
|
m_ready = false;
|
||||||
|
if (m_stuck >= STUCK_TIME)
|
||||||
|
m_ready = false;
|
||||||
|
if (!m_ready)
|
||||||
|
return;
|
||||||
|
//Check the new position and make sure its not in another car
|
||||||
|
new_row = (int)m_position.x;
|
||||||
|
new_col = (int)m_position.z;
|
||||||
|
if (new_row != m_row || new_col != m_col) {
|
||||||
|
//see if the new position places us on top of another car
|
||||||
|
if (carmap[new_row][new_col]) {
|
||||||
|
m_position = old_pos;
|
||||||
|
m_speed = 0.0f;
|
||||||
|
m_stuck++;
|
||||||
|
} else {
|
||||||
|
//look at the new position and decide if we're heading towards or away from the camera
|
||||||
|
m_row = new_row;
|
||||||
|
m_col = new_col;
|
||||||
|
m_change--;
|
||||||
|
m_stuck = 0;
|
||||||
|
if (m_direction == NORTH)
|
||||||
|
m_front = camera.z < m_position.z;
|
||||||
|
else if (m_direction == SOUTH)
|
||||||
|
m_front = camera.z > m_position.z;
|
||||||
|
else if (m_direction == EAST)
|
||||||
|
m_front = camera.x > m_position.x;
|
||||||
|
else
|
||||||
|
m_front = camera.x < m_position.x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_drive_position = (m_drive_position + m_position) / 2.0f;
|
||||||
|
//place the car back on the map
|
||||||
|
carmap[m_row][m_col]++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CCar::Render ()
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector pos;
|
||||||
|
int angle;
|
||||||
|
int turn;
|
||||||
|
|
||||||
|
if (!m_ready)
|
||||||
|
return;
|
||||||
|
if (!Visible (m_drive_position))
|
||||||
|
return;
|
||||||
|
if (m_front)
|
||||||
|
glColor3f (1, 1, 0.8f);
|
||||||
|
else
|
||||||
|
glColor3f (1, 0.2f, 0);
|
||||||
|
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
|
||||||
|
angle = dangles[m_direction];
|
||||||
|
pos = m_drive_position;//
|
||||||
|
angle = 360 - (int)MathAngle (m_position.x, m_position.z, pos.x, pos.z);
|
||||||
|
angle %= 360;
|
||||||
|
turn = (int)MathAngleDifference ((float)m_drive_angle, (float)angle);
|
||||||
|
m_drive_angle += SIGN (turn);
|
||||||
|
pos += glVector (0.5f, 0.0f, 0.5f);
|
||||||
|
|
||||||
|
|
||||||
|
glTexCoord2f (0, 0);
|
||||||
|
glVertex3f (pos.x + angles[angle].x, -CAR_SIZE, pos.z + angles[angle].y);
|
||||||
|
glTexCoord2f (1, 0);
|
||||||
|
glVertex3f (pos.x - angles[angle].x, -CAR_SIZE, pos.z - angles[angle].y);
|
||||||
|
glTexCoord2f (1, 1);
|
||||||
|
glVertex3f (pos.x - angles[angle].x, CAR_SIZE, pos.z - angles[angle].y);
|
||||||
|
glTexCoord2f (0, 1);
|
||||||
|
glVertex3f (pos.x + angles[angle].x, CAR_SIZE, pos.z + angles[angle].y);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
glVertex3f (m_position.x, m_position.y, m_position.z);
|
||||||
|
glVertex3f (m_position.x, m_position.y, m_position.z + 1);
|
||||||
|
glVertex3f (m_position.x + 1, m_position.y, m_position.z + 1);
|
||||||
|
glVertex3f (m_position.x + 1, m_position.y, m_position.z);
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
glTexCoord2f (0, 0);
|
||||||
|
glVertex3f (m_position.x, m_position.y, m_position.z + 0.2f);
|
||||||
|
glTexCoord2f (0, 2);
|
||||||
|
glVertex3f (m_position.x, m_position.y, m_position.z + 1 - 0.2f);
|
||||||
|
glTexCoord2f (1, 2);
|
||||||
|
glVertex3f (m_position.x + 1, m_position.y, m_position.z + 1 - 0.2f);
|
||||||
|
glTexCoord2f (1, 0);
|
||||||
|
glVertex3f (m_position.x + 1, m_position.y, m_position.z + 0.2f);
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
class CCar
|
||||||
|
{
|
||||||
|
GLvector m_position;
|
||||||
|
GLvector m_drive_position;
|
||||||
|
bool m_ready;
|
||||||
|
bool m_front;
|
||||||
|
int m_drive_angle;
|
||||||
|
int m_row;
|
||||||
|
int m_col;
|
||||||
|
int m_direction;
|
||||||
|
int m_change;
|
||||||
|
int m_stuck;
|
||||||
|
float m_speed;
|
||||||
|
float m_max_speed;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CCar ();
|
||||||
|
bool TestPosition (int row, int col);
|
||||||
|
void Render ();
|
||||||
|
void Update ();
|
||||||
|
void Park () { m_ready = false;}
|
||||||
|
class CCar* m_next;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void CarClear ();
|
||||||
|
int CarCount ();
|
||||||
|
void CarRender ();
|
||||||
|
void CarUpdate ();
|
||||||
|
|
|
@ -0,0 +1,285 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Deco.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This handles building and rendering decoration objects - infrastructure &
|
||||||
|
such around the city.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define LOGO_OFFSET 0.2f //How far a logo sticks out from the given surface
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include <gl\glu.h>
|
||||||
|
#include <gl\glaux.h>
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
#include "deco.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "world.h"
|
||||||
|
#include "visible.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CDeco::CDeco ()
|
||||||
|
{
|
||||||
|
|
||||||
|
_mesh = new CMesh ();
|
||||||
|
_use_alpha = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CDeco::Render ()
|
||||||
|
{
|
||||||
|
|
||||||
|
glColor3fv (&_color.red);
|
||||||
|
_mesh->Render ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CDeco::RenderFlat (bool colored)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool CDeco::Alpha ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return _use_alpha;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CDeco::PolyCount ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return _mesh->PolyCount ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
unsigned CDeco::Texture ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return _texture;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CDeco::CreateRadioTower (GLvector pos, float height)
|
||||||
|
{
|
||||||
|
|
||||||
|
CLight* l;
|
||||||
|
float offset;
|
||||||
|
GLvertex v;
|
||||||
|
int index_list[] = {0,1,2,3,4,5};
|
||||||
|
|
||||||
|
offset = height / 15.0f;
|
||||||
|
_center = pos;
|
||||||
|
_use_alpha = true;
|
||||||
|
//Radio tower
|
||||||
|
v.position = glVector (_center.x, _center.y + height, _center.z); v.uv = glVector (0,1);
|
||||||
|
_mesh->VertexAdd (v);
|
||||||
|
v.position = glVector (_center.x - offset, _center.y, _center.z - offset); v.uv = glVector (1,0);
|
||||||
|
_mesh->VertexAdd (v);
|
||||||
|
v.position = glVector (_center.x + offset, _center.y, _center.z - offset); v.uv = glVector (0,0);
|
||||||
|
_mesh->VertexAdd (v);
|
||||||
|
v.position = glVector (_center.x + offset, _center.y, _center.z + offset); v.uv = glVector (1,0);
|
||||||
|
_mesh->VertexAdd (v);
|
||||||
|
v.position = glVector (_center.x - offset, _center.y, _center.z + offset); v.uv = glVector (0,0);
|
||||||
|
_mesh->VertexAdd (v);
|
||||||
|
v.position = glVector (_center.x - offset, _center.y, _center.z - offset); v.uv = glVector (1,0);
|
||||||
|
_mesh->VertexAdd (v);
|
||||||
|
_mesh->FanAdd (&index_list[0], 6);
|
||||||
|
l = new CLight (glVector (_center.x, _center.y + height + 1.0f, _center.z), glRgba (255,192,160), 1);
|
||||||
|
l->Blink ();
|
||||||
|
_texture = TextureId (TEXTURE_LATTICE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CDeco::CreateLogo (GLvector2 start, GLvector2 end, float bottom, int seed, GLrgba color)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex p;
|
||||||
|
int index_list[] = {0,1,3,2};
|
||||||
|
float u1, u2, v1, v2;
|
||||||
|
float top;
|
||||||
|
float height, length;
|
||||||
|
GLvector2 center2d;
|
||||||
|
GLvector to;
|
||||||
|
GLvector out;
|
||||||
|
int logo_index;
|
||||||
|
|
||||||
|
_use_alpha = true;
|
||||||
|
_color = color;
|
||||||
|
logo_index = seed % LOGO_ROWS;
|
||||||
|
to = glVector (start.x, 0.0f, start.y) - glVector (end.x, 0.0f, end.y);
|
||||||
|
to = glVectorNormalize (to);
|
||||||
|
out = glVectorCrossProduct (glVector (0.0f, 1.0f, 0.0f), to) * LOGO_OFFSET;
|
||||||
|
center2d = (start + end) / 2;
|
||||||
|
_center = glVector (center2d.x, bottom, center2d.y);
|
||||||
|
length = glVectorLength (start - end);
|
||||||
|
height = (length / 8.0f) * 1.5f;
|
||||||
|
top = bottom + height;
|
||||||
|
u1 = 0.0f;
|
||||||
|
u2 = 0.5f;//We actually only use the left half of the texture
|
||||||
|
v1 = (float)logo_index / LOGO_ROWS;
|
||||||
|
v2 = v1 + (1.0f / LOGO_ROWS);
|
||||||
|
p.position = glVector (start.x, bottom, start.y) + out; p.uv = glVector (u1,v1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (end.x, bottom, end.y) + out; p.uv = glVector (u2, v1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (end.x, top, end.y) + out; p.uv = glVector (u2, v2);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (start.x, top, start.y) + out; p.uv = glVector (u1, v2);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
_mesh->QuadStripAdd (&index_list[0], 4);
|
||||||
|
_texture = TextureId (TEXTURE_LOGOS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CDeco::CreateLightStrip (float x, float z, float width, float depth, float height, GLrgba color)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex p;
|
||||||
|
int index_list1[] = {0,1,3,2};
|
||||||
|
int index_list2[] = {4,5,7,6};
|
||||||
|
float u, v;
|
||||||
|
|
||||||
|
_color = color;
|
||||||
|
_use_alpha = true;
|
||||||
|
_center = glVector (x + width / 2, height, z + depth / 2);
|
||||||
|
if (width < depth) {
|
||||||
|
u = 1.0f;
|
||||||
|
v = (float)((int)(depth / width));
|
||||||
|
} else {
|
||||||
|
v = 1.0f;
|
||||||
|
u = (float)((int)(width / depth));
|
||||||
|
}
|
||||||
|
//u = MAX (width, 1);
|
||||||
|
//v = MAX (depth, 1);
|
||||||
|
_texture = TextureId (TEXTURE_LIGHT);
|
||||||
|
p.position = glVector (x, height, z); p.uv = glVector (0.0f, 0.0f);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x, height, z + depth); p.uv = glVector (0.0f, v);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x + width, height, z + depth); p.uv = glVector (u, v);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x + width, height, z); p.uv = glVector (u, 0.0f);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
|
||||||
|
p.position = glVector (x - 1, height, z - 1); p.uv = glVector (0, 0);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x - 1, height, z + depth + 1); p.uv = glVector (0, 1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x + width + 1, height, z + depth + 1); p.uv = glVector (1, 1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
p.position = glVector (x + width + 1, height, z - 1); p.uv = glVector (1, 0);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
|
||||||
|
_mesh->QuadStripAdd (&index_list1[0], 4);
|
||||||
|
//_mesh->QuadStripAdd (&index_list2[0], 4);
|
||||||
|
_mesh->Compile ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CDeco::CreateLightTrim (GLvector* chain, int count, float height, int seed, GLrgba color)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex p;
|
||||||
|
GLvector to;
|
||||||
|
GLvector out;
|
||||||
|
int i;
|
||||||
|
int index;
|
||||||
|
int prev, next;
|
||||||
|
float u, v1, v2;
|
||||||
|
float row;
|
||||||
|
int* index_list;
|
||||||
|
|
||||||
|
_color = color;
|
||||||
|
_center = glVector (0.0f, 0.0f, 0.0f);
|
||||||
|
index_list = new int[count * 2 + 2];
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
_center += chain[i];
|
||||||
|
_center /= (float)count;
|
||||||
|
row = (float)(seed % TRIM_ROWS);
|
||||||
|
v1 = row * TRIM_SIZE;
|
||||||
|
v2 = (row + 1.0f) * TRIM_SIZE;
|
||||||
|
index = 0;
|
||||||
|
u = 0.0f;
|
||||||
|
for (i = 0; i < count + 1; i++) {
|
||||||
|
if (i)
|
||||||
|
u += glVectorLength (chain[i % count] - p.position) * 0.1f;
|
||||||
|
//Add the bottom point
|
||||||
|
prev = i - 1;
|
||||||
|
if (prev < 0)
|
||||||
|
prev = count + prev;
|
||||||
|
next = (i + 1) % count;
|
||||||
|
to = glVectorNormalize (chain[next] - chain[prev]);
|
||||||
|
out = glVectorCrossProduct (glVector (0.0f, 1.0f, 0.0f), to) * LOGO_OFFSET;
|
||||||
|
p.position = chain[i % count] + out; p.uv = glVector (u, v2);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
index_list[index] = index;
|
||||||
|
index++;
|
||||||
|
//Top point
|
||||||
|
p.position.y += height;p.uv = glVector (u, v1);
|
||||||
|
_mesh->VertexAdd (p);
|
||||||
|
index_list[index] = index;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
_mesh->QuadStripAdd (index_list, index);
|
||||||
|
delete index_list;
|
||||||
|
_texture = TextureId (TEXTURE_TRIM);
|
||||||
|
_mesh->Compile ();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef ENTITY
|
||||||
|
#include "entity.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CDeco : CEntity
|
||||||
|
{
|
||||||
|
// CDeco* _next;
|
||||||
|
GLrgba _color;
|
||||||
|
class CMesh* _mesh;
|
||||||
|
int _type;
|
||||||
|
unsigned _texture;
|
||||||
|
bool _use_alpha;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CDeco ();
|
||||||
|
void CreateLogo (GLvector2 start, GLvector2 end, float base, int seed, GLrgba color);
|
||||||
|
void CreateLightStrip (float x, float z, float width, float depth, float height, GLrgba color);
|
||||||
|
void CreateLightTrim (GLvector* chain, int count, float height, int seed, GLrgba color);
|
||||||
|
void CreateRadioTower (GLvector pos, float height);
|
||||||
|
void Render (void);
|
||||||
|
void RenderFlat (bool colored);
|
||||||
|
bool Alpha ();
|
||||||
|
int PolyCount ();
|
||||||
|
|
||||||
|
unsigned Texture ();
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,412 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Entity.cpp
|
||||||
|
|
||||||
|
Copyright (c) 2005 Shamus Young
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
An entity is any renderable stationary object in the world. This is an
|
||||||
|
abstract class. This module gathers up the Entities, sorts them by
|
||||||
|
texture use and location, and then stores them in OpenGL render lists
|
||||||
|
for faster rendering.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
|
#include "entity.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "world.h"
|
||||||
|
#include "visible.h"
|
||||||
|
|
||||||
|
struct entity
|
||||||
|
{
|
||||||
|
CEntity* object;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct cell
|
||||||
|
{
|
||||||
|
unsigned list_textured;
|
||||||
|
unsigned list_flat;
|
||||||
|
unsigned list_flat_wireframe;
|
||||||
|
unsigned list_alpha;
|
||||||
|
GLvector pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
static cell cell_list[GRID_SIZE][GRID_SIZE];
|
||||||
|
static int entity_count;
|
||||||
|
static entity* entity_list;
|
||||||
|
static bool sorted;
|
||||||
|
static bool compiled;
|
||||||
|
static int polycount;
|
||||||
|
static int compile_x;
|
||||||
|
static int compile_y;
|
||||||
|
static int compile_count;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int do_compare (const void *arg1, const void *arg2 )
|
||||||
|
{
|
||||||
|
|
||||||
|
struct entity* e1 = (struct entity*)arg1;
|
||||||
|
struct entity* e2 = (struct entity*)arg2;
|
||||||
|
|
||||||
|
if (e1->object->Alpha () && !e2->object->Alpha ())
|
||||||
|
return 1;
|
||||||
|
if (!e1->object->Alpha () && e2->object->Alpha ())
|
||||||
|
return -1;
|
||||||
|
if (e1->object->Texture () > e2->object->Texture ())
|
||||||
|
return 1;
|
||||||
|
else if (e1->object->Texture () < e2->object->Texture ())
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void add (CEntity* b)
|
||||||
|
{
|
||||||
|
|
||||||
|
entity_list = (entity*)realloc (entity_list, sizeof (entity) * (entity_count + 1));
|
||||||
|
entity_list[entity_count].object = b;
|
||||||
|
entity_count++;
|
||||||
|
polycount = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void do_compile ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
if (compiled)
|
||||||
|
return;
|
||||||
|
x = compile_x;
|
||||||
|
y = compile_y;
|
||||||
|
//Changing textures is pretty expensive, and thus sorting the entites so that
|
||||||
|
//they are grouped by texture used can really improve framerate.
|
||||||
|
//qsort (entity_list, entity_count, sizeof (struct entity), do_compare);
|
||||||
|
//sorted = true;
|
||||||
|
//Now group entites on the grid
|
||||||
|
//make a list for the textured objects in this region
|
||||||
|
if (!cell_list[x][y].list_textured)
|
||||||
|
cell_list[x][y].list_textured = glGenLists(1);
|
||||||
|
glNewList (cell_list[x][y].list_textured, GL_COMPILE);
|
||||||
|
cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);
|
||||||
|
for (i = 0; i < entity_count; i++) {
|
||||||
|
GLvector pos = entity_list[i].object->Center ();
|
||||||
|
if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, entity_list[i].object->Texture ());
|
||||||
|
entity_list[i].object->Render ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEndList();
|
||||||
|
|
||||||
|
//Make a list of flat-color stuff (A/C units, ledges, roofs, etc.)
|
||||||
|
if (!cell_list[x][y].list_flat)
|
||||||
|
cell_list[x][y].list_flat = glGenLists(1);
|
||||||
|
glNewList (cell_list[x][y].list_flat, GL_COMPILE);
|
||||||
|
glEnable (GL_CULL_FACE);
|
||||||
|
cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);
|
||||||
|
for (i = 0; i < entity_count; i++) {
|
||||||
|
GLvector pos = entity_list[i].object->Center ();
|
||||||
|
if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {
|
||||||
|
entity_list[i].object->RenderFlat (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEndList();
|
||||||
|
//Now a list of flat-colored stuff that will be wireframe friendly
|
||||||
|
if (!cell_list[x][y].list_flat_wireframe)
|
||||||
|
cell_list[x][y].list_flat_wireframe = glGenLists(1);
|
||||||
|
glNewList (cell_list[x][y].list_flat_wireframe, GL_COMPILE);
|
||||||
|
glEnable (GL_CULL_FACE);
|
||||||
|
cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);
|
||||||
|
for (i = 0; i < entity_count; i++) {
|
||||||
|
GLvector pos = entity_list[i].object->Center ();
|
||||||
|
if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {
|
||||||
|
entity_list[i].object->RenderFlat (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEndList();
|
||||||
|
//Now a list of stuff to be alpha-blended, and thus rendered last
|
||||||
|
if (!cell_list[x][y].list_alpha)
|
||||||
|
cell_list[x][y].list_alpha = glGenLists(1);
|
||||||
|
glNewList (cell_list[x][y].list_alpha, GL_COMPILE);
|
||||||
|
cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);
|
||||||
|
glDepthMask (false);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
for (i = 0; i < entity_count; i++) {
|
||||||
|
GLvector pos = entity_list[i].object->Center ();
|
||||||
|
if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && entity_list[i].object->Alpha ()) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, entity_list[i].object->Texture ());
|
||||||
|
entity_list[i].object->Render ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glDepthMask (true);
|
||||||
|
glEndList();
|
||||||
|
|
||||||
|
//now walk the grid
|
||||||
|
compile_x++;
|
||||||
|
if (compile_x == GRID_SIZE) {
|
||||||
|
compile_x = 0;
|
||||||
|
compile_y++;
|
||||||
|
if (compile_y == GRID_SIZE)
|
||||||
|
compiled = true;
|
||||||
|
}
|
||||||
|
compile_count++;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool EntityReady ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return compiled;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float EntityProgress ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return (float)compile_count / (GRID_SIZE * GRID_SIZE);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void EntityUpdate ()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!TextureReady ()) {
|
||||||
|
sorted = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!sorted) {
|
||||||
|
qsort (entity_list, entity_count, sizeof (struct entity), do_compare);
|
||||||
|
sorted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!compiled)
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
do_compile ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void xEntityRender ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
bool wireframe;
|
||||||
|
int polymode[2];
|
||||||
|
|
||||||
|
glGetIntegerv (GL_POLYGON_MODE, &polymode[0]);
|
||||||
|
wireframe = polymode[0] != GL_FILL;
|
||||||
|
for (i = 0; i < entity_count; i++) {
|
||||||
|
if (Visible (entity_list[i].object->Center ())) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, entity_list[i].object->Texture ());
|
||||||
|
entity_list[i].object->Render ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glColor3f (0,0,0);
|
||||||
|
for (i = 0; i < entity_count; i++) {
|
||||||
|
if (Visible (entity_list[i].object->Center ())) {
|
||||||
|
entity_list[i].object->RenderFlat (wireframe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void EntityRender ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int polymode[2];
|
||||||
|
bool wireframe;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
//Draw all textured objects
|
||||||
|
glGetIntegerv (GL_POLYGON_MODE, &polymode[0]);
|
||||||
|
wireframe = polymode[0] != GL_FILL;
|
||||||
|
if (RenderFlat ())
|
||||||
|
glDisable (GL_TEXTURE_2D);
|
||||||
|
for (x = 0; x < GRID_SIZE; x++) {
|
||||||
|
for (y = 0; y < GRID_SIZE; y++) {
|
||||||
|
if (Visible (x,y))
|
||||||
|
glCallList (cell_list[x][y].list_textured);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//draw all flat colored objects
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glColor3f (0, 0, 0);
|
||||||
|
for (x = 0; x < GRID_SIZE; x++) {
|
||||||
|
for (y = 0; y < GRID_SIZE; y++) {
|
||||||
|
if (Visible (x, y)) {
|
||||||
|
if (wireframe)
|
||||||
|
glCallList (cell_list[x][y].list_flat_wireframe);
|
||||||
|
else
|
||||||
|
glCallList (cell_list[x][y].list_flat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//draw all alpha-blended objects
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glColor3f (0, 0, 0);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
for (x = 0; x < GRID_SIZE; x++) {
|
||||||
|
for (y = 0; y < GRID_SIZE; y++) {
|
||||||
|
if (Visible (x,y)) {
|
||||||
|
glCallList (cell_list[x][y].list_alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void EntityClear ()
|
||||||
|
{
|
||||||
|
|
||||||
|
for (int i = 0; i < entity_count; i++) {
|
||||||
|
delete entity_list[i].object;
|
||||||
|
}
|
||||||
|
if (entity_list)
|
||||||
|
free (entity_list);
|
||||||
|
entity_list = NULL;
|
||||||
|
entity_count = 0;
|
||||||
|
compile_x = 0;
|
||||||
|
compile_y = 0;
|
||||||
|
compile_count = 0;
|
||||||
|
compiled = false;
|
||||||
|
sorted = false;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for (x = 0; x < GRID_SIZE; x++) {
|
||||||
|
for (y = 0; y < GRID_SIZE; y++) {
|
||||||
|
glNewList (cell_list[x][y].list_textured, GL_COMPILE);
|
||||||
|
glEndList();
|
||||||
|
glNewList (cell_list[x][y].list_alpha, GL_COMPILE);
|
||||||
|
glEndList();
|
||||||
|
glNewList (cell_list[x][y].list_flat_wireframe, GL_COMPILE);
|
||||||
|
glEndList();
|
||||||
|
glNewList (cell_list[x][y].list_flat, GL_COMPILE);
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int EntityCount ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return entity_count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void EntityInit (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int EntityPolyCount (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!sorted)
|
||||||
|
return 0;
|
||||||
|
if (polycount)
|
||||||
|
return polycount;
|
||||||
|
for (int i = 0; i < entity_count; i++)
|
||||||
|
polycount += entity_list[i].object->PolyCount ();
|
||||||
|
return polycount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CEntity::CEntity (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
add (this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEntity::Render (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEntity::RenderFlat (bool wireframe)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEntity::Update (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef TYPES
|
||||||
|
#include "glTypes.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ENTITY
|
||||||
|
|
||||||
|
#define ENTITY
|
||||||
|
|
||||||
|
class CEntity
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
protected:
|
||||||
|
|
||||||
|
GLvector _center;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CEntity (void);
|
||||||
|
GLvector Center () { return _center; }
|
||||||
|
virtual void Render (void);
|
||||||
|
virtual void RenderFlat (bool wirefame);
|
||||||
|
virtual unsigned Texture () { return 0; }
|
||||||
|
virtual void Update (void);
|
||||||
|
virtual bool Alpha () { return false; }
|
||||||
|
virtual int PolyCount () { return 0; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void EntityClear ();
|
||||||
|
int EntityCount (void);
|
||||||
|
float EntityProgress ();
|
||||||
|
bool EntityReady ();
|
||||||
|
void EntityRender (void);
|
||||||
|
void EntityUpdate (void);
|
||||||
|
int EntityPolyCount (void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Ini.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This takes various types of data and dumps them into a predefined ini file.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define FORMAT_VECTOR "%f %f %f"
|
||||||
|
#define MAX_RESULT 256
|
||||||
|
#define FORMAT_FLOAT "%1.2f"
|
||||||
|
#define INI_FILE ".\\" APP ".ini"
|
||||||
|
#define SECTION "Settings"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
#include "ini.h"
|
||||||
|
#include "win.h"
|
||||||
|
|
||||||
|
static char result[MAX_RESULT];
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int IniInt (char* entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = GetPrivateProfileInt (SECTION, entry, 0, INI_FILE);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void IniIntSet (char* entry, int val)
|
||||||
|
{
|
||||||
|
|
||||||
|
char buf[20];
|
||||||
|
|
||||||
|
sprintf (buf, "%d", val);
|
||||||
|
WritePrivateProfileString (SECTION, entry, buf, INI_FILE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float IniFloat (char* entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
float f;
|
||||||
|
|
||||||
|
GetPrivateProfileString (SECTION, entry, "", result, MAX_RESULT, INI_FILE);
|
||||||
|
f = (float)atof (result);
|
||||||
|
return f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void IniFloatSet (char* entry, float val)
|
||||||
|
{
|
||||||
|
|
||||||
|
char buf[20];
|
||||||
|
|
||||||
|
sprintf (buf, FORMAT_FLOAT, val);
|
||||||
|
WritePrivateProfileString (SECTION, entry, buf, INI_FILE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
char* IniString (char* entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
GetPrivateProfileString (SECTION, entry, "", result, MAX_RESULT, INI_FILE);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void IniStringSet (char* entry, char* val)
|
||||||
|
{
|
||||||
|
|
||||||
|
WritePrivateProfileString (SECTION, entry, val, INI_FILE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void IniVectorSet (char* entry, GLvector v)
|
||||||
|
{
|
||||||
|
|
||||||
|
sprintf (result, FORMAT_VECTOR, v.x, v.y, v.z);
|
||||||
|
WritePrivateProfileString (SECTION, entry, result, INI_FILE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector IniVector (char* entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector v;
|
||||||
|
|
||||||
|
v.x = v.y = v.z = 0.0f;
|
||||||
|
GetPrivateProfileString (SECTION, entry, "0 0 0", result, MAX_RESULT, INI_FILE);
|
||||||
|
sscanf (result, FORMAT_VECTOR, &v.x, &v.y, &v.z);
|
||||||
|
return v;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
int IniInt (char* entry);
|
||||||
|
void IniIntSet (char* entry, int val);
|
||||||
|
float IniFloat (char* entry);
|
||||||
|
void IniFloatSet (char* entry, float val);
|
||||||
|
char* IniString (char* entry);
|
||||||
|
void IniStringSet (char* entry, char* val);
|
||||||
|
void IniVectorSet (char* entry, GLvector v);
|
||||||
|
GLvector IniVector (char* entry);
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Light.cpp
|
||||||
|
|
||||||
|
2006 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This tracks and renders the light sources. (Note that they do not really
|
||||||
|
CAST light in the OpenGL sense of the world, these are just simple panels.)
|
||||||
|
These are NOT subclassed to entities because these are dynamic. Some lights
|
||||||
|
blink, and thus they can't go into the fixed render lists managed by
|
||||||
|
Entity.cpp.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define MAX_SIZE 5
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include <gl\glu.h>
|
||||||
|
#include <gl\glaux.h>
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "visible.h"
|
||||||
|
|
||||||
|
static GLvector2 angles[5][360];
|
||||||
|
static CLight* head;
|
||||||
|
static bool angles_done;
|
||||||
|
static int count;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void LightClear ()
|
||||||
|
{
|
||||||
|
|
||||||
|
CLight* l;
|
||||||
|
|
||||||
|
while (head) {
|
||||||
|
l = head;
|
||||||
|
head = l->_next;
|
||||||
|
delete l;
|
||||||
|
}
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int LightCount ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void LightRender ()
|
||||||
|
{
|
||||||
|
|
||||||
|
CLight* l;
|
||||||
|
|
||||||
|
if (!angles_done) {
|
||||||
|
for (int size = 0; size < MAX_SIZE; size++) {
|
||||||
|
for (int i = 0 ;i < 360; i++) {
|
||||||
|
angles[size][i].x = cosf ((float)i * DEGREES_TO_RADIANS) * ((float)size + 0.5f);
|
||||||
|
angles[size][i].y = sinf ((float)i * DEGREES_TO_RADIANS) * ((float)size + 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glDepthMask (false);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glBlendFunc (GL_ONE, GL_ONE);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_LIGHT));
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
for (l = head; l; l = l->_next)
|
||||||
|
l->Render ();
|
||||||
|
glEnd ();
|
||||||
|
glDepthMask (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CLight::CLight (GLvector pos, GLrgba color, int size)
|
||||||
|
{
|
||||||
|
|
||||||
|
_position = pos;
|
||||||
|
_color = color * 0.5f;
|
||||||
|
_size = CLAMP (size, 0, (MAX_SIZE - 1));
|
||||||
|
_vert_size = (float)_size + 0.5f;
|
||||||
|
_flat_size = _vert_size + 0.5f;
|
||||||
|
_blink = false;
|
||||||
|
_cell_x = WORLD_TO_GRID(pos.x);
|
||||||
|
_cell_z = WORLD_TO_GRID(pos.z);
|
||||||
|
_next = head;
|
||||||
|
head = this;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CLight::Blink ()
|
||||||
|
{
|
||||||
|
|
||||||
|
_blink = true;
|
||||||
|
//we don't want blinkers to be in sync, so have them blink at
|
||||||
|
//slightly different rates. (Milliseconds)
|
||||||
|
_blink_interval = 1500 + RandomVal (500);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CLight::Render ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int angle;
|
||||||
|
GLvector pos;
|
||||||
|
GLvector camera;
|
||||||
|
GLvector camera_position;
|
||||||
|
GLvector2 offset;
|
||||||
|
|
||||||
|
if (!Visible (_cell_x, _cell_z))
|
||||||
|
return;
|
||||||
|
camera = CameraAngle ();
|
||||||
|
camera_position = CameraPosition ();
|
||||||
|
if (fabs (camera_position.x - _position.x) > RenderFogDistance ())
|
||||||
|
return;
|
||||||
|
if (fabs (camera_position.z - _position.z) > RenderFogDistance ())
|
||||||
|
return;
|
||||||
|
if (_blink && (GetTickCount () % _blink_interval) > 200)
|
||||||
|
return;
|
||||||
|
angle = (int)MathAngle (camera.y);
|
||||||
|
offset = angles[_size][angle];
|
||||||
|
pos = _position;
|
||||||
|
//m_color.alpha = 0.25f;
|
||||||
|
glColor4fv (&_color.red);
|
||||||
|
glTexCoord2f (0, 0);
|
||||||
|
glVertex3f (pos.x + offset.x, pos.y - _vert_size, pos.z + offset.y);
|
||||||
|
glTexCoord2f (0, 1);
|
||||||
|
glVertex3f (pos.x - offset.x, pos.y - _vert_size, pos.z - offset.y);
|
||||||
|
glTexCoord2f (1, 1);
|
||||||
|
glVertex3f (pos.x - offset.x, pos.y + _vert_size, pos.z - offset.y);
|
||||||
|
glTexCoord2f (1, 0);
|
||||||
|
glVertex3f (pos.x + offset.x, pos.y + _vert_size, pos.z + offset.y);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
class CLight
|
||||||
|
{
|
||||||
|
GLvector _position;
|
||||||
|
GLrgba _color;
|
||||||
|
int _size;
|
||||||
|
float _vert_size;
|
||||||
|
float _flat_size;
|
||||||
|
bool _blink;
|
||||||
|
unsigned _blink_interval;
|
||||||
|
int _cell_x;
|
||||||
|
int _cell_z;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CLight(GLvector pos, GLrgba color, int size);
|
||||||
|
class CLight* _next;
|
||||||
|
void Render ();
|
||||||
|
void Blink ();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void LightRender ();
|
||||||
|
void LightClear ();
|
||||||
|
int LightCount ();
|
|
@ -0,0 +1,15 @@
|
||||||
|
#define LIMIT_INTERVAL(interval) { static unsigned next_update; if (next_update > GetTickCount ()) return; next_update = GetTickCount () + interval;}
|
||||||
|
#define DEGREES_TO_RADIANS .017453292F
|
||||||
|
#define RADIANS_TO_DEGREES 57.29577951F
|
||||||
|
#define PI ((double)3.1415926535F)
|
||||||
|
#define PI2 PI*PI
|
||||||
|
#define GRAVITY 9.5f
|
||||||
|
#define CLAMP(a,b,c) (a < b ? b : (a > c ? c : a))
|
||||||
|
#define WRAP(x,y) ((unsigned)x % y)
|
||||||
|
#define SIGN(x) (((x) > 0) ? 1 : ((x) < 0) ? -1 : 0)
|
||||||
|
#define ABS(x) (((x) < 0 ? (-x) : (x)))
|
||||||
|
#define SMALLEST(x,y) (ABS(x) < ABS(y) ? 0 : x)
|
||||||
|
#define MIN(x,y) ((x) < (y) ? x : y)
|
||||||
|
#define MAX(x,y) ((x) > (y) ? x : y)
|
||||||
|
#define POW(x,y) (float)pow(x,y)
|
||||||
|
#define SWAP(a,b) {int temp = a;a = b; b = temp;}
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Math.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Various useful math functions.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
Keep an angle between 0 and 360
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathAngle (float angle)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (angle < 0.0f)
|
||||||
|
angle = 360.0f - (float)fmod (fabs (angle), 360.0f);
|
||||||
|
else
|
||||||
|
angle = (float)fmod (angle, 360.0f);
|
||||||
|
return angle;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
Get an angle between two given points on a grid
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathAngle (float x1, float y1, float x2, float y2)
|
||||||
|
{
|
||||||
|
|
||||||
|
float x_delta;
|
||||||
|
float z_delta;
|
||||||
|
float angle;
|
||||||
|
|
||||||
|
z_delta = (y1 - y2);
|
||||||
|
x_delta = (x1 - x2);
|
||||||
|
if (x_delta == 0) {
|
||||||
|
if (z_delta > 0)
|
||||||
|
return 0.0f;
|
||||||
|
else
|
||||||
|
return 180.0f;
|
||||||
|
}
|
||||||
|
if (fabs (x_delta) < fabs (z_delta)) {
|
||||||
|
angle = 90 - (float)atan (z_delta / x_delta) * RADIANS_TO_DEGREES;
|
||||||
|
if (x_delta < 0)
|
||||||
|
angle -= 180.0f;
|
||||||
|
} else {
|
||||||
|
angle = (float)atan (x_delta / z_delta) * RADIANS_TO_DEGREES;
|
||||||
|
if (z_delta < 0.0f)
|
||||||
|
angle += 180.0f;
|
||||||
|
}
|
||||||
|
if (angle< 0.0f)
|
||||||
|
angle += 360.0f;
|
||||||
|
return angle;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
Get distance (squared) between 2 points on a plane
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathDistance2 (float x1, float y1, float x2, float y2)
|
||||||
|
{
|
||||||
|
|
||||||
|
float dx;
|
||||||
|
float dy;
|
||||||
|
|
||||||
|
dx = x1 - x2;
|
||||||
|
dy = y1 - y2;
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
Get distance between 2 points on a plane. This is slightly slower than
|
||||||
|
MathDistance2 ()
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathDistance (float x1, float y1, float x2, float y2)
|
||||||
|
{
|
||||||
|
|
||||||
|
float dx;
|
||||||
|
float dy;
|
||||||
|
|
||||||
|
dx = x1 - x2;
|
||||||
|
dy = y1 - y2;
|
||||||
|
return (float)sqrt (dx * dx + dy * dy);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
difference between two angles
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathAngleDifference (float a1, float a2)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
float result;
|
||||||
|
|
||||||
|
result = (float)fmod (a1 - a2, 360.0);
|
||||||
|
if (result > 180.0)
|
||||||
|
return result - 360.0F;
|
||||||
|
if (result < -180.0)
|
||||||
|
return result + 360.0F;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
interpolate between two values
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathInterpolate (float n1, float n2, float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
return n1 * (1.0f - delta) + n2 * delta;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
return a scalar of 0.0 to 1.0, based an the given values position within a range
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathSmoothStep (float val, float a, float b)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (b == a)
|
||||||
|
return 0.0f;
|
||||||
|
val -= a;
|
||||||
|
val /= (b - a);
|
||||||
|
return CLAMP (val, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
Average two values
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathAverage (float n1, float n2)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (n1 + n2) / 2.0f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
This will take linear input values from 0.0 to 1.0 and convert them to
|
||||||
|
values along a curve. This could also be acomplished with sin (), but this
|
||||||
|
way avoids converting to radians and back.
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float MathScalarCurve (float val)
|
||||||
|
{
|
||||||
|
|
||||||
|
float sign;
|
||||||
|
|
||||||
|
val = (val - 0.5f) * 2.0f;
|
||||||
|
if (val < 0.0f)
|
||||||
|
sign = -1.0f;
|
||||||
|
else
|
||||||
|
sign = 1.0f;
|
||||||
|
if (val < 0.0f)
|
||||||
|
val = -val;
|
||||||
|
val = 1.0f - val;
|
||||||
|
val *= val;
|
||||||
|
val = 1.0f - val;
|
||||||
|
val *= sign;
|
||||||
|
val = (val + 1.0f) / 2.0f;
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
float MathAngle (float angle);
|
||||||
|
float MathAngle (float x1, float y1, float x2, float y2);
|
||||||
|
float MathAngleDifference (float a1, float a2);
|
||||||
|
float MathAverage (float n1, float n2);
|
||||||
|
float MathInterpolate (float n1, float n2, float delta);
|
||||||
|
float MathLine_distance (float x1, float y1, float x2, float y2, float px, float py);
|
||||||
|
float MathDistance (float x1, float y1, float x2, float y2);
|
||||||
|
float MathDistance2 (float x1, float y1, float x2, float y2);
|
||||||
|
float MathSmoothStep (float val, float a, float b);
|
||||||
|
float MathScalarCurve (float val);
|
|
@ -0,0 +1,216 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Mesh.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This class is used to make constructing objects easier. It handles
|
||||||
|
allocating vertex lists, polygon lists, and suchlike.
|
||||||
|
|
||||||
|
If you were going to implement vertex buffers, this would be the place to
|
||||||
|
do it. Take away the _vertex member variable and store verts for ALL meshes
|
||||||
|
in a common list, which could then be unloaded onto the good 'ol GPU.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include <gl\glu.h>
|
||||||
|
#include <gl\glaux.h>
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
#include "mesh.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CMesh::CMesh ()
|
||||||
|
{
|
||||||
|
|
||||||
|
_vertex_count = 0;
|
||||||
|
_triangle_count = 0;
|
||||||
|
_quad_strip_count = 0;
|
||||||
|
_fan_count = 0;
|
||||||
|
_cube_count = 0;
|
||||||
|
_polycount = 0;
|
||||||
|
_list = 0;
|
||||||
|
_compiled = false;
|
||||||
|
_vertex = NULL;
|
||||||
|
_normal = NULL;
|
||||||
|
_triangle = NULL;
|
||||||
|
_cube = NULL;
|
||||||
|
_quad_strip = NULL;
|
||||||
|
_fan = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CMesh::~CMesh ()
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
if (_vertex)
|
||||||
|
free (_vertex);
|
||||||
|
if (_normal)
|
||||||
|
free (_normal);
|
||||||
|
if (_triangle)
|
||||||
|
free (_triangle);
|
||||||
|
if (_cube)
|
||||||
|
free (_cube);
|
||||||
|
for (i = 0; i < _quad_strip_count; i++)
|
||||||
|
delete _quad_strip[i].index_list;
|
||||||
|
delete _quad_strip;
|
||||||
|
for (i = 0; i < _fan_count; i++)
|
||||||
|
delete _fan[i].index_list;
|
||||||
|
delete _fan;
|
||||||
|
if (_list)
|
||||||
|
glDeleteLists (_list, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CMesh::VertexAdd (GLvertex v)
|
||||||
|
{
|
||||||
|
|
||||||
|
_vertex = (GLvertex*)realloc (_vertex, sizeof (GLvertex) * (_vertex_count + 1));
|
||||||
|
_vertex[_vertex_count] = v;
|
||||||
|
_vertex_count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CMesh::CubeAdd (int* index)
|
||||||
|
{
|
||||||
|
|
||||||
|
_cube = (cube*)realloc (_cube, sizeof (cube) * (_cube_count + 1));
|
||||||
|
memcpy (&_cube[_cube_count].index_list[0], index, sizeof (int) * 10);
|
||||||
|
_cube_count++;
|
||||||
|
_polycount += 5;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CMesh::QuadStripAdd (int* index, int count)
|
||||||
|
{
|
||||||
|
|
||||||
|
_quad_strip = (quad_strip*)realloc (_quad_strip, sizeof (quad_strip) * (_quad_strip_count + 1));
|
||||||
|
_quad_strip[_quad_strip_count].index_list = (int*)malloc (sizeof (int) * count);
|
||||||
|
_quad_strip[_quad_strip_count].count = count;
|
||||||
|
memcpy (&_quad_strip[_quad_strip_count].index_list[0], &index[0], sizeof (int) * count);
|
||||||
|
_quad_strip_count++;
|
||||||
|
_polycount += (count - 2) / 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CMesh::FanAdd (int* index, int count)
|
||||||
|
{
|
||||||
|
|
||||||
|
_fan = (fan*)realloc (_fan, sizeof (fan) * (_fan_count + 1));
|
||||||
|
_fan[_fan_count].index_list = (int*)malloc (sizeof (int) * count);
|
||||||
|
_fan[_fan_count].count = count;
|
||||||
|
memcpy (&_fan[_fan_count].index_list[0], &index[0], sizeof (int) * count);
|
||||||
|
_fan_count++;
|
||||||
|
_polycount += count - 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CMesh::Render ()
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned i, n;
|
||||||
|
int* index;
|
||||||
|
|
||||||
|
if (_compiled) {
|
||||||
|
glCallList (_list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < _quad_strip_count; i++) {
|
||||||
|
index = &_quad_strip[i].index_list[0];
|
||||||
|
glBegin (GL_QUAD_STRIP);
|
||||||
|
for (n = 0; n < _quad_strip[i].count; n++) {
|
||||||
|
glTexCoord2fv (&_vertex[index[n]].uv.x);
|
||||||
|
glVertex3fv (&_vertex[index[n]].position.x);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
for (i = 0; i < _cube_count; i++) {
|
||||||
|
index = &_cube[i].index_list[0];
|
||||||
|
glBegin (GL_QUAD_STRIP);
|
||||||
|
for (n = 0; n < 10; n++) {
|
||||||
|
glTexCoord2fv (&_vertex[index[n]].uv.x);
|
||||||
|
glVertex3fv (&_vertex[index[n]].position.x);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glTexCoord2fv (&_vertex[index[7]].uv.x);
|
||||||
|
glVertex3fv (&_vertex[index[7]].position.x);
|
||||||
|
glVertex3fv (&_vertex[index[5]].position.x);
|
||||||
|
glVertex3fv (&_vertex[index[3]].position.x);
|
||||||
|
glVertex3fv (&_vertex[index[1]].position.x);
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glTexCoord2fv (&_vertex[index[6]].uv.x);
|
||||||
|
glVertex3fv (&_vertex[index[0]].position.x);
|
||||||
|
glVertex3fv (&_vertex[index[2]].position.x);
|
||||||
|
glVertex3fv (&_vertex[index[4]].position.x);
|
||||||
|
glVertex3fv (&_vertex[index[6]].position.x);
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
for (i = 0; i < _fan_count; i++) {
|
||||||
|
index = &_fan[i].index_list[0];
|
||||||
|
glBegin (GL_TRIANGLE_FAN);
|
||||||
|
for (n = 0; n < _fan[i].count; n++) {
|
||||||
|
glTexCoord2fv (&_vertex[index[n]].uv.x);
|
||||||
|
glVertex3fv (&_vertex[index[n]].position.x);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CMesh::Compile ()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!_list)
|
||||||
|
_list = glGenLists(1);
|
||||||
|
glNewList (_list, GL_COMPILE);
|
||||||
|
Render ();
|
||||||
|
glEndList();
|
||||||
|
_compiled = true;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
|
||||||
|
struct cube
|
||||||
|
{
|
||||||
|
int index_list[10];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct quad_strip
|
||||||
|
{
|
||||||
|
int* index_list;
|
||||||
|
unsigned count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fan
|
||||||
|
{
|
||||||
|
int* index_list;
|
||||||
|
unsigned count;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMesh ();
|
||||||
|
~CMesh ();
|
||||||
|
unsigned _vertex_count;
|
||||||
|
unsigned _triangle_count;
|
||||||
|
unsigned _cube_count;
|
||||||
|
unsigned _quad_strip_count;
|
||||||
|
unsigned _fan_count;
|
||||||
|
unsigned _normal_count;
|
||||||
|
unsigned _list;
|
||||||
|
int _polycount;
|
||||||
|
GLvertex* _vertex;
|
||||||
|
GLvector* _normal;
|
||||||
|
GLtriangle* _triangle;
|
||||||
|
cube* _cube;
|
||||||
|
quad_strip* _quad_strip;
|
||||||
|
fan* _fan;
|
||||||
|
bool _compiled;
|
||||||
|
|
||||||
|
//void TriangleRender (unsigned n);
|
||||||
|
//GLtriangle* TriangleAdd (unsigned v1, int unsigned, int unsigned);
|
||||||
|
//GLtriangle* TriangleAdd (GLtriangle c);
|
||||||
|
void NormalAdd (GLvector n);
|
||||||
|
void VertexAdd (GLvertex v);
|
||||||
|
int VertexCount () { return _vertex_count; }
|
||||||
|
int PolyCount () { return _polycount; }
|
||||||
|
void CubeAdd (int* index);
|
||||||
|
void QuadStripAdd (int* index, int count);
|
||||||
|
void FanAdd (int* index, int count);
|
||||||
|
void Render ();
|
||||||
|
void Compile ();
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,266 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="PixelCity" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||||
|
|
||||||
|
CFG=PixelCity - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "PixelCity.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "PixelCity.mak" CFG="PixelCity - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "PixelCity - Win32 Release" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE "PixelCity - Win32 Debug" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName "PixelCity"
|
||||||
|
# PROP Scc_LocalPath "."
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "PixelCity - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/PixelCity.scr"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "PixelCity - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "PixelCity - Win32 Release"
|
||||||
|
# Name "PixelCity - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Group "glTypes"
|
||||||
|
|
||||||
|
# PROP Default_Filter ""
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\glBbox.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\glMatrix.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\glQuat.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\glRgba.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\glVector2.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\glVector3.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Building.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Camera.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Car.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Deco.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Entity.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Ini.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Light.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Math.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Mesh.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Random.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Render.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Sky.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Texture.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Visible.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\World.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Building.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Camera.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Car.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Deco.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Entity.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\glTypes.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Ini.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Light.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Macro.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Math.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Mesh.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Random.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Render.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Sky.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Texture.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Visible.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Win.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\World.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
r a n d o m
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
The Mersenne Twister by Matsumoto and Nishimura <matumoto@math.keio.ac.jp>.
|
||||||
|
It sets new standards for the period, quality and speed of random number
|
||||||
|
generators. The incredible period is 2^19937 - 1, a number with about 6000
|
||||||
|
digits; the 32-bit random numbers exhibit best possible equidistribution
|
||||||
|
properties in dimensions up to 623; and it's fast, very fast.
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#define LOWER_MASK 0x7fffffff
|
||||||
|
#define M 397
|
||||||
|
#define MATRIX_A 0x9908b0df
|
||||||
|
#define N 624
|
||||||
|
#define TEMPERING_MASK_B 0x9d2c5680
|
||||||
|
#define TEMPERING_MASK_C 0xefc60000
|
||||||
|
#define TEMPERING_SHIFT_L(y) (y >> 18)
|
||||||
|
#define TEMPERING_SHIFT_S(y) (y << 7)
|
||||||
|
#define TEMPERING_SHIFT_T(y) (y << 15)
|
||||||
|
#define TEMPERING_SHIFT_U(y) (y >> 11)
|
||||||
|
#define UPPER_MASK 0x80000000
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
|
static int k = 1;
|
||||||
|
static unsigned long mag01[2] = {0x0, MATRIX_A};
|
||||||
|
static unsigned long ptgfsr[N];
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
unsigned long RandomVal (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
int kk;
|
||||||
|
unsigned long y;
|
||||||
|
|
||||||
|
if (k == N) {
|
||||||
|
for (kk = 0; kk < N - M; kk++) {
|
||||||
|
y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);
|
||||||
|
ptgfsr[kk] = ptgfsr[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||||
|
}
|
||||||
|
for (; kk < N - 1; kk++) {
|
||||||
|
y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);
|
||||||
|
ptgfsr[kk] = ptgfsr[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||||
|
}
|
||||||
|
y = (ptgfsr[N - 1] & UPPER_MASK) | (ptgfsr[0] & LOWER_MASK);
|
||||||
|
ptgfsr[N - 1] = ptgfsr[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
y = ptgfsr[k++];
|
||||||
|
y ^= TEMPERING_SHIFT_U (y);
|
||||||
|
y ^= TEMPERING_SHIFT_S (y) & TEMPERING_MASK_B;
|
||||||
|
y ^= TEMPERING_SHIFT_T (y) & TEMPERING_MASK_C;
|
||||||
|
return y ^= TEMPERING_SHIFT_L (y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
unsigned long RandomVal (int range)
|
||||||
|
{
|
||||||
|
|
||||||
|
return range ? (RandomVal () % range) : 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RandomInit (unsigned long seed)
|
||||||
|
{
|
||||||
|
|
||||||
|
//int k;
|
||||||
|
|
||||||
|
//memset (ptgfsr, 0, sizeof (ptgfsr));
|
||||||
|
//mag01[0] = 0x0;
|
||||||
|
//mag01[1] = MATRIX_A;
|
||||||
|
ptgfsr[0] = seed;
|
||||||
|
for (k = 1; k < N; k++)
|
||||||
|
ptgfsr[k] = 69069 * ptgfsr[k - 1];
|
||||||
|
k = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#define COIN_FLIP (RandomVal (2) == 0)
|
||||||
|
|
||||||
|
unsigned long RandomVal (int range);
|
||||||
|
unsigned long RandomVal (void);
|
||||||
|
void RandomInit (unsigned long seed);
|
|
@ -0,0 +1,777 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Render.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This is the core of the gl rendering functions. This contains the main
|
||||||
|
rendering function RenderUpdate (), which initiates the various
|
||||||
|
other renders in the other modules.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define RENDER_DISTANCE 1280
|
||||||
|
#define MAX_TEXT 256
|
||||||
|
#define YOUFAIL(message) {WinPopup (message);return;}
|
||||||
|
#define HELP_SIZE sizeof(help)
|
||||||
|
#define COLOR_CYCLE_TIME 10000 //milliseconds
|
||||||
|
#define COLOR_CYCLE (COLOR_CYCLE_TIME / 4)
|
||||||
|
#define FONT_COUNT (sizeof (fonts) / sizeof (struct glFont))
|
||||||
|
#define FONT_SIZE (LOGO_PIXELS - LOGO_PIXELS / 8)
|
||||||
|
#define BLOOM_SCALING 0.07f
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include <gl\glu.h>
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
#include "entity.h"
|
||||||
|
#include "car.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "ini.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "sky.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "world.h"
|
||||||
|
#include "win.h"
|
||||||
|
|
||||||
|
static PIXELFORMATDESCRIPTOR pfd =
|
||||||
|
{
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
1, // Version Number
|
||||||
|
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
||||||
|
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
|
||||||
|
PFD_DOUBLEBUFFER, // Must Support Double Buffering
|
||||||
|
PFD_TYPE_RGBA, // Request An RGBA Format
|
||||||
|
32, // Select Our glRgbaDepth
|
||||||
|
0, 0, 0, 0, 0, 0, // glRgbaBits Ignored
|
||||||
|
0, // No Alpha Buffer
|
||||||
|
0, // Shift Bit Ignored
|
||||||
|
0, // Accumulation Buffers
|
||||||
|
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||||
|
16, // Z-Buffer (Depth Buffer) bits
|
||||||
|
0, // Stencil Buffers
|
||||||
|
1, // Auxiliary Buffers
|
||||||
|
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||||
|
0, // Reserved
|
||||||
|
0, 0, 0 // Layer Masks Ignored
|
||||||
|
};
|
||||||
|
|
||||||
|
static char help[] =
|
||||||
|
"ESC - Exit!\n"
|
||||||
|
"F1 - Show this help screen\n"
|
||||||
|
"R - Rebuild city\n"
|
||||||
|
"L - Toggle 'letterbox' mode\n"
|
||||||
|
"F - Show Framecounter\n"
|
||||||
|
"W - Toggle Wireframe\n"
|
||||||
|
"E - Change full-scene effects\n"
|
||||||
|
"T - Toggle Textures\n"
|
||||||
|
"G - Toggle Fog\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
struct glFont
|
||||||
|
{
|
||||||
|
char* name;
|
||||||
|
unsigned base_char;
|
||||||
|
} fonts[] =
|
||||||
|
{
|
||||||
|
"Courier New", 0,
|
||||||
|
"Arial", 0,
|
||||||
|
"Times New Roman", 0,
|
||||||
|
"Arial Black", 0,
|
||||||
|
"Impact", 0,
|
||||||
|
"Agency FB", 0,
|
||||||
|
"Book Antiqua", 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if SCREENSAVER
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
EFFECT_NONE,
|
||||||
|
EFFECT_BLOOM,
|
||||||
|
EFFECT_BLOOM_RADIAL,
|
||||||
|
EFFECT_COLOR_CYCLE,
|
||||||
|
EFFECT_GLASS_CITY,
|
||||||
|
EFFECT_DEBUG,
|
||||||
|
EFFECT_DEBUG_OVERBLOOM,
|
||||||
|
EFFECT_COUNT
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
EFFECT_NONE,
|
||||||
|
EFFECT_BLOOM,
|
||||||
|
EFFECT_COUNT,
|
||||||
|
EFFECT_DEBUG,
|
||||||
|
EFFECT_DEBUG_OVERBLOOM,
|
||||||
|
EFFECT_BLOOM_RADIAL,
|
||||||
|
EFFECT_COLOR_CYCLE,
|
||||||
|
EFFECT_GLASS_CITY,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static HDC hDC;
|
||||||
|
static HGLRC hRC;
|
||||||
|
static float render_aspect;
|
||||||
|
static float fog_distance;
|
||||||
|
static int render_width;
|
||||||
|
static int render_height;
|
||||||
|
static bool letterbox;
|
||||||
|
static int letterbox_offset;
|
||||||
|
static int effect;
|
||||||
|
static int max_texture;
|
||||||
|
static unsigned next_fps;
|
||||||
|
static unsigned current_fps;
|
||||||
|
static unsigned frames;
|
||||||
|
static bool show_wireframe;
|
||||||
|
static bool bloom;
|
||||||
|
static bool flat;
|
||||||
|
static bool show_fps;
|
||||||
|
static bool show_fog;
|
||||||
|
static bool show_help;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Draw a clock-ish progress.. widget... thing. It's cute.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void do_progress (float center_x, float center_y, float radius, float opacity, float progress)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int end_angle;
|
||||||
|
float inner, outer;
|
||||||
|
float angle;
|
||||||
|
float s, c;
|
||||||
|
float gap;
|
||||||
|
|
||||||
|
//Outer Ring
|
||||||
|
gap = radius * 0.05f;
|
||||||
|
outer = radius;
|
||||||
|
inner = radius - gap * 2;
|
||||||
|
glColor4f (1,1,1, opacity);
|
||||||
|
glBegin (GL_QUAD_STRIP);
|
||||||
|
for (i = 0; i <= 360; i+= 15) {
|
||||||
|
//GLrgba col = glRgbaUnique (i);
|
||||||
|
//glColor3fv (&col.red);
|
||||||
|
angle = (float)i * DEGREES_TO_RADIANS;
|
||||||
|
s = sinf (angle);
|
||||||
|
c = -cosf (angle);
|
||||||
|
glVertex2f (center_x + s * outer, center_y + c * outer);
|
||||||
|
glVertex2f (center_x + s * inner, center_y + c * inner);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
//Progress indicator
|
||||||
|
glColor4f (1,1,1, opacity);
|
||||||
|
end_angle = (int)(360 * progress);
|
||||||
|
outer = radius - gap * 3;
|
||||||
|
glBegin (GL_TRIANGLE_FAN);
|
||||||
|
glVertex2f (center_x, center_y);
|
||||||
|
for (i = 0; i <= end_angle; i+= 3) {
|
||||||
|
angle = (float)i * DEGREES_TO_RADIANS;
|
||||||
|
s = sinf (angle);
|
||||||
|
c = -cosf (angle);
|
||||||
|
glVertex2f (center_x + s * outer, center_y + c * outer);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
//Tic lines
|
||||||
|
glLineWidth (2.0f);
|
||||||
|
outer = radius - gap * 1;
|
||||||
|
inner = radius - gap * 2;
|
||||||
|
glColor4f (0,0,0, opacity);
|
||||||
|
glBegin (GL_LINES);
|
||||||
|
for (i = 0; i <= 360; i+= 15) {
|
||||||
|
angle = (float)i * DEGREES_TO_RADIANS;
|
||||||
|
s = sinf (angle);
|
||||||
|
c = -cosf (angle);
|
||||||
|
glVertex2f (center_x + s * outer, center_y + c * outer);
|
||||||
|
glVertex2f (center_x + s * inner, center_y + c * inner);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void do_effects (int type)
|
||||||
|
{
|
||||||
|
|
||||||
|
float hue1, hue2, hue3, hue4;
|
||||||
|
GLrgba color;
|
||||||
|
float fade;
|
||||||
|
int radius;
|
||||||
|
int x, y;
|
||||||
|
int i;
|
||||||
|
int bloom_radius;
|
||||||
|
int bloom_step;
|
||||||
|
|
||||||
|
fade = WorldFade ();
|
||||||
|
bloom_radius = 15;
|
||||||
|
bloom_step = bloom_radius / 3;
|
||||||
|
if (!TextureReady () && fade == 0.0f)
|
||||||
|
return;
|
||||||
|
//Now change projection modes so we can render full-screen effects
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glMatrixMode (GL_PROJECTION);
|
||||||
|
glPushMatrix ();
|
||||||
|
glLoadIdentity ();
|
||||||
|
glOrtho (0, render_width, render_height, 0, 0.1f, 2048);
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
glPushMatrix ();
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(0, 0, -1.0f);
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
//Render full-screen effects
|
||||||
|
|
||||||
|
glBlendFunc (GL_ONE, GL_ONE);
|
||||||
|
glEnable (GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_BLOOM));
|
||||||
|
switch (type) {
|
||||||
|
case EFFECT_DEBUG:
|
||||||
|
glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_LOGOS));
|
||||||
|
glDisable (GL_BLEND);
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glColor3f (1, 1, 1);
|
||||||
|
glTexCoord2f (0, 0); glVertex2i (0, render_height / 4);
|
||||||
|
glTexCoord2f (0, 1); glVertex2i (0, 0);
|
||||||
|
glTexCoord2f (1, 1); glVertex2i (render_width / 4, 0);
|
||||||
|
glTexCoord2f (1, 0); glVertex2i (render_width / 4, render_height / 4);
|
||||||
|
|
||||||
|
glTexCoord2f (0, 0); glVertex2i (0, 512);
|
||||||
|
glTexCoord2f (0, 1); glVertex2i (0, 0);
|
||||||
|
glTexCoord2f (1, 1); glVertex2i (512, 0);
|
||||||
|
glTexCoord2f (1, 0); glVertex2i (512, 512);
|
||||||
|
glEnd ();
|
||||||
|
break;
|
||||||
|
case EFFECT_BLOOM_RADIAL:
|
||||||
|
//Psychedelic bloom
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
color = WorldBloomColor () * BLOOM_SCALING;
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
for (i = 0; i <= 100; i+=10) {
|
||||||
|
glTexCoord2f (0, 0); glVertex2i (-i, i + render_height);
|
||||||
|
glTexCoord2f (0, 1); glVertex2i (-i, -i);
|
||||||
|
glTexCoord2f (1, 1); glVertex2i (i + render_width, -i);
|
||||||
|
glTexCoord2f (1, 0); glVertex2i (i + render_width, i + render_height);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
break;
|
||||||
|
case EFFECT_COLOR_CYCLE:
|
||||||
|
//Oooh. Pretty colors. Tint the scene according to screenspace.
|
||||||
|
hue1 = (float)(GetTickCount () % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;
|
||||||
|
hue2 = (float)((GetTickCount () + COLOR_CYCLE) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;
|
||||||
|
hue3 = (float)((GetTickCount () + COLOR_CYCLE * 2) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;
|
||||||
|
hue4 = (float)((GetTickCount () + COLOR_CYCLE * 3) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc (GL_ONE, GL_ONE);
|
||||||
|
glBlendFunc (GL_DST_COLOR, GL_SRC_COLOR);
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
color = glRgbaFromHsl (hue1, 1.0f, 0.6f);
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
glTexCoord2f (0, 0); glVertex2i (0, render_height);
|
||||||
|
color = glRgbaFromHsl (hue2, 1.0f, 0.6f);
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
glTexCoord2f (0, 1); glVertex2i (0, 0);
|
||||||
|
color = glRgbaFromHsl (hue3, 1.0f, 0.6f);
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
glTexCoord2f (1, 1); glVertex2i (render_width, 0);
|
||||||
|
color = glRgbaFromHsl (hue4, 1.0f, 0.6f);
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
glTexCoord2f (1, 0); glVertex2i (render_width, render_height);
|
||||||
|
glEnd ();
|
||||||
|
break;
|
||||||
|
case EFFECT_BLOOM:
|
||||||
|
//Simple bloom effect
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
color = WorldBloomColor () * BLOOM_SCALING;
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
for (x = -bloom_radius; x <= bloom_radius; x += bloom_step) {
|
||||||
|
for (y = -bloom_radius; y <= bloom_radius; y += bloom_step) {
|
||||||
|
if (abs (x) == abs (y) && x)
|
||||||
|
continue;
|
||||||
|
glTexCoord2f (0, 0); glVertex2i (x, y + render_height);
|
||||||
|
glTexCoord2f (0, 1); glVertex2i (x, y);
|
||||||
|
glTexCoord2f (1, 1); glVertex2i (x + render_width, y);
|
||||||
|
glTexCoord2f (1, 0); glVertex2i (x + render_width, y + render_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
break;
|
||||||
|
case EFFECT_DEBUG_OVERBLOOM:
|
||||||
|
//This will punish that uppity GPU. Good for testing low frame rate behavior.
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
color = WorldBloomColor () * 0.06f;
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
for (x = -50; x <= 50; x+=5) {
|
||||||
|
for (y = -50; y <= 50; y+=5) {
|
||||||
|
glTexCoord2f (0, 0); glVertex2i (x, y + render_height);
|
||||||
|
glTexCoord2f (0, 1); glVertex2i (x, y);
|
||||||
|
glTexCoord2f (1, 1); glVertex2i (x + render_width, y);
|
||||||
|
glTexCoord2f (1, 0); glVertex2i (x + render_width, y + render_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Do the fade to / from darkness used to hide scene transitions
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glDisable (GL_TEXTURE_2D);
|
||||||
|
glColor4f (0, 0, 0, fade);
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glVertex2i (0, 0);
|
||||||
|
glVertex2i (0, render_height);
|
||||||
|
glVertex2i (render_width, render_height);
|
||||||
|
glVertex2i (render_width, 0);
|
||||||
|
glEnd ();
|
||||||
|
if (TextureReady () && !EntityReady () && fade != 0.0f) {
|
||||||
|
radius = render_width / 16;
|
||||||
|
do_progress ((float)render_width / 2, (float)render_height / 2, (float)radius, fade, EntityProgress ());
|
||||||
|
RenderPrint (render_width / 2 - LOGO_PIXELS, render_height / 2 + LOGO_PIXELS, 0, glRgba (0.5f), "%1.2f%%", EntityProgress () * 100.0f);
|
||||||
|
}
|
||||||
|
glPopMatrix ();
|
||||||
|
glMatrixMode (GL_PROJECTION);
|
||||||
|
glPopMatrix ();
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderPrint (int x, int y, int font, GLrgba color, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
|
||||||
|
char text[MAX_TEXT];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
text[0] = 0;
|
||||||
|
if (fmt == NULL)
|
||||||
|
return;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsprintf(text, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
glPushAttrib(GL_LIST_BIT);
|
||||||
|
glListBase(fonts[font % FONT_COUNT].base_char - 32);
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
glRasterPos2i (x, y);
|
||||||
|
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderPrint (int line, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
|
||||||
|
char text[MAX_TEXT];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
text[0] = 0;
|
||||||
|
if (fmt == NULL)
|
||||||
|
return;
|
||||||
|
va_start (ap, fmt);
|
||||||
|
vsprintf (text, fmt, ap);
|
||||||
|
va_end (ap);
|
||||||
|
glDepthMask (false);
|
||||||
|
glMatrixMode (GL_PROJECTION);
|
||||||
|
glPushMatrix ();
|
||||||
|
glLoadIdentity ();
|
||||||
|
glOrtho (0, render_width, render_height, 0, 0.1f, 2048);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
glPushMatrix ();
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(0, 0, -1.0f);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable (GL_DEPTH_TEST);
|
||||||
|
RenderPrint (0, line * FONT_SIZE - 2, 0, glRgba (0.0f), text);
|
||||||
|
RenderPrint (4, line * FONT_SIZE + 2, 0, glRgba (0.0f), text);
|
||||||
|
RenderPrint (2, line * FONT_SIZE, 0, glRgba (1.0f), text);
|
||||||
|
glPopAttrib();
|
||||||
|
glPopMatrix ();
|
||||||
|
glMatrixMode (GL_PROJECTION);
|
||||||
|
glPopMatrix ();
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void static do_help (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
char* text;
|
||||||
|
int line;
|
||||||
|
char parse[HELP_SIZE];
|
||||||
|
int x;
|
||||||
|
|
||||||
|
strcpy (parse, help);
|
||||||
|
line = 0;
|
||||||
|
text = strtok (parse, "\n");
|
||||||
|
x = 10;
|
||||||
|
while (text) {
|
||||||
|
RenderPrint (line + 1, text);
|
||||||
|
text = strtok (NULL, "\n");
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderResize (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
float fovy;
|
||||||
|
|
||||||
|
render_width = WinWidth ();
|
||||||
|
render_height = WinHeight ();
|
||||||
|
if (letterbox) {
|
||||||
|
letterbox_offset = render_height / 6;
|
||||||
|
render_height = render_height - letterbox_offset * 2;
|
||||||
|
} else
|
||||||
|
letterbox_offset = 0;
|
||||||
|
//render_aspect = (float)render_height / (float)render_width;
|
||||||
|
glViewport (0, letterbox_offset, render_width, render_height);
|
||||||
|
glMatrixMode (GL_PROJECTION);
|
||||||
|
glLoadIdentity ();
|
||||||
|
render_aspect = (float)render_width / (float)render_height;
|
||||||
|
fovy = 60.0f;
|
||||||
|
if (render_aspect > 1.0f)
|
||||||
|
fovy /= render_aspect;
|
||||||
|
gluPerspective (fovy, render_aspect, 0.1f, RENDER_DISTANCE);
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderTerm (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!hRC)
|
||||||
|
return;
|
||||||
|
wglDeleteContext (hRC);
|
||||||
|
hRC = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderInit (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
HWND hWnd;
|
||||||
|
unsigned PixelFormat;
|
||||||
|
HFONT font;
|
||||||
|
HFONT oldfont;
|
||||||
|
|
||||||
|
hWnd = WinHwnd ();
|
||||||
|
if (!(hDC = GetDC (hWnd)))
|
||||||
|
YOUFAIL ("Can't Create A GL Device Context.") ;
|
||||||
|
if (!(PixelFormat = ChoosePixelFormat(hDC,&pfd)))
|
||||||
|
YOUFAIL ("Can't Find A Suitable PixelFormat.") ;
|
||||||
|
if(!SetPixelFormat(hDC,PixelFormat,&pfd))
|
||||||
|
YOUFAIL ("Can't Set The PixelFormat.");
|
||||||
|
if (!(hRC = wglCreateContext (hDC)))
|
||||||
|
YOUFAIL ("Can't Create A GL Rendering Context.");
|
||||||
|
if(!wglMakeCurrent(hDC,hRC))
|
||||||
|
YOUFAIL ("Can't Activate The GL Rendering Context.");
|
||||||
|
//Load the fonts for printing debug info to the window.
|
||||||
|
for (int i = 0; i < FONT_COUNT; i++) {
|
||||||
|
fonts[i].base_char = glGenLists(96);
|
||||||
|
font = CreateFont (FONT_SIZE, 0, 0, 0,
|
||||||
|
FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_TT_PRECIS,
|
||||||
|
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH,
|
||||||
|
fonts[i].name);
|
||||||
|
oldfont = (HFONT)SelectObject(hDC, font);
|
||||||
|
wglUseFontBitmaps(hDC, 32, 96, fonts[i].base_char);
|
||||||
|
SelectObject(hDC, oldfont);
|
||||||
|
DeleteObject(font);
|
||||||
|
}
|
||||||
|
//load in our settings
|
||||||
|
letterbox = IniInt ("Letterbox") != 0;
|
||||||
|
show_wireframe = IniInt ("Wireframe") != 0;
|
||||||
|
show_fps = IniInt ("ShowFPS") != 0;
|
||||||
|
show_fog = IniInt ("ShowFog") != 0;
|
||||||
|
bloom = IniInt ("Bloom") != 0;
|
||||||
|
effect = IniInt ("Effect");
|
||||||
|
flat = IniInt ("Flat") != 0;
|
||||||
|
fog_distance = WORLD_HALF;
|
||||||
|
//clear the viewport so the user isn't looking at trash while the program starts
|
||||||
|
glViewport (0, 0, WinWidth (), WinHeight ());
|
||||||
|
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
SwapBuffers (hDC);
|
||||||
|
RenderResize ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderFPSToggle ()
|
||||||
|
{
|
||||||
|
|
||||||
|
show_fps = !show_fps;
|
||||||
|
IniIntSet ("ShowFPS", show_fps ? 1 : 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool RenderFog ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return show_fog;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderFogToggle ()
|
||||||
|
{
|
||||||
|
|
||||||
|
show_fog = !show_fog;
|
||||||
|
IniIntSet ("ShowFog", show_fog ? 1 : 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderLetterboxToggle ()
|
||||||
|
{
|
||||||
|
|
||||||
|
letterbox = !letterbox;
|
||||||
|
IniIntSet ("Letterbox", letterbox ? 1 : 0);
|
||||||
|
RenderResize ();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderWireframeToggle ()
|
||||||
|
{
|
||||||
|
|
||||||
|
show_wireframe = !show_wireframe;
|
||||||
|
IniIntSet ("Wireframe", show_wireframe ? 1 : 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool RenderWireframe ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return show_wireframe;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderEffectCycle ()
|
||||||
|
{
|
||||||
|
|
||||||
|
effect = (effect + 1) % EFFECT_COUNT;
|
||||||
|
IniIntSet ("Effect", effect);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool RenderBloom ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return effect == EFFECT_BLOOM || effect == EFFECT_BLOOM_RADIAL
|
||||||
|
|| effect == EFFECT_DEBUG_OVERBLOOM || effect == EFFECT_COLOR_CYCLE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool RenderFlat ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return flat;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderFlatToggle ()
|
||||||
|
{
|
||||||
|
|
||||||
|
flat = !flat;
|
||||||
|
IniIntSet ("Flat", flat ? 1 : 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderHelpToggle ()
|
||||||
|
{
|
||||||
|
|
||||||
|
show_help = !show_help;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float RenderFogDistance ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return fog_distance;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void RenderUpdate (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector pos;
|
||||||
|
GLvector angle;
|
||||||
|
GLrgba color;
|
||||||
|
|
||||||
|
glViewport (0, 0, WinWidth (), WinHeight ());
|
||||||
|
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
if (letterbox)
|
||||||
|
glViewport (0, letterbox_offset, render_width, render_height);
|
||||||
|
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||||
|
glShadeModel(GL_SMOOTH);
|
||||||
|
glFogi (GL_FOG_MODE, GL_LINEAR);
|
||||||
|
if (show_fog) {
|
||||||
|
glEnable (GL_FOG);
|
||||||
|
glFogf (GL_FOG_START, fog_distance - 100);
|
||||||
|
glFogf (GL_FOG_END, fog_distance);
|
||||||
|
color = glRgba (0.0f);
|
||||||
|
glFogfv (GL_FOG_COLOR, &color.red);
|
||||||
|
} else
|
||||||
|
glDisable (GL_FOG);
|
||||||
|
//glEnable (GL_COLOR_MATERIAL);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable (GL_CULL_FACE);
|
||||||
|
glCullFace (GL_BACK);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glMatrixMode (GL_TEXTURE);
|
||||||
|
glLoadIdentity();
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||||
|
|
||||||
|
glLoadIdentity();
|
||||||
|
glLineWidth (2.0f);
|
||||||
|
pos = CameraPosition ();
|
||||||
|
angle = CameraAngle ();
|
||||||
|
glRotatef (angle.x, 1.0f, 0.0f, 0.0f);
|
||||||
|
glRotatef (angle.y, 0.0f, 1.0f, 0.0f);
|
||||||
|
glRotatef (angle.z, 0.0f, 0.0f, 1.0f);
|
||||||
|
glTranslatef (-pos.x, -pos.y, -pos.z);
|
||||||
|
glEnable (GL_TEXTURE_2D);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
//Render all the stuff in the whole entire world.
|
||||||
|
SkyRender ();
|
||||||
|
WorldRender ();
|
||||||
|
if (effect == EFFECT_GLASS_CITY) {
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc (GL_ONE, GL_ONE);
|
||||||
|
glDepthFunc (false);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glMatrixMode (GL_TEXTURE);
|
||||||
|
glTranslatef ((pos.x + pos.z) / SEGMENTS_PER_TEXTURE, 0, 0);
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
} else {
|
||||||
|
glEnable (GL_CULL_FACE);
|
||||||
|
glDisable (GL_BLEND);
|
||||||
|
}
|
||||||
|
EntityRender ();
|
||||||
|
LightRender ();
|
||||||
|
CarRender ();
|
||||||
|
if (show_wireframe) {
|
||||||
|
glDisable (GL_TEXTURE_2D);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
EntityRender ();
|
||||||
|
}
|
||||||
|
//do_effects (EntityReady () ? effect : -1);
|
||||||
|
do_effects (effect);
|
||||||
|
//Framerate tracker
|
||||||
|
if (GetTickCount () > next_fps) {
|
||||||
|
current_fps = frames;
|
||||||
|
frames = 0;
|
||||||
|
next_fps = GetTickCount () + 1000;
|
||||||
|
}
|
||||||
|
if (show_fps && !show_help) {
|
||||||
|
RenderPrint (1, "FPS=%d", current_fps);
|
||||||
|
RenderPrint (2, "Entities=%d", EntityCount () + LightCount () + CarCount ());
|
||||||
|
RenderPrint (3, "Lights=%d", LightCount ());
|
||||||
|
RenderPrint (4, "Polys=%d", EntityPolyCount () + LightCount () + CarCount ());
|
||||||
|
RenderPrint (5, "Building=%1.2f", EntityProgress () * 100);
|
||||||
|
}
|
||||||
|
//Show the help overlay
|
||||||
|
if (show_help)
|
||||||
|
do_help ();
|
||||||
|
glDepthMask (true);
|
||||||
|
frames++;
|
||||||
|
SwapBuffers (hDC);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
bool RenderBloom ();
|
||||||
|
void RenderEffectCycle ();
|
||||||
|
bool RenderFlat ();
|
||||||
|
void RenderFlatToggle ();
|
||||||
|
float RenderFogDistance ();
|
||||||
|
bool RenderFog ();
|
||||||
|
void RenderFogToggle ();
|
||||||
|
void RenderFPSToggle ();
|
||||||
|
void RenderInit ();
|
||||||
|
void RenderLetterboxToggle ();
|
||||||
|
void RenderResize ();
|
||||||
|
void RenderTerm ();
|
||||||
|
void RenderUpdate ();
|
||||||
|
bool RenderWireframe ();
|
||||||
|
void RenderWireframeToggle ();
|
||||||
|
void RenderHelpToggle ();
|
||||||
|
void RenderPrint (int x, int y, int font, GLrgba color, const char *fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Sky.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Did this need to be written as a class? It did not. There will never be
|
||||||
|
more than one sky in play, so the whole class structure here is superflous,
|
||||||
|
but harmless.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define SKYPOINTS 24
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "sky.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "glTypes.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
static CSky* sky;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SkyRender ()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (sky && !RenderFlat ())
|
||||||
|
sky->Render ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SkyClear ()
|
||||||
|
{
|
||||||
|
|
||||||
|
if(sky)
|
||||||
|
delete sky;
|
||||||
|
sky = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CSky::Render ()
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector angle, position;
|
||||||
|
|
||||||
|
if (!RenderFog ())
|
||||||
|
return;
|
||||||
|
glDepthMask (false);
|
||||||
|
glPushAttrib (GL_POLYGON_BIT | GL_FOG_BIT);
|
||||||
|
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
glDisable (GL_FOG);
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glPushMatrix ();
|
||||||
|
glLoadIdentity();
|
||||||
|
angle = CameraAngle ();
|
||||||
|
position = CameraPosition ();
|
||||||
|
glRotatef (angle.x, 1.0f, 0.0f, 0.0f);
|
||||||
|
glRotatef (angle.y, 0.0f, 1.0f, 0.0f);
|
||||||
|
glRotatef (angle.z, 0.0f, 0.0f, 1.0f);
|
||||||
|
glTranslatef (0.0f, -position.y / 100.0f, 0.0f);
|
||||||
|
glEnable (GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_SKY));
|
||||||
|
glCallList (m_list);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_CLOUDS));
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glCallList (m_list);
|
||||||
|
glPopMatrix ();
|
||||||
|
glPopAttrib ();
|
||||||
|
glDepthMask (true);
|
||||||
|
glEnable (GL_COLOR_MATERIAL);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CSky::CSky ()
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvertex circle[SKYPOINTS];
|
||||||
|
GLvector pos;
|
||||||
|
float angle;
|
||||||
|
int i;
|
||||||
|
float size;
|
||||||
|
float rad;
|
||||||
|
float lum;
|
||||||
|
|
||||||
|
size = 10.0f;
|
||||||
|
for (i = 0; i < SKYPOINTS; i++) {
|
||||||
|
angle = (float)i / (float)(SKYPOINTS - 1);
|
||||||
|
angle *= 360;
|
||||||
|
angle *= DEGREES_TO_RADIANS;
|
||||||
|
circle[i].position.x = sinf (angle) * size;
|
||||||
|
circle[i].position.y = 0.1f;
|
||||||
|
circle[i].position.z = cosf (angle) * size;
|
||||||
|
circle[i].uv.x = ((float)i / (float)(SKYPOINTS - 1)) * 5.0f;
|
||||||
|
circle[i].uv.y = 0.5f;
|
||||||
|
rad = ((float)i / (SKYPOINTS - 1)) * 180.0f * DEGREES_TO_RADIANS;
|
||||||
|
lum = sinf (rad);
|
||||||
|
lum = (float)pow (lum, 5);
|
||||||
|
circle[i].color = glRgba (lum);
|
||||||
|
}
|
||||||
|
m_list = glGenLists(1);
|
||||||
|
glNewList (m_list, GL_COMPILE);
|
||||||
|
glColor3f (1, 1, 1);
|
||||||
|
|
||||||
|
glBegin (GL_QUAD_STRIP);
|
||||||
|
for (i = 0; i < SKYPOINTS; i++) {
|
||||||
|
glTexCoord2f (circle[i].uv.x, 0.0f);
|
||||||
|
glVertex3fv (&circle[i].position.x);
|
||||||
|
pos = circle[i].position;
|
||||||
|
pos.y = size / 3.5f;
|
||||||
|
glTexCoord2f (circle[i].uv.x, 1.0f);
|
||||||
|
glVertex3fv (&pos.x);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
glEndList();
|
||||||
|
glEndList();
|
||||||
|
sky = this;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#define SKY_GRID 21
|
||||||
|
#define SKY_HALF (SKY_GRID / 2)
|
||||||
|
|
||||||
|
struct sky_point
|
||||||
|
{
|
||||||
|
GLrgba color;
|
||||||
|
GLvector position;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSky
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int m_list;
|
||||||
|
int m_stars_list;
|
||||||
|
sky_point m_grid[SKY_GRID][SKY_GRID];
|
||||||
|
|
||||||
|
public:
|
||||||
|
CSky ();
|
||||||
|
void Render (void);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void SkyRender ();
|
||||||
|
void SkyClear ();
|
|
@ -0,0 +1,887 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Texture.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This procedurally builds all of the textures.
|
||||||
|
|
||||||
|
I apologize in advance for the apalling state of this module. It's the victim
|
||||||
|
of iterative and experimental development. It has cruft, poorly named
|
||||||
|
functions, obscure code, poorly named variables, a is poorly organized. Even
|
||||||
|
the formatting sucks in places. Its only saving grace is that it works.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define RANDOM_COLOR_SHIFT ((float)(RandomVal (10)) / 50.0f)
|
||||||
|
#define RANDOM_COLOR_VAL ((float)(RandomVal (256)) / 256.0f)
|
||||||
|
#define RANDOM_COLOR_LIGHT ((float)(200 + RandomVal (56)) / 256.0f)
|
||||||
|
#define SKY_BANDS (sizeof (sky_pos) / sizeof (int))
|
||||||
|
#define PREFIX_COUNT (sizeof (prefix) / sizeof (char*))
|
||||||
|
#define SUFFIX_COUNT (sizeof (suffix) / sizeof (char*))
|
||||||
|
#define NAME_COUNT (sizeof (name) / sizeof (char*))
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include <gl\glu.h>
|
||||||
|
#include <gl\glaux.h>
|
||||||
|
|
||||||
|
#include "gltypes.h"
|
||||||
|
#include "building.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "car.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "sky.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
static char* prefix[] =
|
||||||
|
{
|
||||||
|
"i",
|
||||||
|
"Green ",
|
||||||
|
"Mega",
|
||||||
|
"Super ",
|
||||||
|
"Omni",
|
||||||
|
"e",
|
||||||
|
"Hyper",
|
||||||
|
"Global ",
|
||||||
|
"Vital",
|
||||||
|
"Next ",
|
||||||
|
"Pacific ",
|
||||||
|
"Metro",
|
||||||
|
"Unity ",
|
||||||
|
"G-",
|
||||||
|
"Trans",
|
||||||
|
"Infinity ",
|
||||||
|
"Superior ",
|
||||||
|
"Monolith ",
|
||||||
|
"Best ",
|
||||||
|
"Atlantic ",
|
||||||
|
"First ",
|
||||||
|
"Union ",
|
||||||
|
"National ",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char* name[] =
|
||||||
|
{
|
||||||
|
"Biotic",
|
||||||
|
"Info",
|
||||||
|
"Data",
|
||||||
|
"Solar",
|
||||||
|
"Aerospace",
|
||||||
|
"Motors",
|
||||||
|
"Nano",
|
||||||
|
"Online",
|
||||||
|
"Circuits",
|
||||||
|
"Energy",
|
||||||
|
"Med",
|
||||||
|
"Robotic",
|
||||||
|
"Exports",
|
||||||
|
"Security",
|
||||||
|
"Systems",
|
||||||
|
"Financial",
|
||||||
|
"Industrial",
|
||||||
|
"Media",
|
||||||
|
"Materials",
|
||||||
|
"Foods",
|
||||||
|
"Networks",
|
||||||
|
"Shipping",
|
||||||
|
"Tools",
|
||||||
|
"Medical",
|
||||||
|
"Publishing",
|
||||||
|
"Enterprises",
|
||||||
|
"Audio",
|
||||||
|
"Health",
|
||||||
|
"Bank",
|
||||||
|
"Imports",
|
||||||
|
"Apparel",
|
||||||
|
"Petroleum",
|
||||||
|
"Studios",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char* suffix[] =
|
||||||
|
{
|
||||||
|
"Corp",
|
||||||
|
" Inc.",
|
||||||
|
"Co",
|
||||||
|
"World",
|
||||||
|
".Com",
|
||||||
|
" USA",
|
||||||
|
" Ltd.",
|
||||||
|
"Net",
|
||||||
|
" Tech",
|
||||||
|
" Labs",
|
||||||
|
" Mfg.",
|
||||||
|
" UK",
|
||||||
|
" Unlimited",
|
||||||
|
" One",
|
||||||
|
};
|
||||||
|
|
||||||
|
class CTexture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int _my_id;
|
||||||
|
unsigned _glid;
|
||||||
|
int _size;
|
||||||
|
int _half;
|
||||||
|
int _segment_size;
|
||||||
|
bool _ready;
|
||||||
|
bool _masked;
|
||||||
|
bool _mipmap;
|
||||||
|
bool _clamp;
|
||||||
|
public:
|
||||||
|
CTexture* _next;
|
||||||
|
CTexture (int id, int size, bool mipmap, bool clamp, bool masked);
|
||||||
|
void Clear () { _ready = false; }
|
||||||
|
void Rebuild ();
|
||||||
|
void DrawWindows ();
|
||||||
|
};
|
||||||
|
|
||||||
|
static CTexture* head;
|
||||||
|
static bool textures_done;
|
||||||
|
static GLrgba horizon_color;
|
||||||
|
static GLrgba cloud_color;
|
||||||
|
static bool prefix_used[PREFIX_COUNT];
|
||||||
|
static bool name_used[NAME_COUNT];
|
||||||
|
static bool suffix_used[SUFFIX_COUNT];
|
||||||
|
static int build_time;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void drawrect_simple (int left, int top, int right, int bottom, GLrgba color)
|
||||||
|
{
|
||||||
|
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glVertex2i (left, top);
|
||||||
|
glVertex2i (right, top);
|
||||||
|
glVertex2i (right, bottom);
|
||||||
|
glVertex2i (left, bottom);
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void drawrect_simple (int left, int top, int right, int bottom, GLrgba color1, GLrgba color2)
|
||||||
|
{
|
||||||
|
|
||||||
|
glColor3fv (&color1.red);
|
||||||
|
glBegin (GL_TRIANGLE_FAN);
|
||||||
|
glVertex2i ((left + right) / 2, (top + bottom) / 2);
|
||||||
|
glColor3fv (&color2.red);
|
||||||
|
glVertex2i (left, top);
|
||||||
|
glVertex2i (right, top);
|
||||||
|
glVertex2i (right, bottom);
|
||||||
|
glVertex2i (left, bottom);
|
||||||
|
glVertex2i (left, top);
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void drawrect (int left, int top, int right, int bottom, GLrgba color)
|
||||||
|
{
|
||||||
|
|
||||||
|
float average;
|
||||||
|
float hue;
|
||||||
|
int potential;
|
||||||
|
int repeats;
|
||||||
|
int height;
|
||||||
|
int i, j;
|
||||||
|
bool bright;
|
||||||
|
GLrgba color_noise;
|
||||||
|
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glLineWidth (1.0f);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
glColor3fv (&color.red);
|
||||||
|
|
||||||
|
if (left == right) { //in low resolution, a "rect" might be 1 pixel wide
|
||||||
|
glBegin (GL_LINES);
|
||||||
|
glVertex2i (left, top);
|
||||||
|
glVertex2i (left, bottom);
|
||||||
|
glEnd ();
|
||||||
|
} if (top == bottom) { //in low resolution, a "rect" might be 1 pixel wide
|
||||||
|
glBegin (GL_LINES);
|
||||||
|
glVertex2i (left, top);
|
||||||
|
glVertex2i (right, top);
|
||||||
|
glEnd ();
|
||||||
|
} else { // draw one of those fancy 2-dimensional rectangles
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glVertex2i (left, top);
|
||||||
|
glVertex2i (right, top);
|
||||||
|
glVertex2i (right, bottom);
|
||||||
|
glVertex2i (left, bottom);
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
|
||||||
|
average = (color.red + color.blue + color.green) / 3.0f;
|
||||||
|
bright = average > 0.5f;
|
||||||
|
potential = (int)(average * 255.0f);
|
||||||
|
|
||||||
|
if (bright) {
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glBegin (GL_POINTS);
|
||||||
|
for (i = left + 1; i < right - 1; i++) {
|
||||||
|
for (j = top + 1; j < bottom - 1; j++) {
|
||||||
|
glColor4i (255, 0, RandomVal (potential), 255);
|
||||||
|
hue = 0.2f + (float)RandomVal (100) / 300.0f + (float)RandomVal (100) / 300.0f + (float)RandomVal (100) / 300.0f;
|
||||||
|
color_noise = glRgbaFromHsl (hue, 0.3f, 0.5f);
|
||||||
|
color_noise.alpha = (float)RandomVal (potential) / 144.0f;
|
||||||
|
glColor4f (RANDOM_COLOR_VAL, RANDOM_COLOR_VAL, RANDOM_COLOR_VAL, (float)RandomVal (potential) / 144.0f);
|
||||||
|
glColor4fv (&color_noise.red);
|
||||||
|
glVertex2i (i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
repeats = RandomVal (6) + 1;
|
||||||
|
height = (bottom - top) + (RandomVal (3) - 1) + (RandomVal(3) - 1);
|
||||||
|
for (i = left; i < right; i++) {
|
||||||
|
if (RandomVal (3) == 0)
|
||||||
|
repeats = RandomVal (4) + 1;
|
||||||
|
if (RandomVal (6) == 0) {
|
||||||
|
height = bottom - top;
|
||||||
|
height = RandomVal (height);
|
||||||
|
height = RandomVal (height);
|
||||||
|
height = RandomVal (height);
|
||||||
|
height = ((bottom - top) + height) / 2;
|
||||||
|
}
|
||||||
|
for (j = 0; j < 1; j++) {
|
||||||
|
glBegin (GL_LINES);
|
||||||
|
glColor4f (0, 0, 0, (float)RandomVal (256) / 256.0f);
|
||||||
|
glVertex2i (i, bottom - height);
|
||||||
|
glColor4f (0, 0, 0, (float)RandomVal (256) / 256.0f);
|
||||||
|
glVertex2i (i, bottom);
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void window (int x, int y, int size, int id, GLrgba color)
|
||||||
|
{
|
||||||
|
|
||||||
|
int margin;
|
||||||
|
int half;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
margin = size / 3;
|
||||||
|
half = size / 2;
|
||||||
|
//color = (color * 0.9f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT);
|
||||||
|
//glColor3fv (&color.red);
|
||||||
|
switch (id) {
|
||||||
|
case TEXTURE_BUILDING1: //filled, 1-pixel frame
|
||||||
|
drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);
|
||||||
|
break;
|
||||||
|
case TEXTURE_BUILDING2: //vertical
|
||||||
|
drawrect (x + margin, y + 1, x + size - margin, y + size - 1, color);
|
||||||
|
break;
|
||||||
|
case TEXTURE_BUILDING3: //side-by-side pair
|
||||||
|
drawrect (x + 1, y + 1, x + half - 1, y + size - margin, color);
|
||||||
|
drawrect (x + half + 1, y + 1, x + size - 1, y + size - margin, color);
|
||||||
|
break;
|
||||||
|
case TEXTURE_BUILDING4: //windows with blinds
|
||||||
|
drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);
|
||||||
|
i = RandomVal (size - 2);
|
||||||
|
drawrect (x + 1, y + 1, x + size - 1, y + i + 1, color * 0.3f);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case TEXTURE_BUILDING5: //vert stripes
|
||||||
|
drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);
|
||||||
|
drawrect (x + margin, y + 1, x + margin, y + size - 1, color * 0.7f);
|
||||||
|
drawrect (x + size - margin - 1, y + 1, x + size - margin - 1, y + size - 1, color * 0.3f);
|
||||||
|
break;
|
||||||
|
case TEXTURE_BUILDING6: //wide horz line
|
||||||
|
drawrect (x + 1, y + 1, x + size - 1, y + size - margin, color);
|
||||||
|
break;
|
||||||
|
case TEXTURE_BUILDING7: //4-pane
|
||||||
|
drawrect (x + 2, y + 1, x + size - 1, y + size - 1, color);
|
||||||
|
drawrect (x + 2, y + half, x + size - 1, y + half, color * 0.2f);
|
||||||
|
drawrect (x + half, y + 1, x + half, y + size - 1, color * 0.2f);
|
||||||
|
break;
|
||||||
|
case TEXTURE_BUILDING8: // Single narrow window
|
||||||
|
drawrect (x + half - 1, y + 1, x + half + 1, y + size - margin, color);
|
||||||
|
break;
|
||||||
|
case TEXTURE_BUILDING9: //horizontal
|
||||||
|
drawrect (x + 1, y + margin, x + size - 1, y + size - margin - 1, color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void do_bloom (CTexture* t)
|
||||||
|
{
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glViewport(0, 0, t->_size , t->_size);
|
||||||
|
glCullFace (GL_BACK);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDepthMask (true);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable (GL_CULL_FACE);
|
||||||
|
glCullFace (GL_BACK);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glEnable (GL_FOG);
|
||||||
|
glFogf (GL_FOG_START, RenderFogDistance () / 2);
|
||||||
|
glFogf (GL_FOG_END, RenderFogDistance ());
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
WorldRender ();
|
||||||
|
glEnable (GL_TEXTURE_2D);
|
||||||
|
EntityRender ();
|
||||||
|
CarRender ();
|
||||||
|
LightRender ();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, t->_glid);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, t->_size, t->_size, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CTexture::CTexture (int id, int size, bool mipmap, bool clamp, bool masked)
|
||||||
|
{
|
||||||
|
|
||||||
|
glGenTextures (1, &_glid);
|
||||||
|
_my_id = id;
|
||||||
|
_mipmap = mipmap;
|
||||||
|
_clamp = clamp;
|
||||||
|
_masked = masked;
|
||||||
|
_size = size;
|
||||||
|
_half = size / 2;
|
||||||
|
_segment_size = size / SEGMENTS_PER_TEXTURE;
|
||||||
|
_ready = false;
|
||||||
|
_next = head;
|
||||||
|
head = this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This draws all of the windows on a building texture. lit_density controls
|
||||||
|
how many lights are on. (1 in n chance that the light is on. Higher values
|
||||||
|
mean less lit windows. run_length controls how often it will consider
|
||||||
|
changing the lit / unlit status. 1 produces a complete scatter, higher
|
||||||
|
numbers make long strings of lights.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CTexture::DrawWindows ()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
int run;
|
||||||
|
int run_length;
|
||||||
|
int lit_density;
|
||||||
|
GLrgba color;
|
||||||
|
bool lit;
|
||||||
|
|
||||||
|
//color = glRgbaUnique (_my_id);
|
||||||
|
for (y = 0; y < SEGMENTS_PER_TEXTURE; y++) {
|
||||||
|
//Every few floors we change the behavior
|
||||||
|
if (!(y % 8)) {
|
||||||
|
run = 0;
|
||||||
|
run_length = RandomVal (9) + 2;
|
||||||
|
lit_density = 2 + RandomVal(2) + RandomVal(2);
|
||||||
|
lit = false;
|
||||||
|
}
|
||||||
|
for (x = 0; x < SEGMENTS_PER_TEXTURE; x++) {
|
||||||
|
//if this run is over reroll lit and start a new one
|
||||||
|
if (run < 1) {
|
||||||
|
run = RandomVal (run_length);
|
||||||
|
lit = RandomVal (lit_density) == 0;
|
||||||
|
//if (lit)
|
||||||
|
//color = glRgba (0.5f + (float)(RandomVal () % 128) / 256.0f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT);
|
||||||
|
}
|
||||||
|
if (lit)
|
||||||
|
color = glRgba (0.5f + (float)(RandomVal () % 128) / 256.0f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT);
|
||||||
|
else
|
||||||
|
color = glRgba ((float)(RandomVal () % 40) / 256.0f);
|
||||||
|
window (x * _segment_size, y * _segment_size, _segment_size, _my_id, color);
|
||||||
|
run--;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Here is where ALL of the procedural textures are created. It's filled with
|
||||||
|
obscure logic, magic numbers, and messy code. Part of this is because
|
||||||
|
there is a lot of "art" being done here, and lots of numbers that could be
|
||||||
|
endlessly tweaked. Also because I'm lazy.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CTexture::Rebuild ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
int x, y;
|
||||||
|
int name_num, prefix_num, suffix_num;
|
||||||
|
float radius;
|
||||||
|
GLvector2 pos;
|
||||||
|
GLrgba color;
|
||||||
|
bool use_framebuffer;
|
||||||
|
unsigned char* bits;
|
||||||
|
unsigned start;
|
||||||
|
int lapsed;
|
||||||
|
|
||||||
|
start = GetTickCount ();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _glid);
|
||||||
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, _size, _size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
if (_clamp) {
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
}
|
||||||
|
//Set up our viewport so that drawing into our texture will be as easy
|
||||||
|
//as possible. We make the viewport and projection simply match the given
|
||||||
|
//texture size.
|
||||||
|
glViewport(0, 0, _size , _size);
|
||||||
|
glMatrixMode (GL_PROJECTION);
|
||||||
|
glLoadIdentity ();
|
||||||
|
glOrtho (0, _size, _size, 0, 0.1f, 2048);
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
glPushMatrix ();
|
||||||
|
glLoadIdentity();
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glTranslatef(0, 0, -10.0f);
|
||||||
|
glClearColor (0, 0, 0, _masked ? 0.0f : 1.0f);
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
use_framebuffer = true;
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
switch (_my_id) {
|
||||||
|
case TEXTURE_GROUND:
|
||||||
|
unsigned char icolor[4];
|
||||||
|
char cell;
|
||||||
|
|
||||||
|
//memset (buffer, 0, 1024 * 1024 * 4);
|
||||||
|
bits = new unsigned char[_size * _size * 4];
|
||||||
|
ZeroMemory (bits, sizeof (bits));
|
||||||
|
icolor[3] = 255;
|
||||||
|
for (x = 0; x < _size; x++) {
|
||||||
|
for (y = 0; y < _size; y++) {
|
||||||
|
cell = WorldCell (x, y);
|
||||||
|
memset (icolor, 0, 3);
|
||||||
|
if (cell & CLAIM_ROAD)
|
||||||
|
icolor[0] = icolor[1] = icolor[2] = 12;
|
||||||
|
if (cell == CLAIM_WALK)
|
||||||
|
icolor[0] = icolor[1] = icolor[2] = 64;
|
||||||
|
icolor[0] += (unsigned char)RandomVal (4);
|
||||||
|
icolor[1] += (unsigned char)RandomVal (4);
|
||||||
|
icolor[2] += (unsigned char)RandomVal (4);
|
||||||
|
if (1) { //use this to make the road lanes visible
|
||||||
|
if (cell & MAP_ROAD_EAST)
|
||||||
|
icolor[0] += 128;
|
||||||
|
if (cell & MAP_ROAD_WEST)
|
||||||
|
icolor[1] += 128;
|
||||||
|
if (cell & MAP_ROAD_NORTH)
|
||||||
|
icolor[2] += 128;
|
||||||
|
if (cell & MAP_ROAD_SOUTH) {
|
||||||
|
icolor[1] += 64;
|
||||||
|
icolor[2] += 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy (&bits[(x + y * _size) * 4], &icolor[0], 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _glid);
|
||||||
|
|
||||||
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, _size, _size, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits);
|
||||||
|
use_framebuffer = false;
|
||||||
|
delete bits;
|
||||||
|
break;
|
||||||
|
case TEXTURE_LATTICE:
|
||||||
|
glLineWidth (2.0f);
|
||||||
|
|
||||||
|
glColor3f (0,0,0);
|
||||||
|
glBegin (GL_LINES);
|
||||||
|
glVertex2i (0, 0); glVertex2i (_size, _size);//diagonal
|
||||||
|
glVertex2i (0, 0); glVertex2i (0, _size);//vertical
|
||||||
|
glVertex2i (0, 0); glVertex2i (_size, 0);//vertical
|
||||||
|
glEnd ();
|
||||||
|
glBegin (GL_LINE_STRIP);
|
||||||
|
glVertex2i (0, 0);
|
||||||
|
for (i = 0; i < _size; i += 9) {
|
||||||
|
if (i % 2)
|
||||||
|
glVertex2i (0, i);
|
||||||
|
else
|
||||||
|
glVertex2i (i, i);
|
||||||
|
}
|
||||||
|
for (i = 0; i < _size; i += 9) {
|
||||||
|
if (i % 2)
|
||||||
|
glVertex2i (i, 0);
|
||||||
|
else
|
||||||
|
glVertex2i (i, i);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
break;
|
||||||
|
case TEXTURE_SOFT_CIRCLE:
|
||||||
|
//Make a simple circle of light, bright in the center and fading out
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
radius = ((float)_half) - 3;
|
||||||
|
glBegin (GL_TRIANGLE_FAN);
|
||||||
|
glColor4f (1, 1, 1, 1);
|
||||||
|
glVertex2i (_half, _half);
|
||||||
|
glColor4f (0, 0, 0, 0);
|
||||||
|
for (i = 0; i <= 360; i++) {
|
||||||
|
pos.x = sinf ((float)i * DEGREES_TO_RADIANS) * radius;
|
||||||
|
pos.y = cosf ((float)i * DEGREES_TO_RADIANS) * radius;
|
||||||
|
glVertex2i (_half + (int)pos.x, _half + (int)pos.y);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
break;
|
||||||
|
case TEXTURE_LIGHT:
|
||||||
|
//
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
radius = ((float)_half) - 3;
|
||||||
|
for (j = 0; j < 2; j++) {
|
||||||
|
glBegin (GL_TRIANGLE_FAN);
|
||||||
|
glColor4f (1, 1, 1, 1);
|
||||||
|
glVertex2i (_half, _half);
|
||||||
|
if (!j)
|
||||||
|
radius = ((float)_half / 2);
|
||||||
|
else
|
||||||
|
radius = 8;
|
||||||
|
glColor4f (1, 1, 0, 0);
|
||||||
|
for (i = 0; i <= 360; i++) {
|
||||||
|
pos.x = sinf ((float)i * DEGREES_TO_RADIANS) * radius;
|
||||||
|
pos.y = cosf ((float)i * DEGREES_TO_RADIANS) * radius;
|
||||||
|
glVertex2i (_half + (int)pos.x, _half + (int)pos.y);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TEXTURE_HEADLIGHT:
|
||||||
|
//Make a simple circle of light, bright in the center and fading out
|
||||||
|
radius = ((float)_half) - 20;
|
||||||
|
x = _half - 20;
|
||||||
|
y = _half;
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glBegin (GL_TRIANGLE_FAN);
|
||||||
|
glColor4f (0.8f, 0.8f, 0.8f, 0.6f);
|
||||||
|
glVertex2i (_half - 5, y);
|
||||||
|
glColor4f (0, 0, 0, 0);
|
||||||
|
for (i = 0; i <= 360; i += 36) {
|
||||||
|
pos.x = sinf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;
|
||||||
|
pos.y = cosf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;
|
||||||
|
glVertex2i (x + (int)pos.x, _half + (int)pos.y);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
x = _half + 20;
|
||||||
|
glBegin (GL_TRIANGLE_FAN);
|
||||||
|
glColor4f (0.8f, 0.8f, 0.8f, 0.6f);
|
||||||
|
glVertex2i (_half + 5, y);
|
||||||
|
glColor4f (0, 0, 0, 0);
|
||||||
|
for (i = 0; i <= 360; i += 36) {
|
||||||
|
pos.x = sinf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;
|
||||||
|
pos.y = cosf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;
|
||||||
|
glVertex2i (x + (int)pos.x, _half + (int)pos.y);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
x = _half - 6;
|
||||||
|
drawrect_simple (x - 3, y - 2, x + 2, y + 2, glRgba (1.0f));
|
||||||
|
x = _half + 6;
|
||||||
|
drawrect_simple (x - 2, y - 2, x + 3, y + 2, glRgba (1.0f));
|
||||||
|
break;
|
||||||
|
case TEXTURE_LOGOS:
|
||||||
|
i = 0;
|
||||||
|
glDepthMask (false);
|
||||||
|
glDisable (GL_BLEND);
|
||||||
|
name_num = RandomVal (NAME_COUNT);
|
||||||
|
prefix_num = RandomVal (PREFIX_COUNT);
|
||||||
|
suffix_num = RandomVal (SUFFIX_COUNT);
|
||||||
|
glColor3f (1,1,1);
|
||||||
|
while (i < _size) {
|
||||||
|
//randomly use a prefix OR suffix, but not both. Too verbose.
|
||||||
|
/*
|
||||||
|
if (COIN_FLIP)
|
||||||
|
RenderPrint (2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba (1.0f), "%s%s", prefix[prefix_num], name[name_num]);
|
||||||
|
else
|
||||||
|
RenderPrint (2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba (1.0f), "%s%s", name[name_num], suffix[suffix_num]);
|
||||||
|
*/
|
||||||
|
RenderPrint (2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba (1.0f), "Pixel City");
|
||||||
|
name_num = (name_num + 1) % NAME_COUNT;
|
||||||
|
prefix_num = (prefix_num + 1) % PREFIX_COUNT;
|
||||||
|
suffix_num = (suffix_num + 1) % SUFFIX_COUNT;
|
||||||
|
i += LOGO_PIXELS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TEXTURE_CLOUDS:
|
||||||
|
int width, height;
|
||||||
|
int offset;
|
||||||
|
float scale;
|
||||||
|
|
||||||
|
for (i = _size - 30; i > 5; i -= 1) {
|
||||||
|
x = RandomVal (_size);
|
||||||
|
y = i;
|
||||||
|
|
||||||
|
scale = 1.0f - ((float)y / (float)_size);
|
||||||
|
width = RandomVal (_half / 2) + (int)((float)_half * scale) / 2;
|
||||||
|
scale = 1.0f - (float)y / (float)_size;
|
||||||
|
height = (int)((float)(width) * scale);
|
||||||
|
height = MAX (height, 4);
|
||||||
|
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glEnable (GL_TEXTURE_2D);
|
||||||
|
glBindTexture (GL_TEXTURE_2D, TextureId (TEXTURE_SOFT_CIRCLE));
|
||||||
|
glDepthMask (false);
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
for (offset = -_size; offset <= _size; offset += _size) {
|
||||||
|
for (scale = 1.0f; scale > 0.0f; scale -= 0.25f) {
|
||||||
|
int width_adjust;
|
||||||
|
int height_adjust;
|
||||||
|
float inv_scale;
|
||||||
|
|
||||||
|
inv_scale = 1.0f - (scale);
|
||||||
|
|
||||||
|
if (scale < 0.4f)
|
||||||
|
color = cloud_color;
|
||||||
|
else
|
||||||
|
color = glRgba (0.0f);
|
||||||
|
color.alpha = 1.0f;
|
||||||
|
glColor4fv (&color.red);
|
||||||
|
//width_adjust = (int)((1.0f - scale) * ((float)width / 2.0f));
|
||||||
|
width_adjust = (int)((float)width / 2.0f + (int)(inv_scale * ((float)width / 2.0f)));
|
||||||
|
height_adjust = height + (int)(scale * (float)height * 0.99f);
|
||||||
|
|
||||||
|
glTexCoord2f (0, 0); glVertex2i (offset + x - width_adjust, y + height - height_adjust);
|
||||||
|
glTexCoord2f (0, 1); glVertex2i (offset + x - width_adjust, y + height);
|
||||||
|
glTexCoord2f (1, 1); glVertex2i (offset + x + width_adjust, y + height);
|
||||||
|
glTexCoord2f (1, 0); glVertex2i (offset + x + width_adjust, y + height - height_adjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TEXTURE_TRIM:
|
||||||
|
int margin;
|
||||||
|
y = 0;
|
||||||
|
margin = MAX (TRIM_PIXELS / 4, 1);
|
||||||
|
for (x = 0; x < _size; x += TRIM_PIXELS)
|
||||||
|
drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f));
|
||||||
|
y += TRIM_PIXELS;
|
||||||
|
for (x = 0; x < _size; x += TRIM_PIXELS * 2)
|
||||||
|
drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f));
|
||||||
|
y += TRIM_PIXELS;
|
||||||
|
for (x = 0; x < _size; x += TRIM_PIXELS * 3)
|
||||||
|
drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f));
|
||||||
|
y += TRIM_PIXELS;
|
||||||
|
for (x = 0; x < _size; x += TRIM_PIXELS)
|
||||||
|
drawrect_simple (x + margin, y + margin * 2, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f));
|
||||||
|
break;
|
||||||
|
case TEXTURE_SKY:
|
||||||
|
glDisable (GL_BLEND);
|
||||||
|
glBegin (GL_QUAD_STRIP);
|
||||||
|
glColor3f (0,0,0);
|
||||||
|
glVertex2i (0, _half);
|
||||||
|
glVertex2i (_size, _half);
|
||||||
|
glColor3fv (&horizon_color.red);
|
||||||
|
glVertex2i (0, _size - 2);
|
||||||
|
glVertex2i (_size, _size - 2);
|
||||||
|
glEnd ();
|
||||||
|
//Draw a bunch of little faux-buildings on the horizon.
|
||||||
|
for (i = 0; i < _size; i += 5)
|
||||||
|
drawrect (i, _size - RandomVal (8) - RandomVal (8) - RandomVal (8), i + RandomVal (9), _size, glRgba (0.0f));
|
||||||
|
break;
|
||||||
|
default: //building textures
|
||||||
|
DrawWindows ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
glPopMatrix ();
|
||||||
|
//Now blit the finished image into our texture
|
||||||
|
if (use_framebuffer) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _glid);
|
||||||
|
glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, _size, _size, 0);
|
||||||
|
}
|
||||||
|
if (_mipmap) {
|
||||||
|
bits = (unsigned char*)malloc (_size * _size * 4);
|
||||||
|
glGetTexImage (GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits);
|
||||||
|
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, _size, _size, GL_RGBA, GL_UNSIGNED_BYTE, bits);
|
||||||
|
free (bits);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||||
|
} else
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
||||||
|
//cleanup and restore the viewport
|
||||||
|
RenderResize ();
|
||||||
|
_ready = true;
|
||||||
|
lapsed = GetTickCount () - start;
|
||||||
|
build_time += lapsed;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
unsigned TextureId (int id)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (CTexture* t = head; t; t = t->_next) {
|
||||||
|
if (t->_my_id == id)
|
||||||
|
return t->_glid;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
unsigned TextureRandomBuilding (int index)
|
||||||
|
{
|
||||||
|
|
||||||
|
index = abs (index) % BUILDING_COUNT;
|
||||||
|
return TextureId (TEXTURE_BUILDING1 + index);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void TextureReset (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
float hue, sat;
|
||||||
|
|
||||||
|
textures_done = false;
|
||||||
|
build_time = 0;
|
||||||
|
for (CTexture* t = head; t; t = t->_next)
|
||||||
|
t->Clear ();
|
||||||
|
hue = 0.5f + (float)RandomVal (20) / 100.0f;
|
||||||
|
sat = 0.1f + (float)RandomVal (80) / 100.0f;
|
||||||
|
horizon_color = glRgbaFromHsl (hue, sat, 0.15f);
|
||||||
|
cloud_color = glRgbaFromHsl (hue, 0.15f, 0.1f);
|
||||||
|
ZeroMemory (prefix_used, sizeof (prefix_used));
|
||||||
|
ZeroMemory (name_used, sizeof (name_used));
|
||||||
|
ZeroMemory (suffix_used, sizeof (suffix_used));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool TextureReady ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return textures_done;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void TextureUpdate (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (textures_done) {
|
||||||
|
if (!RenderBloom ())
|
||||||
|
return;
|
||||||
|
CTexture* t;
|
||||||
|
|
||||||
|
for (t = head; t; t = t->_next) {
|
||||||
|
if (t->_my_id != TEXTURE_BLOOM)
|
||||||
|
continue;
|
||||||
|
do_bloom (t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (CTexture* t = head; t; t = t->_next) {
|
||||||
|
if (!t->_ready) {
|
||||||
|
t->Rebuild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textures_done = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void TextureTerm (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
CTexture* t;
|
||||||
|
|
||||||
|
while (head) {
|
||||||
|
t = head->_next;
|
||||||
|
free (head);
|
||||||
|
head = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void TextureInit (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
new CTexture (TEXTURE_SKY, 512, true, false, false);
|
||||||
|
new CTexture (TEXTURE_CLOUDS, 256, true, false, true);
|
||||||
|
new CTexture (TEXTURE_LATTICE, 128, true, true, true);
|
||||||
|
new CTexture (TEXTURE_LIGHT, 128, false, false, true);
|
||||||
|
new CTexture (TEXTURE_SOFT_CIRCLE, 128, false, false, true);
|
||||||
|
new CTexture (TEXTURE_HEADLIGHT, 128, false, false, true);
|
||||||
|
new CTexture (TEXTURE_TRIM, TRIM_RESOLUTION, true, false, false);
|
||||||
|
if (SHOW_DEBUG_GROUND)
|
||||||
|
new CTexture (TEXTURE_GROUND, 1024, false, false, false);
|
||||||
|
new CTexture (TEXTURE_LOGOS, LOGO_RESOLUTION, true, false, true);
|
||||||
|
for (int i = TEXTURE_BUILDING1; i <= TEXTURE_BUILDING9; i++)
|
||||||
|
new CTexture (i, 512, true, false, false);
|
||||||
|
new CTexture (TEXTURE_BLOOM, 512, true, false, false);
|
||||||
|
int names = PREFIX_COUNT * NAME_COUNT + SUFFIX_COUNT * NAME_COUNT;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
#define SEGMENTS_PER_TEXTURE 64
|
||||||
|
#define ONE_SEGMENT (1.0f / SEGMENTS_PER_TEXTURE)
|
||||||
|
#define LANES_PER_TEXTURE 8
|
||||||
|
#define LANE_SIZE (1.0f / LANES_PER_TEXTURE)
|
||||||
|
#define LANE_PIXELS (_size / LANES_PER_TEXTURE)
|
||||||
|
#define TRIM_RESOLUTION 256
|
||||||
|
#define TRIM_ROWS 4
|
||||||
|
#define TRIM_SIZE (1.0f / TRIM_ROWS)
|
||||||
|
#define TRIM_PIXELS (TRIM_RESOLUTION / TRIM_ROWS)
|
||||||
|
#define LOGO_RESOLUTION 512
|
||||||
|
#define LOGO_ROWS 16
|
||||||
|
#define LOGO_SIZE (1.0f / LOGO_ROWS)
|
||||||
|
#define LOGO_PIXELS (LOGO_RESOLUTION / LOGO_ROWS)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TEXTURE_GROUND,
|
||||||
|
TEXTURE_LIGHT,
|
||||||
|
TEXTURE_SOFT_CIRCLE,
|
||||||
|
TEXTURE_SKY,
|
||||||
|
TEXTURE_CLOUDS,
|
||||||
|
TEXTURE_LOGOS,
|
||||||
|
TEXTURE_TRIM,
|
||||||
|
TEXTURE_BLOOM,
|
||||||
|
TEXTURE_HEADLIGHT,
|
||||||
|
TEXTURE_LATTICE,
|
||||||
|
TEXTURE_BUILDING1,
|
||||||
|
TEXTURE_BUILDING2,
|
||||||
|
TEXTURE_BUILDING3,
|
||||||
|
TEXTURE_BUILDING4,
|
||||||
|
TEXTURE_BUILDING5,
|
||||||
|
TEXTURE_BUILDING6,
|
||||||
|
TEXTURE_BUILDING7,
|
||||||
|
TEXTURE_BUILDING8,
|
||||||
|
TEXTURE_BUILDING9,
|
||||||
|
TEXTURE_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BUILDING_COUNT ((TEXTURE_BUILDING9 - TEXTURE_BUILDING1) + 1)
|
||||||
|
|
||||||
|
unsigned TextureFromName (char* name);
|
||||||
|
unsigned TextureId (int id);
|
||||||
|
void TextureInit (void);
|
||||||
|
void TextureTerm (void);
|
||||||
|
unsigned TextureRandomBuilding (int index);
|
||||||
|
bool TextureReady ();
|
||||||
|
void TextureReset (void);
|
||||||
|
void TextureUpdate (void);
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Visible.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This module runs the visibility grid, a 2-dimensional array that aids in
|
||||||
|
culling objects during rendering.
|
||||||
|
|
||||||
|
There are many ways this could be refined or sped up, although tests indicate
|
||||||
|
it's not a huge drain on performance.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "glTypes.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "visible.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
static bool vis_grid[GRID_SIZE][GRID_SIZE];
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool Visible (GLvector pos)
|
||||||
|
{
|
||||||
|
|
||||||
|
return vis_grid[WORLD_TO_GRID(pos.x)][WORLD_TO_GRID(pos.z)];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool Visible (int x, int z)
|
||||||
|
{
|
||||||
|
|
||||||
|
return vis_grid[x][z];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void VisibleUpdate (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector angle;
|
||||||
|
GLvector position;
|
||||||
|
int x, y, grid_x, grid_z;
|
||||||
|
int left, right, front, back;
|
||||||
|
float angle_to;
|
||||||
|
float angle_diff;
|
||||||
|
float target_x, target_z;
|
||||||
|
|
||||||
|
LIMIT_INTERVAL (50);
|
||||||
|
//Clear the visibility table
|
||||||
|
ZeroMemory (vis_grid, sizeof (vis_grid));
|
||||||
|
//Calculate which cell the camera is in
|
||||||
|
angle = CameraAngle ();
|
||||||
|
position = CameraPosition ();
|
||||||
|
grid_x = WORLD_TO_GRID(position.x);
|
||||||
|
grid_z = WORLD_TO_GRID(position.z);
|
||||||
|
//Cells directly adjactent to the camera might technically fall out of the fov,
|
||||||
|
//but still have a few objects poking into screenspace when looking up or down.
|
||||||
|
//Rather than obsess over sorting those objects properly, it's more efficient to
|
||||||
|
//just mark them visible.
|
||||||
|
left = right = front = back = 3;
|
||||||
|
//Looking north, can't see south.
|
||||||
|
if (angle.y < 45.0f || angle.y > 315.0f)
|
||||||
|
front = 0;
|
||||||
|
//Looking south, can't see north
|
||||||
|
if (angle.y > 135.0f && angle.y < 225.0f)
|
||||||
|
back = 0;
|
||||||
|
//Looking east, can't see west
|
||||||
|
if (angle.y > 45.0f && angle.y < 135.0f)
|
||||||
|
left = 0;
|
||||||
|
//Looking west, can't see east
|
||||||
|
if (angle.y > 225.0f && angle.y < 315.0f)
|
||||||
|
right = 0;
|
||||||
|
//Now mark the block around us the might be visible
|
||||||
|
for (x = grid_x - left; x <= grid_x + right; x++) {
|
||||||
|
if (x < 0 || x >= WORLD_SIZE) //just in case the camera leaves the world map
|
||||||
|
continue;
|
||||||
|
for (y = grid_z - back; y <= grid_z + front; y++) {
|
||||||
|
if (y < 0 || y >= WORLD_SIZE) //just in case the camera leaves the world map
|
||||||
|
continue;
|
||||||
|
vis_grid[x][y] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Doesn't matter where we are facing, objects in current cell are always visible
|
||||||
|
vis_grid[grid_x][grid_z] = true;
|
||||||
|
//Here, we look at the angle from the current camera position to the cell
|
||||||
|
//on the grid, and how much that angle deviates from the current view angle.
|
||||||
|
for (x = 0; x < GRID_SIZE; x++) {
|
||||||
|
for (y = 0; y < GRID_SIZE; y++) {
|
||||||
|
//if we marked it visible earlier, skip all this math
|
||||||
|
if (vis_grid[x][y])
|
||||||
|
continue;
|
||||||
|
//if the camera is to the left of this cell, use the left edge
|
||||||
|
if (grid_x < x)
|
||||||
|
target_x = (float)x * GRID_RESOLUTION;
|
||||||
|
else
|
||||||
|
target_x = (float)(x + 1) * GRID_RESOLUTION;
|
||||||
|
if (grid_z < y)
|
||||||
|
target_z = (float)y * GRID_RESOLUTION;
|
||||||
|
else
|
||||||
|
target_z = (float)(y + 1) * GRID_RESOLUTION;
|
||||||
|
angle_to = 180 - MathAngle (target_x, target_z, position.x, position.z);
|
||||||
|
//Store how many degrees the cell is to the
|
||||||
|
angle_diff = (float)fabs (MathAngleDifference (angle.y, angle_to));
|
||||||
|
vis_grid[x][y] = angle_diff < 45;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#define GRID_RESOLUTION 32
|
||||||
|
#define GRID_CELL (GRID_RESOLUTION / 2)
|
||||||
|
#define GRID_SIZE (WORLD_SIZE / GRID_RESOLUTION)
|
||||||
|
#define WORLD_TO_GRID(x) (int)(x / GRID_RESOLUTION)
|
||||||
|
#define GRID_TO_WORLD(x) ((float)x * GRID_RESOLUTION)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void VisibleUpdate (void);
|
||||||
|
bool Visible (GLvector pos);
|
||||||
|
bool Visible (int x, int z);
|
|
@ -0,0 +1,608 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Win.cpp
|
||||||
|
|
||||||
|
2006 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Create the main window and make it go.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define MOUSE_MOVEMENT 0.5f
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <scrnsave.h>
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
|
#include "car.h"
|
||||||
|
#include "entity.h"
|
||||||
|
#include "glTypes.h"
|
||||||
|
#include "ini.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "win.h"
|
||||||
|
#include "world.h"
|
||||||
|
#include "visible.h"
|
||||||
|
|
||||||
|
|
||||||
|
#pragma comment (lib, "opengl32.lib")
|
||||||
|
#pragma comment (lib, "glu32.lib")
|
||||||
|
#pragma comment (lib, "GLaux.lib")
|
||||||
|
#if SCREENSAVER
|
||||||
|
#pragma comment (lib, "scrnsave.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static HWND hwnd;
|
||||||
|
static HINSTANCE module;
|
||||||
|
static int width;
|
||||||
|
static int height;
|
||||||
|
static int half_width;
|
||||||
|
static int half_height;
|
||||||
|
static bool lmb;
|
||||||
|
static bool rmb;
|
||||||
|
static bool mouse_forced;
|
||||||
|
static POINT select_pos;
|
||||||
|
static POINT mouse_pos;
|
||||||
|
|
||||||
|
static bool quit;
|
||||||
|
static HINSTANCE instance;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CenterCursor ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int center_x;
|
||||||
|
int center_y;
|
||||||
|
RECT rect;
|
||||||
|
|
||||||
|
SetCursor (NULL);
|
||||||
|
mouse_forced = true;
|
||||||
|
GetWindowRect (hwnd, &rect);
|
||||||
|
center_x = rect.left + (rect.right - rect.left) / 2;
|
||||||
|
center_y = rect.top + (rect.bottom - rect.top) / 2;
|
||||||
|
SetCursorPos (center_x, center_y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void MoveCursor (int x, int y)
|
||||||
|
{
|
||||||
|
|
||||||
|
int center_x;
|
||||||
|
int center_y;
|
||||||
|
RECT rect;
|
||||||
|
|
||||||
|
SetCursor (NULL);
|
||||||
|
mouse_forced = true;
|
||||||
|
GetWindowRect (hwnd, &rect);
|
||||||
|
center_x = rect.left + x;
|
||||||
|
center_y = rect.top + y;
|
||||||
|
SetCursorPos (center_x, center_y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
RECT r;
|
||||||
|
float delta_x, delta_y;
|
||||||
|
POINT p;
|
||||||
|
int param;
|
||||||
|
int key;
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
|
case WM_SIZE:
|
||||||
|
param = wParam; // resizing flag
|
||||||
|
width = LOWORD(lParam); // width of client area
|
||||||
|
height = HIWORD(lParam); // height of client area
|
||||||
|
|
||||||
|
if (param == SIZE_RESTORED)
|
||||||
|
IniIntSet ("WindowMaximized", 0);
|
||||||
|
if (param == SIZE_MAXIMIZED) {
|
||||||
|
IniIntSet ("WindowMaximized", 1);
|
||||||
|
} else {
|
||||||
|
IniIntSet ("WindowWidth", width);
|
||||||
|
IniIntSet ("WindowHeight", height);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case WM_MOVE:
|
||||||
|
GetClientRect (hwnd, &r);
|
||||||
|
height = r.bottom - r.top;
|
||||||
|
width = r.right - r.left;
|
||||||
|
IniIntSet ("WindowX", r.left);
|
||||||
|
IniIntSet ("WindowY", r.top);
|
||||||
|
IniIntSet ("WindowWidth", width);
|
||||||
|
IniIntSet ("WindowHeight", height);
|
||||||
|
half_width = width / 2;
|
||||||
|
half_height = height / 2;
|
||||||
|
break;
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
key = (int) wParam;
|
||||||
|
|
||||||
|
if (key == 'R')
|
||||||
|
WorldReset ();
|
||||||
|
if (key == 'C')
|
||||||
|
CameraAutoToggle ();
|
||||||
|
if (key == 'W')
|
||||||
|
RenderWireframeToggle ();
|
||||||
|
if (key == 'E')
|
||||||
|
RenderEffectCycle ();
|
||||||
|
if (key == 'L')
|
||||||
|
RenderLetterboxToggle ();
|
||||||
|
if (key == 'F')
|
||||||
|
RenderFPSToggle ();
|
||||||
|
if (key == 'G')
|
||||||
|
RenderFogToggle ();
|
||||||
|
if (key == 'T')
|
||||||
|
RenderFlatToggle ();
|
||||||
|
if (key == VK_F1)
|
||||||
|
RenderHelpToggle ();
|
||||||
|
if (key == 'B')
|
||||||
|
CameraNextBehavior ();
|
||||||
|
if (key == VK_ESCAPE)
|
||||||
|
quit = true;
|
||||||
|
if (key == VK_F5)
|
||||||
|
CameraReset ();
|
||||||
|
return 0;
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
lmb = true;
|
||||||
|
SetCapture (hwnd);
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
rmb = true;
|
||||||
|
SetCapture (hwnd);
|
||||||
|
break;
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
lmb = false;
|
||||||
|
if (!rmb) {
|
||||||
|
ReleaseCapture ();
|
||||||
|
MoveCursor (select_pos.x, select_pos.y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
rmb = false;
|
||||||
|
if (!lmb) {
|
||||||
|
ReleaseCapture ();
|
||||||
|
MoveCursor (select_pos.x, select_pos.y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
p.x = LOWORD(lParam); // horizontal position of cursor
|
||||||
|
p.y = HIWORD(lParam); // vertical position of cursor
|
||||||
|
if (p.x < 0 || p.x > width)
|
||||||
|
break;
|
||||||
|
if (p.y < 0 || p.y > height)
|
||||||
|
break;
|
||||||
|
if (!mouse_forced && !lmb && !rmb) {
|
||||||
|
select_pos = p;
|
||||||
|
}
|
||||||
|
if (mouse_forced) {
|
||||||
|
mouse_forced = false;
|
||||||
|
} else if (rmb || lmb) {
|
||||||
|
CenterCursor ();
|
||||||
|
delta_x = (float)(mouse_pos.x - p.x) * MOUSE_MOVEMENT;
|
||||||
|
delta_y = (float)(mouse_pos.y - p.y) * MOUSE_MOVEMENT;
|
||||||
|
if (rmb && lmb) {
|
||||||
|
GLvector pos;
|
||||||
|
CameraPan (delta_x);
|
||||||
|
pos = CameraPosition ();
|
||||||
|
pos.y += delta_y;
|
||||||
|
CameraPositionSet (pos);
|
||||||
|
} else if (rmb) {
|
||||||
|
CameraPan (delta_x);
|
||||||
|
CameraForward (delta_y);
|
||||||
|
} else if (lmb) {
|
||||||
|
GLvector angle;
|
||||||
|
angle = CameraAngle ();
|
||||||
|
angle.y -= delta_x;
|
||||||
|
angle.x += delta_y;
|
||||||
|
CameraAngleSet (angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mouse_pos = p;
|
||||||
|
break;
|
||||||
|
case WM_CLOSE:
|
||||||
|
quit = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
HINSTANCE WinInstance ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
n o t e
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void WinPopup (char* message, ...)
|
||||||
|
{
|
||||||
|
|
||||||
|
va_list marker;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
va_start (marker, message);
|
||||||
|
vsprintf (buf, message, marker);
|
||||||
|
va_end (marker);
|
||||||
|
MessageBox (NULL, buf, APP_TITLE, MB_ICONSTOP | MB_OK |
|
||||||
|
MB_TASKMODAL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int WinWidth (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return width;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void WinMousePosition (int* x, int* y)
|
||||||
|
{
|
||||||
|
|
||||||
|
*x = select_pos.x;
|
||||||
|
*y = select_pos.y;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int WinHeight (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return height;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void WinTerm (void)
|
||||||
|
{
|
||||||
|
#if !SCREENAVER
|
||||||
|
DestroyWindow (hwnd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
HWND WinHwnd (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return hwnd;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool WinInit (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
WNDCLASSEX wcex;
|
||||||
|
int x, y;
|
||||||
|
int style;
|
||||||
|
bool max;
|
||||||
|
|
||||||
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wcex.lpfnWndProc = (WNDPROC)WndProc;
|
||||||
|
wcex.cbClsExtra = 0;
|
||||||
|
wcex.cbWndExtra = 0;
|
||||||
|
wcex.hInstance = instance;
|
||||||
|
wcex.hIcon = NULL;
|
||||||
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
|
||||||
|
wcex.lpszMenuName = NULL;
|
||||||
|
wcex.lpszClassName = APP_TITLE;
|
||||||
|
wcex.hIconSm = NULL;
|
||||||
|
if (!RegisterClassEx(&wcex)) {
|
||||||
|
WinPopup ("Cannot create window class");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
x = IniInt ("WindowX");
|
||||||
|
y = IniInt ("WindowY");
|
||||||
|
style = WS_TILEDWINDOW;
|
||||||
|
style |= WS_MAXIMIZE;
|
||||||
|
width = IniInt ("WindowWidth");
|
||||||
|
height = IniInt ("WindowHeight");
|
||||||
|
width = CLAMP (width, 800, 2048);
|
||||||
|
height = CLAMP (height, 600, 2048);
|
||||||
|
half_width = width / 2;
|
||||||
|
half_height = height / 2;
|
||||||
|
max = IniInt ("WindowMaximized") == 1;
|
||||||
|
if (!(hwnd = CreateWindowEx (0, APP_TITLE, APP_TITLE, style,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, instance, NULL))) {
|
||||||
|
WinPopup ("Cannot create window");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (max)
|
||||||
|
ShowWindow (hwnd, SW_MAXIMIZE);
|
||||||
|
else
|
||||||
|
ShowWindow (hwnd, SW_SHOW);
|
||||||
|
UpdateWindow (hwnd);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void AppQuit ()
|
||||||
|
{
|
||||||
|
|
||||||
|
quit = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void AppInit (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
RandomInit (1);
|
||||||
|
CameraInit ();
|
||||||
|
RenderInit ();
|
||||||
|
TextureInit ();
|
||||||
|
WorldInit ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void AppUpdate ()
|
||||||
|
{
|
||||||
|
|
||||||
|
CameraUpdate ();
|
||||||
|
WorldUpdate ();
|
||||||
|
TextureUpdate ();
|
||||||
|
VisibleUpdate ();
|
||||||
|
CarUpdate ();
|
||||||
|
EntityUpdate ();
|
||||||
|
RenderUpdate ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
W i n M a i n
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void AppTerm (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
TextureTerm ();
|
||||||
|
WorldTerm ();
|
||||||
|
RenderTerm ();
|
||||||
|
CameraTerm ();
|
||||||
|
WinTerm ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
W i n M a i n
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
#if !SCREENSAVER
|
||||||
|
|
||||||
|
int PASCAL WinMain (HINSTANCE instance_in, HINSTANCE previous_instance,
|
||||||
|
LPSTR command_line, int show_style)
|
||||||
|
{
|
||||||
|
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
instance = instance_in;
|
||||||
|
WinInit ();
|
||||||
|
AppInit ();
|
||||||
|
while (!quit) {
|
||||||
|
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
|
||||||
|
if (msg.message == WM_QUIT)
|
||||||
|
quit = true;
|
||||||
|
else {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AppUpdate ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AppTerm ();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static bool terminated;
|
||||||
|
|
||||||
|
LONG WINAPI ScreenSaverProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
|
||||||
|
RECT r;
|
||||||
|
float delta_x, delta_y;
|
||||||
|
POINT p;
|
||||||
|
int param;
|
||||||
|
int key;
|
||||||
|
|
||||||
|
if (terminated)
|
||||||
|
return DefScreenSaverProc (hWnd, msg, wParam, lParam);
|
||||||
|
switch (msg) {
|
||||||
|
case WM_CREATE:
|
||||||
|
hwnd = hWnd;
|
||||||
|
AppInit ();
|
||||||
|
return 0;
|
||||||
|
case WM_CLOSE:
|
||||||
|
case WM_DESTROY:
|
||||||
|
AppTerm ();
|
||||||
|
terminated = true;
|
||||||
|
return 0;
|
||||||
|
case WM_PAINT:
|
||||||
|
AppUpdate ();
|
||||||
|
return 0;
|
||||||
|
case WM_SIZE:
|
||||||
|
param = wParam; // resizing flag
|
||||||
|
width = LOWORD(lParam); // width of client area
|
||||||
|
height = HIWORD(lParam); // height of client area
|
||||||
|
|
||||||
|
if (param == SIZE_MAXIMIZED) {
|
||||||
|
IniIntSet ("WindowMaximized", 1);
|
||||||
|
} else {
|
||||||
|
IniIntSet ("WindowWidth", width);
|
||||||
|
IniIntSet ("WindowHeight", height);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case WM_MOVE:
|
||||||
|
GetClientRect (hwnd, &r);
|
||||||
|
height = r.bottom - r.top;
|
||||||
|
width = r.right - r.left;
|
||||||
|
IniIntSet ("WindowX", r.left);
|
||||||
|
IniIntSet ("WindowY", r.top);
|
||||||
|
IniIntSet ("WindowWidth", width);
|
||||||
|
IniIntSet ("WindowHeight", height);
|
||||||
|
half_width = width / 2;
|
||||||
|
half_height = height / 2;
|
||||||
|
break;
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
key = (int) wParam;
|
||||||
|
|
||||||
|
if (key == 'R')
|
||||||
|
WorldReset ();
|
||||||
|
else if (key == 'C')
|
||||||
|
CameraAutoToggle ();
|
||||||
|
else if (key == 'W')
|
||||||
|
RenderWireframeToggle ();
|
||||||
|
else if (key == 'E')
|
||||||
|
RenderEffectCycle ();
|
||||||
|
else if (key == 'L')
|
||||||
|
RenderLetterboxToggle ();
|
||||||
|
else if (key == 'F')
|
||||||
|
RenderFPSToggle ();
|
||||||
|
else if (key == 'G')
|
||||||
|
RenderFogToggle ();
|
||||||
|
else if (key == 'T')
|
||||||
|
RenderFlatToggle ();
|
||||||
|
else if (key == VK_F1)
|
||||||
|
RenderHelpToggle ();
|
||||||
|
else if (key == VK_ESCAPE)
|
||||||
|
break;
|
||||||
|
else if (key == VK_F5)
|
||||||
|
CameraReset ();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
return 0;
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
lmb = true;
|
||||||
|
SetCapture (hwnd);
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
rmb = true;
|
||||||
|
SetCapture (hwnd);
|
||||||
|
break;
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
lmb = false;
|
||||||
|
if (!rmb) {
|
||||||
|
ReleaseCapture ();
|
||||||
|
MoveCursor (select_pos.x, select_pos.y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
rmb = false;
|
||||||
|
if (!lmb) {
|
||||||
|
ReleaseCapture ();
|
||||||
|
MoveCursor (select_pos.x, select_pos.y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
p.x = LOWORD(lParam); // horizontal position of cursor
|
||||||
|
p.y = HIWORD(lParam); // vertical position of cursor
|
||||||
|
if (p.x < 0 || p.x > width)
|
||||||
|
break;
|
||||||
|
if (p.y < 0 || p.y > height)
|
||||||
|
break;
|
||||||
|
if (!mouse_forced && !lmb && !rmb) {
|
||||||
|
select_pos = p;
|
||||||
|
}
|
||||||
|
if (mouse_forced) {
|
||||||
|
mouse_forced = false;
|
||||||
|
} else if (rmb || lmb) {
|
||||||
|
CenterCursor ();
|
||||||
|
delta_x = (float)(mouse_pos.x - p.x) * MOUSE_MOVEMENT;
|
||||||
|
delta_y = (float)(mouse_pos.y - p.y) * MOUSE_MOVEMENT;
|
||||||
|
if (rmb && lmb) {
|
||||||
|
GLvector pos;
|
||||||
|
CameraPan (delta_x);
|
||||||
|
pos = CameraPosition ();
|
||||||
|
pos.y += delta_y;
|
||||||
|
CameraPositionSet (pos);
|
||||||
|
} else if (rmb) {
|
||||||
|
CameraPan (delta_x);
|
||||||
|
CameraForward (delta_y);
|
||||||
|
} else if (lmb) {
|
||||||
|
GLvector angle;
|
||||||
|
angle = CameraAngle ();
|
||||||
|
angle.y -= delta_x;
|
||||||
|
angle.x += delta_y;
|
||||||
|
CameraAngleSet (angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mouse_pos = p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return DefScreenSaverProc (hWnd, msg, wParam, lParam);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { return FALSE; }
|
||||||
|
BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,12 @@
|
||||||
|
#define APP_TITLE "PixelCity"
|
||||||
|
#define APP "pixelcity"
|
||||||
|
#define SCREENSAVER 0
|
||||||
|
|
||||||
|
|
||||||
|
HWND WinHwnd (void);
|
||||||
|
void WinPopup (char* message, ...);
|
||||||
|
void WinTerm (void);
|
||||||
|
bool WinInit (void);
|
||||||
|
int WinWidth (void);
|
||||||
|
int WinHeight (void);
|
||||||
|
void WinMousePosition (int* x, int* y);
|
|
@ -0,0 +1,745 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
World.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This holds a bunch of variables used by the other modules. It has the
|
||||||
|
claim system, which tracks all of the "property" is being used: As roads,
|
||||||
|
buildings, etc.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define HUE_COUNT (sizeof(hue_list)/sizeof(float))
|
||||||
|
#define LIGHT_COLOR_COUNT (sizeof(light_colors)/sizeof(HSL))
|
||||||
|
#define CARS 600
|
||||||
|
#define WORLD_EDGE 200
|
||||||
|
#if SCREENSAVER
|
||||||
|
#define RESET_INTERVAL 120 //seconds
|
||||||
|
#define FADE_TIME 500 //milliseconds
|
||||||
|
#else
|
||||||
|
#define RESET_INTERVAL 999 //seconds
|
||||||
|
#define FADE_TIME 1500 //milliseconds
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include <gl\glu.h>
|
||||||
|
#include <gl\glaux.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "glTypes.h"
|
||||||
|
#include "building.h"
|
||||||
|
#include "car.h"
|
||||||
|
#include "deco.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "light.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "sky.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "visible.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
struct plot
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int z;
|
||||||
|
int width;
|
||||||
|
int depth;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FADE_IDLE,
|
||||||
|
FADE_OUT,
|
||||||
|
FADE_WAIT,
|
||||||
|
FADE_IN,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HSL
|
||||||
|
{
|
||||||
|
float hue;
|
||||||
|
float sat;
|
||||||
|
float lum;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CStreet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int _x;
|
||||||
|
int _y;
|
||||||
|
int _width;
|
||||||
|
int _depth;
|
||||||
|
CMesh* _mesh;
|
||||||
|
|
||||||
|
CStreet (int x, int y, int width, int depth);
|
||||||
|
~CStreet();
|
||||||
|
void Render ();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static HSL light_colors[] =
|
||||||
|
{
|
||||||
|
0.04f, 0.9f, 0.93f, //Amber / pink
|
||||||
|
0.055f, 0.95f, 0.93f, //Slightly brighter amber
|
||||||
|
0.08f, 0.7f, 0.93f, //Very pale amber
|
||||||
|
0.07f, 0.9f, 0.93f, //Very pale orange
|
||||||
|
0.1f, 0.9f, 0.85f, //Peach
|
||||||
|
0.13f, 0.9f, 0.93f, //Pale Yellow
|
||||||
|
0.15f, 0.9f, 0.93f, //Yellow
|
||||||
|
0.17f, 1.0f, 0.85f, //Saturated Yellow
|
||||||
|
0.55f, 0.9f, 0.93f, //Cyan
|
||||||
|
0.55f, 0.9f, 0.93f, //Cyan - pale, almost white
|
||||||
|
0.6f, 0.9f, 0.93f, //Pale blue
|
||||||
|
0.65f, 0.9f, 0.93f, //Pale Blue II, The Palening
|
||||||
|
0.65f, 0.4f, 0.99f, //Pure white. Bo-ring.
|
||||||
|
0.65f, 0.0f, 0.8f, //Dimmer white.
|
||||||
|
0.65f, 0.0f, 0.6f, //Dimmest white.
|
||||||
|
};
|
||||||
|
|
||||||
|
static float hue_list[] = { 0.04f, 0.07f, 0.1f, 0.5f, 0.6f }; //Yellows and blues - good for lights
|
||||||
|
static GLrgba bloom_color;
|
||||||
|
static long last_update;
|
||||||
|
static char world[WORLD_SIZE][WORLD_SIZE];
|
||||||
|
static CSky* sky;
|
||||||
|
static int fade_state;
|
||||||
|
static unsigned fade_start;
|
||||||
|
static float fade_current;
|
||||||
|
static int modern_count;
|
||||||
|
static int tower_count;
|
||||||
|
static int blocky_count;
|
||||||
|
static bool reset_needed;
|
||||||
|
static int skyscrapers;
|
||||||
|
static GLbbox hot_zone;
|
||||||
|
static unsigned start_time;
|
||||||
|
static int logo_index;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static GLrgba get_light_color (float sat, float lum)
|
||||||
|
{
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
index = RandomVal (LIGHT_COLOR_COUNT);
|
||||||
|
return glRgbaFromHsl (light_colors[index].hue, sat, lum);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void claim (int x, int y, int width, int depth, int val)
|
||||||
|
{
|
||||||
|
|
||||||
|
int xx, yy;
|
||||||
|
|
||||||
|
for (xx = x; xx < (x + width); xx++) {
|
||||||
|
for (yy = y; yy < (y + depth); yy++) {
|
||||||
|
world[CLAMP (xx,0,WORLD_SIZE - 1)][CLAMP (yy,0,WORLD_SIZE - 1)] |= val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static bool claimed (int x, int y, int width, int depth)
|
||||||
|
{
|
||||||
|
|
||||||
|
int xx, yy;
|
||||||
|
|
||||||
|
for (xx = x; xx < x + width; xx++) {
|
||||||
|
for (yy = y; yy < y + depth; yy++) {
|
||||||
|
if (world[CLAMP (xx,0,WORLD_SIZE - 1)][CLAMP (yy,0,WORLD_SIZE - 1)])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void build_road (int x1, int y1, int width, int depth)
|
||||||
|
{
|
||||||
|
|
||||||
|
int lanes;
|
||||||
|
int divider;
|
||||||
|
int sidewalk;
|
||||||
|
|
||||||
|
//the given rectangle defines a street and its sidewalk. See which way it goes.
|
||||||
|
if (width > depth)
|
||||||
|
lanes = depth;
|
||||||
|
else
|
||||||
|
lanes = width;
|
||||||
|
//if we dont have room for both lanes and sidewalk, abort
|
||||||
|
if (lanes < 4)
|
||||||
|
return;
|
||||||
|
//if we have an odd number of lanes, give the extra to a divider.
|
||||||
|
if (lanes % 2) {
|
||||||
|
lanes--;
|
||||||
|
divider = 1;
|
||||||
|
} else
|
||||||
|
divider = 0;
|
||||||
|
//no more than 10 traffic lanes, give the rest to sidewalks
|
||||||
|
sidewalk = MAX (2, (lanes - 10));
|
||||||
|
lanes -= sidewalk;
|
||||||
|
sidewalk /= 2;
|
||||||
|
//take the remaining space and give half to each direction
|
||||||
|
lanes /= 2;
|
||||||
|
//Mark the entire rectangle as used
|
||||||
|
claim (x1, y1, width, depth, CLAIM_WALK);
|
||||||
|
//now place the directional roads
|
||||||
|
if (width > depth) {
|
||||||
|
claim (x1, y1 + sidewalk, width, lanes, CLAIM_ROAD | MAP_ROAD_WEST);
|
||||||
|
claim (x1, y1 + sidewalk + lanes + divider, width, lanes, CLAIM_ROAD | MAP_ROAD_EAST);
|
||||||
|
} else {
|
||||||
|
claim (x1 + sidewalk, y1, lanes, depth, CLAIM_ROAD | MAP_ROAD_SOUTH);
|
||||||
|
claim (x1 + sidewalk + lanes + divider, y1, lanes, depth, CLAIM_ROAD | MAP_ROAD_NORTH);
|
||||||
|
}
|
||||||
|
//new CStreet (x1, y1, width, depth);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static plot find_plot (int x, int z)
|
||||||
|
{
|
||||||
|
|
||||||
|
plot p;
|
||||||
|
int x1, x2, z1, z2;
|
||||||
|
|
||||||
|
//We've been given the location of an open bit of land, but we have no
|
||||||
|
//idea how big it is. Find the boundary.
|
||||||
|
x1 = x2 = x;
|
||||||
|
while (!claimed (x1 - 1, z, 1, 1) && x1 > 0)
|
||||||
|
x1--;
|
||||||
|
while (!claimed (x2 + 1, z, 1, 1) && x2 < WORLD_SIZE)
|
||||||
|
x2++;
|
||||||
|
z1 = z2 = z;
|
||||||
|
while (!claimed (x, z1 - 1, 1, 1) && z1 > 0)
|
||||||
|
z1--;
|
||||||
|
while (!claimed (x, z2 + 1, 1, 1) && z2 < WORLD_SIZE)
|
||||||
|
z2++;
|
||||||
|
p.width = (x2 - x1);
|
||||||
|
p.depth = (z2 - z1);
|
||||||
|
p.x = x1;
|
||||||
|
p.z = z1;
|
||||||
|
return p;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static plot make_plot (int x, int z, int width, int depth)
|
||||||
|
{
|
||||||
|
|
||||||
|
plot p = {x, z, width, depth};
|
||||||
|
return p;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void do_building (plot p)
|
||||||
|
{
|
||||||
|
|
||||||
|
int height;
|
||||||
|
int seed;
|
||||||
|
int area;
|
||||||
|
int type;
|
||||||
|
GLrgba color;
|
||||||
|
bool square;
|
||||||
|
|
||||||
|
//now we know how big the rectangle plot is.
|
||||||
|
area = p.width * p.depth;
|
||||||
|
color = WorldLightColor (RandomVal ());
|
||||||
|
seed = RandomVal ();
|
||||||
|
//Make sure the plot is big enough for a building
|
||||||
|
if (p.width < 10 || p.depth < 10)
|
||||||
|
return;
|
||||||
|
//If the area is too big for one building, sub-divide it.
|
||||||
|
if (area > 600) {
|
||||||
|
if (p.width > p.depth) {
|
||||||
|
p.width /= 2;
|
||||||
|
if (COIN_FLIP)
|
||||||
|
do_building (make_plot (p.x, p.z, p.width, p.depth));
|
||||||
|
else
|
||||||
|
do_building (make_plot (p.x + p.width, p.z, p.width, p.depth));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
p.depth /= 2;
|
||||||
|
if (COIN_FLIP)
|
||||||
|
do_building (make_plot (p.x, p.z, p.width, p.depth));
|
||||||
|
else
|
||||||
|
do_building (make_plot (p.x, p.z + p.depth, p.width, p.depth));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (area < 100)
|
||||||
|
return;
|
||||||
|
//The plot is "square" if width & depth are close
|
||||||
|
square = abs (p.width - p.depth) < 10;
|
||||||
|
//mark the land as used so other buildings don't appear here, even if we don't use it all.
|
||||||
|
claim (p.x, p.z, p.width, p.depth, CLAIM_BUILDING);
|
||||||
|
//The roundy mod buildings look best on square plots.
|
||||||
|
if (square && p.width > 20) {
|
||||||
|
height = 45 + RandomVal (10);
|
||||||
|
modern_count++;
|
||||||
|
skyscrapers++;
|
||||||
|
new CBuilding (BUILDING_MODERN, p.x, p.z, height, p.width, p.depth, seed, color);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//This spot isn't ideal for any particular building, but try to keep a good mix
|
||||||
|
if (tower_count < modern_count && tower_count < blocky_count) {
|
||||||
|
type = BUILDING_TOWER;
|
||||||
|
tower_count++;
|
||||||
|
} else if (blocky_count < modern_count) {
|
||||||
|
type = BUILDING_BLOCKY;
|
||||||
|
blocky_count++;
|
||||||
|
} else {
|
||||||
|
type = BUILDING_MODERN;
|
||||||
|
modern_count++;
|
||||||
|
}
|
||||||
|
height = 45 + RandomVal (10);
|
||||||
|
new CBuilding (type, p.x, p.z, height, p.width, p.depth, seed, color);
|
||||||
|
skyscrapers++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int build_light_strip (int x1, int z1, int direction)
|
||||||
|
{
|
||||||
|
|
||||||
|
CDeco* d;
|
||||||
|
GLrgba color;
|
||||||
|
int x2, z2;
|
||||||
|
int length;
|
||||||
|
int width, depth;
|
||||||
|
int dir_x, dir_z;
|
||||||
|
float size_adjust;
|
||||||
|
|
||||||
|
//We adjust the size of the lights with this.
|
||||||
|
size_adjust = 2.5f;
|
||||||
|
color = glRgbaFromHsl (0.09f, 0.99f, 0.85f);
|
||||||
|
switch (direction) {
|
||||||
|
case NORTH:
|
||||||
|
dir_z = 1; dir_x = 0;break;
|
||||||
|
case SOUTH:
|
||||||
|
dir_z = 1; dir_x = 0;break;
|
||||||
|
case EAST:
|
||||||
|
dir_z = 0; dir_x = 1;break;
|
||||||
|
case WEST:
|
||||||
|
dir_z = 0; dir_x = 1;break;
|
||||||
|
}
|
||||||
|
//So we know we're on the corner of an intersection
|
||||||
|
//look in the given until we reach the end of the sidewalk
|
||||||
|
x2 = x1;
|
||||||
|
z2 = z1;
|
||||||
|
length = 0;
|
||||||
|
while (x2 > 0 && x2 < WORLD_SIZE && z2 > 0 && z2 < WORLD_SIZE) {
|
||||||
|
if ((world[x2][z2] & CLAIM_ROAD))
|
||||||
|
break;
|
||||||
|
length++;
|
||||||
|
x2 += dir_x;
|
||||||
|
z2 += dir_z;
|
||||||
|
}
|
||||||
|
if (length < 10)
|
||||||
|
return length;
|
||||||
|
width = MAX (abs(x2 - x1), 1);
|
||||||
|
depth = MAX (abs(z2 - z1), 1);
|
||||||
|
d = new CDeco;
|
||||||
|
if (direction == EAST)
|
||||||
|
d->CreateLightStrip ((float)x1, (float)z1 - size_adjust, (float)width, (float)depth + size_adjust, 2, color);
|
||||||
|
else if (direction == WEST)
|
||||||
|
d->CreateLightStrip ((float)x1, (float)z1, (float)width, (float)depth + size_adjust, 2, color);
|
||||||
|
else if (direction == NORTH)
|
||||||
|
d->CreateLightStrip ((float)x1, (float)z1, (float)width + size_adjust, (float)depth, 2, color);
|
||||||
|
else
|
||||||
|
d->CreateLightStrip ((float)x1 - size_adjust, (float)z1, (float)width + size_adjust, (float)depth, 2, color);
|
||||||
|
return length;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void do_reset (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
int width, depth, height;
|
||||||
|
int attempts;
|
||||||
|
bool broadway_done;
|
||||||
|
bool road_left, road_right;
|
||||||
|
GLrgba light_color;
|
||||||
|
GLrgba building_color;
|
||||||
|
float west_street, north_street, east_street, south_street;
|
||||||
|
|
||||||
|
//RandomInit (6);
|
||||||
|
reset_needed = false;
|
||||||
|
broadway_done = false;
|
||||||
|
skyscrapers = 0;
|
||||||
|
logo_index = 0;
|
||||||
|
tower_count = blocky_count = modern_count = 0;
|
||||||
|
hot_zone = glBboxClear ();
|
||||||
|
EntityClear ();
|
||||||
|
LightClear ();
|
||||||
|
CarClear ();
|
||||||
|
TextureReset ();
|
||||||
|
//Pick a tint for the bloom
|
||||||
|
bloom_color = get_light_color(0.5f + (float)RandomVal (10) / 20.0f, 0.75f);
|
||||||
|
light_color = glRgbaFromHsl (0.11f, 1.0f, 0.65f);
|
||||||
|
ZeroMemory (world, WORLD_SIZE * WORLD_SIZE);
|
||||||
|
for (y = WORLD_EDGE; y < WORLD_SIZE - WORLD_EDGE; y += RandomVal (30) + 20) {
|
||||||
|
if (!broadway_done && y > WORLD_HALF - 20) {
|
||||||
|
build_road (0, y, WORLD_SIZE, 19);
|
||||||
|
y += 20;
|
||||||
|
broadway_done = true;
|
||||||
|
} else {
|
||||||
|
depth = 6 + RandomVal (6);
|
||||||
|
if (y < WORLD_HALF / 2)
|
||||||
|
north_street = (float)(y + depth / 2);
|
||||||
|
if (y < (WORLD_SIZE - WORLD_HALF / 2))
|
||||||
|
south_street = (float)(y + depth / 2);
|
||||||
|
build_road (0, y, WORLD_SIZE, depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
broadway_done = false;
|
||||||
|
for (x = WORLD_EDGE; x < WORLD_SIZE - WORLD_EDGE; x += RandomVal (30) + 20) {
|
||||||
|
if (!broadway_done && x > WORLD_HALF - 20) {
|
||||||
|
build_road (x, 0, 19, WORLD_SIZE);
|
||||||
|
x += 20;
|
||||||
|
broadway_done = true;
|
||||||
|
} else {
|
||||||
|
width = 6 + RandomVal (6);
|
||||||
|
if (x <= WORLD_HALF / 2)
|
||||||
|
west_street = (float)(x + width / 2);
|
||||||
|
if (x <= WORLD_HALF + WORLD_HALF / 2)
|
||||||
|
east_street = (float)(x + width / 2);
|
||||||
|
build_road (x, 0, width, WORLD_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//We kept track of the positions of streets that will outline the high-detail hot zone
|
||||||
|
//in the middle of the world. Save this in a bounding box so that later we can
|
||||||
|
//have the camera fly around without clipping through buildings.
|
||||||
|
hot_zone = glBboxContainPoint (hot_zone, glVector (west_street, 0.0f, north_street));
|
||||||
|
hot_zone = glBboxContainPoint (hot_zone, glVector (east_street, 0.0f, south_street));
|
||||||
|
|
||||||
|
//Scan for places to put runs of streetlights on the east & west side of the road
|
||||||
|
for (x = 1; x < WORLD_SIZE - 1; x++) {
|
||||||
|
for (y = 0; y < WORLD_SIZE; y++) {
|
||||||
|
//if this isn't a bit of sidewalk, then keep looking
|
||||||
|
if (!(world[x][y] & CLAIM_WALK))
|
||||||
|
continue;
|
||||||
|
//If it's used as a road, skip it.
|
||||||
|
if ((world[x][y] & CLAIM_ROAD))
|
||||||
|
continue;
|
||||||
|
road_left = (world[x + 1][y] & CLAIM_ROAD) != 0;
|
||||||
|
road_right = (world[x - 1][y] & CLAIM_ROAD) != 0;
|
||||||
|
//if the cells to our east and west are not road, then we're not on a corner.
|
||||||
|
if (!road_left && !road_right)
|
||||||
|
continue;
|
||||||
|
//if the cell to our east AND west is road, then we're on a median. skip it
|
||||||
|
if (road_left && road_right)
|
||||||
|
continue;
|
||||||
|
y += build_light_strip (x, y, road_right ? SOUTH : NORTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Scan for places to put runs of streetlights on the north & south side of the road
|
||||||
|
for (y = 1; y < WORLD_SIZE - 1; y++) {
|
||||||
|
for (x = 1; x < WORLD_SIZE - 1; x++) {
|
||||||
|
//if this isn't a bit of sidewalk, then keep looking
|
||||||
|
if (!(world[x][y] & CLAIM_WALK))
|
||||||
|
continue;
|
||||||
|
//If it's used as a road, skip it.
|
||||||
|
if ((world[x][y] & CLAIM_ROAD))
|
||||||
|
continue;
|
||||||
|
road_left = (world[x][y + 1] & CLAIM_ROAD) != 0;
|
||||||
|
road_right = (world[x][y - 1] & CLAIM_ROAD) != 0;
|
||||||
|
//if the cell to our east AND west is road, then we're on a median. skip it
|
||||||
|
if (road_left && road_right)
|
||||||
|
continue;
|
||||||
|
//if the cells to our north and south are not road, then we're not on a corner.
|
||||||
|
if (!road_left && !road_right)
|
||||||
|
continue;
|
||||||
|
x += build_light_strip (x, y, road_right ? EAST : WEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Scan over the center area of the map and place the big buildings
|
||||||
|
attempts = 0;
|
||||||
|
while (skyscrapers < 50 && attempts < 350) {
|
||||||
|
x = (WORLD_HALF / 2) + (RandomVal () % WORLD_HALF);
|
||||||
|
y = (WORLD_HALF / 2) + (RandomVal () % WORLD_HALF);
|
||||||
|
if (!claimed (x, y, 1,1)) {
|
||||||
|
do_building (find_plot (x, y));
|
||||||
|
skyscrapers++;
|
||||||
|
}
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
//now blanket the rest of the world with lesser buildings
|
||||||
|
for (x = 0; x < WORLD_SIZE; x ++) {
|
||||||
|
for (y = 0; y < WORLD_SIZE; y ++) {
|
||||||
|
if (world[CLAMP (x,0,WORLD_SIZE)][CLAMP (y,0,WORLD_SIZE)])
|
||||||
|
continue;
|
||||||
|
width = 12 + RandomVal (20);
|
||||||
|
depth = 12 + RandomVal (20);
|
||||||
|
height = MIN (width, depth);
|
||||||
|
if (x < 30 || y < 30 || x > WORLD_SIZE - 30 || y > WORLD_SIZE - 30)
|
||||||
|
height = RandomVal (15) + 20;
|
||||||
|
else if (x < WORLD_HALF / 2)
|
||||||
|
height /= 2;
|
||||||
|
while (width > 8 && depth > 8) {
|
||||||
|
if (!claimed (x, y, width, depth)) {
|
||||||
|
claim (x, y, width, depth,CLAIM_BUILDING);
|
||||||
|
building_color = WorldLightColor (RandomVal ());
|
||||||
|
//if we're out of the hot zone, use simple buildings
|
||||||
|
if (x < hot_zone.min.x || x > hot_zone.max.x || y < hot_zone.min.z || y > hot_zone.max.z) {
|
||||||
|
height = 5 + RandomVal (height) + RandomVal (height);
|
||||||
|
new CBuilding (BUILDING_SIMPLE, x + 1, y + 1, height, width - 2, depth - 2, RandomVal (), building_color);
|
||||||
|
} else { //use fancy buildings.
|
||||||
|
height = 15 + RandomVal (15);
|
||||||
|
width -=2;
|
||||||
|
depth -=2;
|
||||||
|
if (COIN_FLIP)
|
||||||
|
new CBuilding (BUILDING_TOWER, x + 1, y + 1, height, width, depth, RandomVal (), building_color);
|
||||||
|
else
|
||||||
|
new CBuilding (BUILDING_BLOCKY, x + 1, y + 1, height, width, depth, RandomVal (), building_color);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
width--;
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
//leave big gaps near the edge of the map, no need to pack detail there.
|
||||||
|
if (y < WORLD_EDGE || y > WORLD_SIZE - WORLD_EDGE)
|
||||||
|
y += 32;
|
||||||
|
}
|
||||||
|
//leave big gaps near the edge of the map
|
||||||
|
if (x < WORLD_EDGE || x > WORLD_SIZE - WORLD_EDGE)
|
||||||
|
x += 28;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This will return a random color which is suitible for light sources, taken
|
||||||
|
from a narrow group of hues. (Yellows, oranges, blues.)
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba WorldLightColor (unsigned index)
|
||||||
|
{
|
||||||
|
|
||||||
|
index %= LIGHT_COLOR_COUNT;
|
||||||
|
return glRgbaFromHsl (light_colors[index].hue, light_colors[index].sat, light_colors[index].lum);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
char WorldCell (int x, int y)
|
||||||
|
{
|
||||||
|
|
||||||
|
return world[CLAMP (x, 0,WORLD_SIZE - 1)][CLAMP (y, 0, WORLD_SIZE - 1)];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba WorldBloomColor ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return bloom_color;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int WorldLogoIndex ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return logo_index++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLbbox WorldHotZone ()
|
||||||
|
{
|
||||||
|
|
||||||
|
return hot_zone;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void WorldTerm (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void WorldReset (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
//If we're already fading out, then this is the developer hammering on the
|
||||||
|
//"rebuild" button. Let's hurry things up for the nice man...
|
||||||
|
if (fade_state == FADE_OUT)
|
||||||
|
do_reset ();
|
||||||
|
//If reset is called but the world isn't ready, then don't bother fading out.
|
||||||
|
//The program probably just started.
|
||||||
|
fade_state = FADE_OUT;
|
||||||
|
fade_start = GetTickCount ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void WorldRender ()
|
||||||
|
{
|
||||||
|
|
||||||
|
//Cheap - render the crappy one-texture streets
|
||||||
|
if (!SHOW_DEBUG_GROUND)
|
||||||
|
return;
|
||||||
|
glDepthMask (false);
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glDisable (GL_BLEND);
|
||||||
|
glEnable (GL_TEXTURE_2D);
|
||||||
|
glColor3f (1,1,1);
|
||||||
|
glBindTexture (GL_TEXTURE_2D, TextureId (TEXTURE_GROUND));
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glTexCoord2f (0, 0); glVertex3f ( 0., 0, 0);
|
||||||
|
glTexCoord2f (0, 1); glVertex3f ( 0, 0, 1024);
|
||||||
|
glTexCoord2f (1, 1); glVertex3f ( 1024, 0, 1024);
|
||||||
|
glTexCoord2f (1, 0); glVertex3f ( 1024, 0, 0);
|
||||||
|
glEnd ();
|
||||||
|
glDepthMask (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float WorldFade (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return fade_current;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void WorldUpdate (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned fade_delta;
|
||||||
|
unsigned now, elapsed;
|
||||||
|
|
||||||
|
now = GetTickCount ();
|
||||||
|
if (reset_needed) {
|
||||||
|
do_reset (); //Now we've faded out the scene, rebuild it
|
||||||
|
}
|
||||||
|
if (fade_state != FADE_IDLE) {
|
||||||
|
if (fade_state == FADE_WAIT && TextureReady () && EntityReady ()) {
|
||||||
|
fade_state = FADE_IN;
|
||||||
|
fade_start = now;
|
||||||
|
fade_current = 1.0f;
|
||||||
|
}
|
||||||
|
fade_delta = now - fade_start;
|
||||||
|
//See if we're done fading in or out
|
||||||
|
if (fade_delta > FADE_TIME && fade_state != FADE_WAIT) {
|
||||||
|
if (fade_state == FADE_OUT) {
|
||||||
|
reset_needed = true;
|
||||||
|
fade_state = FADE_WAIT;
|
||||||
|
fade_current = 1.0f;
|
||||||
|
} else {
|
||||||
|
fade_state = FADE_IDLE;
|
||||||
|
fade_current = 0.0f;
|
||||||
|
start_time = time (NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fade_current = (float)fade_delta / FADE_TIME;
|
||||||
|
if (fade_state == FADE_IN)
|
||||||
|
fade_current = 1.0f - fade_current;
|
||||||
|
if (fade_state == FADE_WAIT)
|
||||||
|
fade_current = 1.0f;
|
||||||
|
}
|
||||||
|
if (!TextureReady ())
|
||||||
|
fade_current = 1.0f;
|
||||||
|
}
|
||||||
|
if (fade_state == FADE_IDLE && !TextureReady ()) {
|
||||||
|
fade_state = FADE_IN;
|
||||||
|
fade_start = now;
|
||||||
|
}
|
||||||
|
elapsed = time (NULL) - start_time;
|
||||||
|
if (fade_state == FADE_IDLE && elapsed > RESET_INTERVAL)
|
||||||
|
WorldReset ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void WorldInit (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
last_update = GetTickCount ();
|
||||||
|
for (int i = 0; i < CARS; i++)
|
||||||
|
new CCar ();
|
||||||
|
sky = new CSky ();
|
||||||
|
WorldReset ();
|
||||||
|
fade_state = FADE_OUT;
|
||||||
|
fade_start = 0;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#define SHOW_DEBUG_GROUND 0
|
||||||
|
|
||||||
|
#define WORLD_SIZE 1024
|
||||||
|
#define WORLD_HALF (WORLD_SIZE / 2)
|
||||||
|
|
||||||
|
#define CLAIM_ROAD 1
|
||||||
|
#define CLAIM_WALK 2
|
||||||
|
#define CLAIM_BUILDING 4
|
||||||
|
#define MAP_ROAD_NORTH 8
|
||||||
|
#define MAP_ROAD_SOUTH 16
|
||||||
|
#define MAP_ROAD_EAST 32
|
||||||
|
#define MAP_ROAD_WEST 64
|
||||||
|
#define RANDOM_COLOR (glRgbaFromHsl ((float)RandomVal (255)/255,1.0f, 0.75f))
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NORTH,
|
||||||
|
EAST,
|
||||||
|
SOUTH,
|
||||||
|
WEST
|
||||||
|
};
|
||||||
|
|
||||||
|
GLrgba WorldBloomColor ();
|
||||||
|
char WorldCell (int x, int y);
|
||||||
|
GLrgba WorldLightColor (unsigned index);
|
||||||
|
int WorldLogoIndex ();
|
||||||
|
GLbbox WorldHotZone ();
|
||||||
|
void WorldInit (void);
|
||||||
|
float WorldFade (void);
|
||||||
|
void WorldRender ();
|
||||||
|
void WorldReset (void);
|
||||||
|
void WorldTerm (void);
|
||||||
|
void WorldUpdate (void);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
i
|
||||||
|
Green
|
||||||
|
Mega
|
||||||
|
Super
|
||||||
|
Omni
|
||||||
|
e
|
||||||
|
Hyper
|
||||||
|
Global
|
||||||
|
Vital
|
||||||
|
Next
|
||||||
|
Pacific
|
||||||
|
Metro
|
||||||
|
Unity
|
||||||
|
G-
|
||||||
|
Trans
|
||||||
|
Infinity
|
||||||
|
Superior
|
||||||
|
Monolith
|
||||||
|
Best
|
||||||
|
Atlantic
|
||||||
|
First
|
||||||
|
Union
|
||||||
|
National
|
||||||
|
|
||||||
|
|
||||||
|
Biotic
|
||||||
|
Info
|
||||||
|
Data
|
||||||
|
Solar
|
||||||
|
Aerospace
|
||||||
|
Motors
|
||||||
|
Nano
|
||||||
|
Online
|
||||||
|
Circuits
|
||||||
|
Energy
|
||||||
|
Med
|
||||||
|
Robotic
|
||||||
|
Exports
|
||||||
|
Security
|
||||||
|
Systems
|
||||||
|
Financial
|
||||||
|
Industrial
|
||||||
|
Media
|
||||||
|
Materials
|
||||||
|
Foods
|
||||||
|
Networks
|
||||||
|
Shipping
|
||||||
|
Tools
|
||||||
|
Medical
|
||||||
|
Publishing
|
||||||
|
Enterpise
|
||||||
|
Audio
|
||||||
|
Health
|
||||||
|
Bank
|
||||||
|
Imports
|
||||||
|
Apparel
|
||||||
|
Petroleum
|
||||||
|
Studios
|
||||||
|
|
||||||
|
|
||||||
|
Corp
|
||||||
|
Inc.
|
||||||
|
Co
|
||||||
|
World
|
||||||
|
.Com
|
||||||
|
USA
|
||||||
|
Ltd.
|
||||||
|
Net
|
||||||
|
Tech
|
||||||
|
Labs
|
||||||
|
Mfg.
|
||||||
|
UK
|
||||||
|
Unlimited
|
||||||
|
One
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
glBbox.cpp
|
||||||
|
|
||||||
|
2006 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This module has a few functions useful for manipulating the bounding-box
|
||||||
|
structs.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define MAX_VALUE 999999999999999.9f
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "macro.h"
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
Does the given point fall within the given Bbox?
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool glBboxTestPoint (GLbbox box, GLvector point)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (point.x > box.max.x || point.x < box.min.x)
|
||||||
|
return false;
|
||||||
|
if (point.y > box.max.y || point.y < box.min.y)
|
||||||
|
return false;
|
||||||
|
if (point.z > box.max.z || point.z < box.min.z)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
Expand Bbox (if needed) to contain given point
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLbbox glBboxContainPoint (GLbbox box, GLvector point)
|
||||||
|
{
|
||||||
|
|
||||||
|
box.min.x = MIN (box.min.x, point.x);
|
||||||
|
box.min.y = MIN (box.min.y, point.y);
|
||||||
|
box.min.z = MIN (box.min.z, point.z);
|
||||||
|
box.max.x = MAX (box.max.x, point.x);
|
||||||
|
box.max.y = MAX (box.max.y, point.y);
|
||||||
|
box.max.z = MAX (box.max.z, point.z);
|
||||||
|
return box;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
This will invalidate the bbox.
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLbbox glBboxClear (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLbbox result;
|
||||||
|
|
||||||
|
result.max = glVector (-MAX_VALUE, -MAX_VALUE, -MAX_VALUE);
|
||||||
|
result.min = glVector ( MAX_VALUE, MAX_VALUE, MAX_VALUE);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,324 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
glMatrix.cpp
|
||||||
|
|
||||||
|
2006 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Functions useful for manipulating the Matrix struct
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#define M(e,x,y) (e.elements[x][y])
|
||||||
|
|
||||||
|
/*** Order type constants, constructors, extractors ***/
|
||||||
|
|
||||||
|
/* There are 24 possible conventions, designated by: */
|
||||||
|
/* o EulAxI = axis used initially */
|
||||||
|
/* o EulPar = parity of axis permutation */
|
||||||
|
/* o EulRep = repetition of initial axis as last */
|
||||||
|
/* o EulFrm = frame from which axes are taken */
|
||||||
|
/* Axes I,J,K will be a permutation of X,Y,Z. */
|
||||||
|
/* Axis H will be either I or K, depending on EulRep. */
|
||||||
|
/* Frame S takes axes from initial static frame. */
|
||||||
|
/* If ord = (AxI=X, Par=Even, Rep=No, Frm=S), then */
|
||||||
|
/* {a,b,c,ord} means Rz(c)Ry(b)Rx(a), where Rz(c)v */
|
||||||
|
/* rotates v around Z by c radians. */
|
||||||
|
|
||||||
|
#define EulFrmS 0
|
||||||
|
#define EulFrmR 1
|
||||||
|
#define EulFrm(ord) ((unsigned)(ord)&1)
|
||||||
|
#define EulRepNo 0
|
||||||
|
#define EulRepYes 1
|
||||||
|
#define EulRep(ord) (((unsigned)(ord)>>1)&1)
|
||||||
|
#define EulParEven 0
|
||||||
|
#define EulParOdd 1
|
||||||
|
#define EulPar(ord) (((unsigned)(ord)>>2)&1)
|
||||||
|
#define EulSafe "\000\001\002\000"
|
||||||
|
#define EulNext "\001\002\000\001"
|
||||||
|
#define EulAxI(ord) ((int)(EulSafe[(((unsigned)(ord)>>3)&3)]))
|
||||||
|
#define EulAxJ(ord) ((int)(EulNext[EulAxI(ord)+(EulPar(ord)==EulParOdd)]))
|
||||||
|
#define EulAxK(ord) ((int)(EulNext[EulAxI(ord)+(EulPar(ord)!=EulParOdd)]))
|
||||||
|
#define EulAxH(ord) ((EulRep(ord)==EulRepNo)?EulAxK(ord):EulAxI(ord))
|
||||||
|
/* EulGetOrd unpacks all useful information about order simultaneously. */
|
||||||
|
#define EulGetOrd(ord,i,j,k,h,n,s,f) {unsigned o=ord;f=o&1;o>>=1;s=o&1;o>>=1;\
|
||||||
|
n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];k=EulNext[i+1-n];h=s?k:i;}
|
||||||
|
/* EulOrd creates an order value between 0 and 23 from 4-tuple choices. */
|
||||||
|
#define EulOrd(i,p,r,f) (((((((i)<<1)+(p))<<1)+(r))<<1)+(f))
|
||||||
|
/* Static axes */
|
||||||
|
#define EulOrdXYZs EulOrd(X,EulParEven,EulRepNo,EulFrmS)
|
||||||
|
#define EulOrdXYXs EulOrd(X,EulParEven,EulRepYes,EulFrmS)
|
||||||
|
#define EulOrdXZYs EulOrd(X,EulParOdd,EulRepNo,EulFrmS)
|
||||||
|
#define EulOrdXZXs EulOrd(X,EulParOdd,EulRepYes,EulFrmS)
|
||||||
|
#define EulOrdYZXs EulOrd(Y,EulParEven,EulRepNo,EulFrmS)
|
||||||
|
#define EulOrdYZYs EulOrd(Y,EulParEven,EulRepYes,EulFrmS)
|
||||||
|
#define EulOrdYXZs EulOrd(Y,EulParOdd,EulRepNo,EulFrmS)
|
||||||
|
#define EulOrdYXYs EulOrd(Y,EulParOdd,EulRepYes,EulFrmS)
|
||||||
|
#define EulOrdZXYs EulOrd(Z,EulParEven,EulRepNo,EulFrmS)
|
||||||
|
#define EulOrdZXZs EulOrd(Z,EulParEven,EulRepYes,EulFrmS)
|
||||||
|
#define EulOrdZYXs EulOrd(Z,EulParOdd,EulRepNo,EulFrmS)
|
||||||
|
#define EulOrdZYZs EulOrd(Z,EulParOdd,EulRepYes,EulFrmS)
|
||||||
|
/* Rotating axes */
|
||||||
|
#define EulOrdZYXr EulOrd(X,EulParEven,EulRepNo,EulFrmR)
|
||||||
|
#define EulOrdXYXr EulOrd(X,EulParEven,EulRepYes,EulFrmR)
|
||||||
|
#define EulOrdYZXr EulOrd(X,EulParOdd,EulRepNo,EulFrmR)
|
||||||
|
#define EulOrdXZXr EulOrd(X,EulParOdd,EulRepYes,EulFrmR)
|
||||||
|
#define EulOrdXZYr EulOrd(Y,EulParEven,EulRepNo,EulFrmR)
|
||||||
|
#define EulOrdYZYr EulOrd(Y,EulParEven,EulRepYes,EulFrmR)
|
||||||
|
#define EulOrdZXYr EulOrd(Y,EulParOdd,EulRepNo,EulFrmR)
|
||||||
|
#define EulOrdYXYr EulOrd(Y,EulParOdd,EulRepYes,EulFrmR)
|
||||||
|
#define EulOrdYXZr EulOrd(Z,EulParEven,EulRepNo,EulFrmR)
|
||||||
|
#define EulOrdZXZr EulOrd(Z,EulParEven,EulRepYes,EulFrmR)
|
||||||
|
#define EulOrdXYZr EulOrd(Z,EulParOdd,EulRepNo,EulFrmR)
|
||||||
|
#define EulOrdZYZr EulOrd(Z,EulParOdd,EulRepYes,EulFrmR)
|
||||||
|
|
||||||
|
//EulerAngles Eul_(float ai, float aj, float ah, int order);
|
||||||
|
//Quat Eul_ToQuat(EulerAngles ea);
|
||||||
|
//void Eul_ToHMatrix(EulerAngles ea, HMatrix M);
|
||||||
|
//EulerAngles Eul_FromHMatrix(HMatrix M, int order);
|
||||||
|
//EulerAngles Eul_FromQuat(Quat q, int order);
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
#include "macro.h"
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
static float identity[4][4] =
|
||||||
|
{
|
||||||
|
{1.0f, 0.0f, 0.0f, 0.0f},
|
||||||
|
{0.0f, 1.0f, 0.0f, 0.0f},
|
||||||
|
{0.0f, 0.0f, 1.0f, 0.0f},
|
||||||
|
{0.0f, 0.0f, 0.0f, 1.0f},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void* glMatrixCreate (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLmatrix* m;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
m = new GLmatrix;
|
||||||
|
for (x = 0; x < 4; x++) {
|
||||||
|
for (y = 0; y < 4; y++) {
|
||||||
|
m -> elements[x][y] = identity[x][y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (void*)m;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLmatrix glMatrixIdentity (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLmatrix m;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
for (x = 0; x < 4; x++) {
|
||||||
|
for (y = 0; y < 4; y++) {
|
||||||
|
M(m, x, y) = identity[x][y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void glMatrixElementsSet (GLmatrix* m, float* in)
|
||||||
|
{
|
||||||
|
|
||||||
|
m -> elements[0][0] = in[0];
|
||||||
|
m -> elements[0][1] = in[1];
|
||||||
|
m -> elements[0][2] = in[2];
|
||||||
|
m -> elements[0][3] = in[3];
|
||||||
|
|
||||||
|
m -> elements[1][0] = in[4];
|
||||||
|
m -> elements[1][1] = in[5];
|
||||||
|
m -> elements[1][2] = in[6];
|
||||||
|
m -> elements[1][3] = in[7];
|
||||||
|
|
||||||
|
m -> elements[2][0] = in[8];
|
||||||
|
m -> elements[2][1] = in[9];
|
||||||
|
m -> elements[2][2] = in[10];
|
||||||
|
m -> elements[2][3] = in[11];
|
||||||
|
|
||||||
|
m -> elements[3][0] = in[12];
|
||||||
|
m -> elements[3][1] = in[13];
|
||||||
|
m -> elements[3][2] = in[14];
|
||||||
|
m -> elements[3][3] = in[15];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
A matrix multiplication (dot product) of two 4x4 matrices.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLmatrix glMatrixMultiply (GLmatrix a, GLmatrix b)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLmatrix result;
|
||||||
|
|
||||||
|
M(result, 0,0) = M(a, 0,0) * M(b, 0, 0) + M(a, 1,0) * M(b, 0, 1) + M(a, 2,0) * M(b, 0, 2);
|
||||||
|
M(result, 1,0) = M(a, 0,0) * M(b, 1, 0) + M(a, 1,0) * M(b, 1, 1) + M(a, 2,0) * M(b, 1, 2);
|
||||||
|
M(result, 2,0) = M(a, 0,0) * M(b, 2, 0) + M(a, 1,0) * M(b, 2, 1) + M(a, 2,0) * M(b, 2, 2);
|
||||||
|
M(result, 3,0) = M(a, 0,0) * M(b, 3, 0) + M(a, 1,0) * M(b, 3, 1) + M(a, 2,0) * M(b, 3, 2) + M(a, 3,0);
|
||||||
|
|
||||||
|
M(result, 0,1) = M(a, 0,1) * M(b, 0, 0) + M(a, 1,1) * M(b, 0, 1) + M(a, 2,1) * M(b, 0, 2);
|
||||||
|
M(result, 1,1) = M(a, 0,1) * M(b, 1, 0) + M(a, 1,1) * M(b, 1, 1) + M(a, 2,1) * M(b, 1, 2);
|
||||||
|
M(result, 2,1) = M(a, 0,1) * M(b, 2, 0) + M(a, 1,1) * M(b, 2, 1) + M(a, 2,1) * M(b, 2, 2);
|
||||||
|
M(result, 3,1) = M(a, 0,1) * M(b, 3, 0) + M(a, 1,1) * M(b, 3, 1) + M(a, 2,1) * M(b, 3, 2) + M(a, 3,1);
|
||||||
|
|
||||||
|
M(result, 0,2) = M(a, 0,2) * M(b, 0, 0) + M(a, 1,2) * M(b, 0, 1) + M(a, 2,2) * M(b, 0, 2);
|
||||||
|
M(result, 1,2) = M(a, 0,2) * M(b, 1, 0) + M(a, 1,2) * M(b, 1, 1) + M(a, 2,2) * M(b, 1, 2);
|
||||||
|
M(result, 2,2) = M(a, 0,2) * M(b, 2, 0) + M(a, 1,2) * M(b, 2, 1) + M(a, 2,2) * M(b, 2, 2);
|
||||||
|
M(result, 3,2) = M(a, 0,2) * M(b, 3, 0) + M(a, 1,2) * M(b, 3, 1) + M(a, 2,2) * M(b, 3, 2) + M(a, 3,2);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector glMatrixTransformPoint (GLmatrix m, GLvector in)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector out;
|
||||||
|
|
||||||
|
out.x = M(m,0,0) * in.x + M(m,1,0) * in.y + M(m,2,0) * in.z + M(m,3,0);
|
||||||
|
out.y = M(m,0,1) * in.x + M(m,1,1) * in.y + M(m,2,1) * in.z + M(m,3,1);
|
||||||
|
out.z = M(m,0,2) * in.x + M(m,1,2) * in.y + M(m,2,2) * in.z + M(m,3,2);
|
||||||
|
return out;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLmatrix glMatrixTranslate (GLmatrix m, GLvector in)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector old;
|
||||||
|
|
||||||
|
old.x = M(m,3,0);
|
||||||
|
old.y = M(m,3,1);
|
||||||
|
old.z = M(m,3,2);
|
||||||
|
M(m, 3, 0) = 0.0f;
|
||||||
|
M(m, 3, 1) = 0.0f;
|
||||||
|
M(m, 3, 2) = 0.0f;
|
||||||
|
in = glMatrixTransformPoint (m, in);
|
||||||
|
M(m, 3, 0) = old.x;
|
||||||
|
M(m, 3, 1) = old.y;
|
||||||
|
M(m, 3, 2) = old.z;
|
||||||
|
M(m,3,0) += in.x;
|
||||||
|
M(m,3,1) += in.y;
|
||||||
|
M(m,3,2) += in.z;
|
||||||
|
return m;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLmatrix glMatrixRotate (GLmatrix m, float theta, float x, float y, float z)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLmatrix r;
|
||||||
|
float length;
|
||||||
|
float s, c, t;
|
||||||
|
GLvector in;
|
||||||
|
|
||||||
|
theta *= DEGREES_TO_RADIANS;
|
||||||
|
r = glMatrixIdentity ();
|
||||||
|
length = (float)sqrt (x * x + y * y + z * z);
|
||||||
|
if (length < 0.00001f)
|
||||||
|
return m;
|
||||||
|
x /= length;
|
||||||
|
y /= length;
|
||||||
|
z /= length;
|
||||||
|
s = (float)sin (theta);
|
||||||
|
c = (float)cos (theta);
|
||||||
|
t = 1.0f - c;
|
||||||
|
|
||||||
|
in.x = in.y = in.z = 1.0f;
|
||||||
|
M(r, 0,0) = t*x*x + c;
|
||||||
|
M(r, 1,0) = t*x*y - s*z;
|
||||||
|
M(r, 2,0) = t*x*z + s*y;
|
||||||
|
M(r, 3,0) = 0;
|
||||||
|
|
||||||
|
M(r, 0,1) = t*x*y + s*z;
|
||||||
|
M(r, 1,1) = t*y*y + c;
|
||||||
|
M(r, 2,1) = t*y*z - s*x;
|
||||||
|
M(r, 3,1) = 0;
|
||||||
|
|
||||||
|
M(r, 0,2) = t*x*z - s*y;
|
||||||
|
M(r, 1,2) = t*y*z + s*x;
|
||||||
|
M(r, 2,2) = t*z*z + c;
|
||||||
|
M(r, 3,2) = 0;
|
||||||
|
|
||||||
|
m = glMatrixMultiply (m, r);
|
||||||
|
return m;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert matrix to Euler angles (in radians). */
|
||||||
|
GLvector glMatrixToEuler (GLmatrix mat, int order)
|
||||||
|
{
|
||||||
|
GLvector ea;
|
||||||
|
int i,j,k,h,n,s,f;
|
||||||
|
|
||||||
|
EulGetOrd (order,i,j,k,h,n,s,f);
|
||||||
|
if (s==EulRepYes) {
|
||||||
|
float sy = (float)sqrt(mat.elements[i][j]*mat.elements[i][j] + mat.elements[i][k]*mat.elements[i][k]);
|
||||||
|
if (sy > 16 * FLT_EPSILON) {
|
||||||
|
ea.x = (float)atan2(mat.elements[i][j], mat.elements[i][k]);
|
||||||
|
ea.y = (float)atan2(sy, mat.elements[i][i]);
|
||||||
|
ea.z = (float)atan2(mat.elements[j][i], -mat.elements[k][i]);
|
||||||
|
} else {
|
||||||
|
ea.x = (float)atan2(-mat.elements[j][k], mat.elements[j][j]);
|
||||||
|
ea.y = (float)atan2(sy, mat.elements[i][i]);
|
||||||
|
ea.z = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
float cy = (float)sqrt(mat.elements[i][i]*mat.elements[i][i] + mat.elements[j][i]*mat.elements[j][i]);
|
||||||
|
if (cy > 16*FLT_EPSILON) {
|
||||||
|
ea.x = (float)atan2(mat.elements[k][j], mat.elements[k][k]);
|
||||||
|
ea.y = (float)atan2(-mat.elements[k][i], cy);
|
||||||
|
ea.z = (float)atan2(mat.elements[j][i], mat.elements[i][i]);
|
||||||
|
} else {
|
||||||
|
ea.x = (float)atan2(-mat.elements[j][k], mat.elements[j][j]);
|
||||||
|
ea.y = (float)atan2(-mat.elements[k][i], cy);
|
||||||
|
ea.z = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n==EulParOdd) {
|
||||||
|
ea.x = -ea.x;
|
||||||
|
ea.y = - ea.y;
|
||||||
|
ea.z = -ea.z;
|
||||||
|
}
|
||||||
|
if (f==EulFrmR) {
|
||||||
|
float t = ea.x;
|
||||||
|
ea.x = ea.z;
|
||||||
|
ea.z = t;
|
||||||
|
}
|
||||||
|
//ea.w = order;
|
||||||
|
return (ea);
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
glQuat.cpp
|
||||||
|
|
||||||
|
2006 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Functions for dealing with Quaternions
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
enum QuatPart {X, Y, Z, W};
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLquat glQuat (float x, float y, float z, float w)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLquat result;
|
||||||
|
|
||||||
|
result.x = x;
|
||||||
|
result.y = y;
|
||||||
|
result.z = z;
|
||||||
|
result.w = w;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Convert quaternion to Euler angles (in radians). */
|
||||||
|
/*
|
||||||
|
EulerAngles Eul_FromQuat(Quat q, int order)
|
||||||
|
{
|
||||||
|
HMatrix M;
|
||||||
|
double Nq = q.x*q.x+q.y*q.y+q.z*q.z+q.w*q.w;
|
||||||
|
double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
|
||||||
|
double xs = q.x*s, ys = q.y*s, zs = q.z*s;
|
||||||
|
double wx = q.w*xs, wy = q.w*ys, wz = q.w*zs;
|
||||||
|
double xx = q.x*xs, xy = q.x*ys, xz = q.x*zs;
|
||||||
|
double yy = q.y*ys, yz = q.y*zs, zz = q.z*zs;
|
||||||
|
M[X][X] = 1.0 - (yy + zz); M[X][Y] = xy - wz; M[X][Z] = xz + wy;
|
||||||
|
M[Y][X] = xy + wz; M[Y][Y] = 1.0 - (xx + zz); M[Y][Z] = yz - wx;
|
||||||
|
M[Z][X] = xz - wy; M[Z][Y] = yz + wx; M[Z][Z] = 1.0 - (xx + yy);
|
||||||
|
M[W][X]=M[W][Y]=M[W][Z]=M[X][W]=M[Y][W]=M[Z][W]=0.0; M[W][W]=1.0;
|
||||||
|
return (Eul_FromHMatrix(M, order));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLvector glQuatToEuler (GLquat q, int order)
|
||||||
|
{
|
||||||
|
GLmatrix M;
|
||||||
|
|
||||||
|
float Nq = q.x*q.x+q.y*q.y+q.z*q.z+q.w*q.w;
|
||||||
|
float s = (Nq > 0.0f) ? (2.0f / Nq) : 0.0f;
|
||||||
|
float xs = q.x*s, ys = q.y*s, zs = q.z*s;
|
||||||
|
float wx = q.w*xs, wy = q.w*ys, wz = q.w*zs;
|
||||||
|
float xx = q.x*xs, xy = q.x*ys, xz = q.x*zs;
|
||||||
|
float yy = q.y*ys, yz = q.y*zs, zz = q.z*zs;
|
||||||
|
M.elements[X][X] = 1.0f - (yy + zz); M.elements[X][Y] = xy - wz; M.elements[X][Z] = xz + wy;
|
||||||
|
M.elements[Y][X] = xy + wz; M.elements[Y][Y] = 1.0f - (xx + zz); M.elements[Y][Z] = yz - wx;
|
||||||
|
M.elements[Z][X] = xz - wy; M.elements[Z][Y] = yz + wx; M.elements[Z][Z] = 1.0f - (xx + yy);
|
||||||
|
M.elements[W][X] = M.elements[W][Y] =
|
||||||
|
M.elements[W][Z] = M.elements[X][W] =
|
||||||
|
M.elements[Y][W] = M.elements[Z][W] = 0.0f;
|
||||||
|
M.elements[W][W] = 1.0f;
|
||||||
|
return (glMatrixToEuler(M, order));
|
||||||
|
}
|
|
@ -0,0 +1,401 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
glRgba.cpp
|
||||||
|
|
||||||
|
2009 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Functions for dealing with RGBA color values.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
#include "glTypes.h"
|
||||||
|
#include "macro.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgbaFromHsl (float h, float sl, float l)
|
||||||
|
{
|
||||||
|
|
||||||
|
float v;
|
||||||
|
float r,g,b;
|
||||||
|
|
||||||
|
|
||||||
|
r = l; // default to gray
|
||||||
|
g = l;
|
||||||
|
b = l;
|
||||||
|
v = (l <= 0.5f) ? (l * (1.0f + sl)) : (l + sl - l * sl);
|
||||||
|
if (v > 0) {
|
||||||
|
float m;
|
||||||
|
float sv;
|
||||||
|
int sextant;
|
||||||
|
float fract, vsf, mid1, mid2;
|
||||||
|
|
||||||
|
m = l + l - v;
|
||||||
|
sv = (v - m ) / v;
|
||||||
|
h *= 6.0f;
|
||||||
|
sextant = (int)h;
|
||||||
|
fract = h - sextant;
|
||||||
|
vsf = v * sv * fract;
|
||||||
|
mid1 = m + vsf;
|
||||||
|
mid2 = v - vsf;
|
||||||
|
switch (sextant) {
|
||||||
|
case 0:
|
||||||
|
r = v; g = mid1; b = m;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r = mid2; g = v; b = m;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r = m; g = v; b = mid1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r = m; g = mid2; b = v;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
r = mid1; g = m; b = v;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
r = v; g = m; b = mid2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return glRgba (r, g, b);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgbaInterpolate (GLrgba c1, GLrgba c2, float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = MathInterpolate (c1.red, c2.red, delta);
|
||||||
|
result.green = MathInterpolate (c1.green, c2.green, delta);
|
||||||
|
result.blue = MathInterpolate (c1.blue, c2.blue, delta);
|
||||||
|
result.alpha = MathInterpolate (c1.alpha, c2.alpha, delta);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgbaAdd (GLrgba c1, GLrgba c2)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = c1.red + c2.red;
|
||||||
|
result.green = c1.green + c2.green;
|
||||||
|
result.blue = c1.blue + c2.blue;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgbaSubtract (GLrgba c1, GLrgba c2)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = c1.red - c2.red;
|
||||||
|
result.green = c1.green - c2.green;
|
||||||
|
result.blue = c1.blue - c2.blue;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgbaMultiply (GLrgba c1, GLrgba c2)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = c1.red * c2.red;
|
||||||
|
result.green = c1.green * c2.green;
|
||||||
|
result.blue = c1.blue * c2.blue;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgbaScale (GLrgba c, float scale)
|
||||||
|
{
|
||||||
|
|
||||||
|
c.red *= scale;
|
||||||
|
c.green *= scale;
|
||||||
|
c.blue *= scale;
|
||||||
|
return c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgba (char* string)
|
||||||
|
{
|
||||||
|
|
||||||
|
long color;
|
||||||
|
char buffer[10];
|
||||||
|
char* pound;
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
strncmp (buffer, string, 10);
|
||||||
|
if (pound = strchr (buffer, '#'))
|
||||||
|
pound[0] = ' ';
|
||||||
|
if (sscanf (string, "%x", &color) != 1)
|
||||||
|
return glRgba (0.0f);
|
||||||
|
result.red = (float)GetBValue (color) / 255.0f;
|
||||||
|
result.green = (float)GetGValue (color) / 255.0f;
|
||||||
|
result.blue = (float)GetRValue (color) / 255.0f;
|
||||||
|
result.alpha = 1.0f;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgba (int red, int green, int blue)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = (float)red / 255.0f;
|
||||||
|
result.green = (float)green / 255.0f;
|
||||||
|
result.blue = (float)blue / 255.0f;
|
||||||
|
result.alpha = 1.0f;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgba (float red, float green, float blue)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = red;
|
||||||
|
result.green = green;
|
||||||
|
result.blue = blue;
|
||||||
|
result.alpha = 1.0f;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgba (float red, float green, float blue, float alpha)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = red;
|
||||||
|
result.green = green;
|
||||||
|
result.blue = blue;
|
||||||
|
result.alpha = alpha;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgba (long c)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = (float)GetRValue (c) / 255.0f;
|
||||||
|
result.green = (float)GetGValue (c) / 255.0f;
|
||||||
|
result.blue = (float)GetBValue (c) / 255.0f;
|
||||||
|
result.alpha = 1.0f;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgba (float luminance)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba result;
|
||||||
|
|
||||||
|
result.red = luminance;
|
||||||
|
result.green = luminance;
|
||||||
|
result.blue = luminance;
|
||||||
|
result.alpha = 1.0f;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
Takes the given index and returns a "random" color unique for that index.
|
||||||
|
512 Unique values: #0 and #512 will be the same, as will #1 and #513, etc
|
||||||
|
Useful for visual debugging in some situations.
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba glRgbaUnique (int i)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLrgba c;
|
||||||
|
|
||||||
|
c.alpha = 1.0f;
|
||||||
|
c.red = 0.4f + ((i & 1) ? 0.2f : 0.0f) + ((i & 8) ? 0.3f : 0.0f) - ((i & 64) ? 0.3f : 0.0f);
|
||||||
|
c.green = 0.4f + ((i & 2) ? 0.2f : 0.0f) + ((i & 32) ? 0.3f : 0.0f) - ((i & 128) ? 0.3f : 0.0f);
|
||||||
|
c.blue = 0.4f + ((i & 4) ? 0.2f : 0.0f) + ((i & 16) ? 0.3f : 0.0f) - ((i & 256) ? 0.3f : 0.0f);
|
||||||
|
return c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
+ operator
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba GLrgba::operator+ (const GLrgba& c)
|
||||||
|
{
|
||||||
|
return glRgba (red + c.red, green + c.green, blue + c.blue, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLrgba GLrgba::operator+ (const float& c)
|
||||||
|
{
|
||||||
|
return glRgba (red + c, green + c, blue + c, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLrgba::operator+= (const GLrgba& c)
|
||||||
|
{
|
||||||
|
red += c.red;
|
||||||
|
green += c.green;
|
||||||
|
blue += c.blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLrgba::operator+= (const float& c)
|
||||||
|
{
|
||||||
|
red += c;
|
||||||
|
green += c;
|
||||||
|
blue += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
- operator
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba GLrgba::operator- (const GLrgba& c)
|
||||||
|
{
|
||||||
|
return glRgba (red - c.red, green - c.green, blue - c.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLrgba GLrgba::operator- (const float& c)
|
||||||
|
{
|
||||||
|
return glRgba (red - c, green - c, blue - c, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLrgba::operator-= (const GLrgba& c)
|
||||||
|
{
|
||||||
|
red -= c.red;
|
||||||
|
green -= c.green;
|
||||||
|
blue -= c.blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLrgba::operator-= (const float& c)
|
||||||
|
{
|
||||||
|
red -= c;
|
||||||
|
green -= c;
|
||||||
|
blue -= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
* operator
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba GLrgba::operator* (const GLrgba& c)
|
||||||
|
{
|
||||||
|
return glRgba (red * c.red, green * c.green, blue * c.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLrgba GLrgba::operator* (const float& c)
|
||||||
|
{
|
||||||
|
return glRgba (red * c, green * c, blue * c, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLrgba::operator*= (const GLrgba& c)
|
||||||
|
{
|
||||||
|
red *= c.red;
|
||||||
|
green *= c.green;
|
||||||
|
blue *= c.blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLrgba::operator*= (const float& c)
|
||||||
|
{
|
||||||
|
red *= c;
|
||||||
|
green *= c;
|
||||||
|
blue *= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
/ operator
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLrgba GLrgba::operator/ (const GLrgba& c)
|
||||||
|
{
|
||||||
|
return glRgba (red / c.red, green / c.green, blue / c.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLrgba GLrgba::operator/ (const float& c)
|
||||||
|
{
|
||||||
|
return glRgba (red / c, green / c, blue / c, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLrgba::operator/= (const GLrgba& c)
|
||||||
|
{
|
||||||
|
red /= c.red;
|
||||||
|
green /= c.green;
|
||||||
|
blue /= c.blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLrgba::operator/= (const float& c)
|
||||||
|
{
|
||||||
|
red /= c;
|
||||||
|
green /= c;
|
||||||
|
blue /= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLrgba::operator== (const GLrgba& c)
|
||||||
|
{
|
||||||
|
return (red == c.red && green == c.green && blue == c.blue);
|
||||||
|
}
|
|
@ -0,0 +1,209 @@
|
||||||
|
#ifndef glTYPES
|
||||||
|
#define glTYPES
|
||||||
|
|
||||||
|
#define GL_CLAMP_TO_EDGE 0x812F
|
||||||
|
|
||||||
|
#define OPERATORS(type) \
|
||||||
|
type operator+ (const type& c); \
|
||||||
|
type operator+ (const float& c);\
|
||||||
|
void operator+= (const type& c);\
|
||||||
|
void operator+= (const float& c);\
|
||||||
|
type operator- (const type& c);\
|
||||||
|
type operator- (const float& c);\
|
||||||
|
void operator-= (const type& c);\
|
||||||
|
void operator-= (const float& c);\
|
||||||
|
type operator* (const type& c);\
|
||||||
|
type operator* (const float& c);\
|
||||||
|
void operator*= (const type& c);\
|
||||||
|
void operator*= (const float& c);\
|
||||||
|
type operator/ (const type& c);\
|
||||||
|
type operator/ (const float& c);\
|
||||||
|
void operator/= (const type& c);\
|
||||||
|
void operator/= (const float& c);\
|
||||||
|
bool operator== (const type& c);
|
||||||
|
|
||||||
|
|
||||||
|
#define JOINT_MAX_CHILDREN 8
|
||||||
|
|
||||||
|
struct GLquat
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLvector
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
OPERATORS(GLvector);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef GLvector GLvector3;
|
||||||
|
|
||||||
|
struct GLvector2
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
OPERATORS(GLvector2);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLrgba
|
||||||
|
{
|
||||||
|
float red;
|
||||||
|
float green;
|
||||||
|
float blue;
|
||||||
|
float alpha;
|
||||||
|
OPERATORS(GLrgba);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLmatrix
|
||||||
|
{
|
||||||
|
float elements[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLbbox
|
||||||
|
{
|
||||||
|
GLvector3 min;
|
||||||
|
GLvector3 max;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLvertex
|
||||||
|
{
|
||||||
|
GLvector3 position;
|
||||||
|
GLvector2 uv;
|
||||||
|
GLrgba color;
|
||||||
|
int bone;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLrect
|
||||||
|
{
|
||||||
|
float left;
|
||||||
|
float top;
|
||||||
|
float right;
|
||||||
|
float bottom;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLtriangle
|
||||||
|
{
|
||||||
|
int v1;
|
||||||
|
int v2;
|
||||||
|
int v3;
|
||||||
|
int normal1;
|
||||||
|
int normal2;
|
||||||
|
int normal3;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
class GLmodel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
unsigned vertex_count;
|
||||||
|
unsigned triangle_count;
|
||||||
|
unsigned normal_count;
|
||||||
|
GLvertex* vertex;
|
||||||
|
GLvector* normal;
|
||||||
|
GLtriangle* triangle;
|
||||||
|
|
||||||
|
void TriangleRender (unsigned n);
|
||||||
|
GLtriangle* TriangleAdd (unsigned v1, int unsigned, int unsigned);
|
||||||
|
GLtriangle* TriangleAdd (GLtriangle c);
|
||||||
|
void NormalAdd (GLvector n);
|
||||||
|
void VertexAdd (GLvertex v);
|
||||||
|
GLmodel ();
|
||||||
|
~GLmodel ();
|
||||||
|
void Render ();
|
||||||
|
GLbbox BBox ();
|
||||||
|
private:
|
||||||
|
GLbbox m_bbox;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLkeyframe
|
||||||
|
{
|
||||||
|
float time;
|
||||||
|
GLvector offset;
|
||||||
|
GLvector rotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GLsegment
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
GLvector rotation;
|
||||||
|
GLvector offset;
|
||||||
|
GLkeyframe keyframes[255];
|
||||||
|
int frame_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GLanimate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLanimate ();
|
||||||
|
void KeyframeAdd (int joint, float time, GLquat q);
|
||||||
|
void TimeSet (float time);
|
||||||
|
void PositionSet (float pos);
|
||||||
|
GLvector Rotation (int);
|
||||||
|
GLvector Offset (int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLsegment* m_segments;
|
||||||
|
int m_segment_count;
|
||||||
|
float m_length;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLbbox glBboxClear (void);
|
||||||
|
GLbbox glBboxContainPoint (GLbbox box, GLvector point);
|
||||||
|
bool glBboxTestPoint (GLbbox box, GLvector point);
|
||||||
|
|
||||||
|
GLrgba glRgba (char* string);
|
||||||
|
GLrgba glRgba (float red, float green, float blue);
|
||||||
|
GLrgba glRgba (float luminance);
|
||||||
|
GLrgba glRgba (float red, float green, float blue, float alpha);
|
||||||
|
GLrgba glRgba (long c);
|
||||||
|
GLrgba glRgba (int red, int green, int blue);
|
||||||
|
GLrgba glRgbaAdd (GLrgba c1, GLrgba c2);
|
||||||
|
GLrgba glRgbaSubtract (GLrgba c1, GLrgba c2);
|
||||||
|
GLrgba glRgbaInterpolate (GLrgba c1, GLrgba c2, float delta);
|
||||||
|
GLrgba glRgbaScale (GLrgba c, float scale);
|
||||||
|
GLrgba glRgbaMultiply (GLrgba c1, GLrgba c2);
|
||||||
|
GLrgba glRgbaUnique (int i);
|
||||||
|
GLrgba glRgbaFromHsl (float h, float s, float l);
|
||||||
|
|
||||||
|
GLmatrix glMatrixIdentity (void);
|
||||||
|
void glMatrixElementsSet (GLmatrix* m, float* in);
|
||||||
|
GLmatrix glMatrixMultiply (GLmatrix a, GLmatrix b);
|
||||||
|
GLvector glMatrixTransformPoint (GLmatrix m, GLvector in);
|
||||||
|
GLmatrix glMatrixTranslate (GLmatrix m, GLvector in);
|
||||||
|
GLmatrix glMatrixRotate (GLmatrix m, float theta, float x, float y, float z);
|
||||||
|
GLvector glMatrixToEuler (GLmatrix mat, int order);
|
||||||
|
|
||||||
|
GLquat glQuat (float x, float y, float z, float w);
|
||||||
|
GLvector glQuatToEuler (GLquat q, int order);
|
||||||
|
|
||||||
|
GLvector glVector (float x, float y, float z);
|
||||||
|
GLvector glVectorCrossProduct (GLvector v1, GLvector v2);
|
||||||
|
float glVectorDotProduct (GLvector v1, GLvector v2);
|
||||||
|
void glVectorGl (GLvector v);
|
||||||
|
GLvector glVectorInterpolate (GLvector v1, GLvector v2, float scalar);
|
||||||
|
float glVectorLength (GLvector v);
|
||||||
|
GLvector glVectorNormalize (GLvector v);
|
||||||
|
GLvector glVectorReflect (GLvector3 ray, GLvector3 normal);
|
||||||
|
|
||||||
|
GLvector2 glVector (float x, float y);
|
||||||
|
GLvector2 glVectorAdd (GLvector2 val1, GLvector2 val2);
|
||||||
|
GLvector2 glVectorSubtract (GLvector2 val1, GLvector2 val2);
|
||||||
|
GLvector2 glVectorNormalize (GLvector2 v);
|
||||||
|
GLvector2 glVectorInterpolate (GLvector2 v1, GLvector2 v2, float scalar);
|
||||||
|
GLvector2 glVectorSinCos (float angle);
|
||||||
|
float glVectorLength (GLvector2 v);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Vector2.cpp
|
||||||
|
|
||||||
|
2006 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Functions for dealing with 2d (usually texture mapping) values.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
|
||||||
|
#include "glTypes.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "macro.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector2 glVectorNormalize (GLvector2 v)
|
||||||
|
{
|
||||||
|
|
||||||
|
float length;
|
||||||
|
|
||||||
|
length = glVectorLength (v);
|
||||||
|
if (length < 0.000001f)
|
||||||
|
return v;
|
||||||
|
return v * (1.0f / length);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float glVectorLength (GLvector2 v)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (float)sqrt (v.x * v.x + v.y * v.y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector2 glVectorSinCos (float a)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector2 val;
|
||||||
|
|
||||||
|
a *= DEGREES_TO_RADIANS;
|
||||||
|
val.x = sinf (a);
|
||||||
|
val.y = cosf (a);
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector2 glVector (float x, float y)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector2 val;
|
||||||
|
|
||||||
|
val.x = x;
|
||||||
|
val.y = y;
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector2 glVectorAdd (GLvector2 val1, GLvector2 val2)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector2 result;
|
||||||
|
|
||||||
|
result.x = val1.x + val2.x;
|
||||||
|
result.y = val1.y + val2.y;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector2 glVectorInterpolate (GLvector2 v1, GLvector2 v2, float scalar)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector2 result;
|
||||||
|
|
||||||
|
result.x = MathInterpolate (v1.x, v2.x, scalar);
|
||||||
|
result.y = MathInterpolate (v1.y, v2.y, scalar);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector2 glVectorSubtract (GLvector2 val1, GLvector2 val2)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector2 result;
|
||||||
|
|
||||||
|
result.x = val1.x - val2.x;
|
||||||
|
result.y = val1.y - val2.y;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
+
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector2 GLvector2::operator+ (const GLvector2& c)
|
||||||
|
{
|
||||||
|
return glVector (x + c.x, y + c.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector2 GLvector2::operator+ (const float& c)
|
||||||
|
{
|
||||||
|
return glVector (x + c, y + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector2::operator+= (const GLvector2& c)
|
||||||
|
{
|
||||||
|
x += c.x;
|
||||||
|
y += c.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector2::operator+= (const float& c)
|
||||||
|
{
|
||||||
|
x += c;
|
||||||
|
y += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector2 GLvector2::operator- (const GLvector2& c)
|
||||||
|
{
|
||||||
|
return glVector (x - c.x, y - c.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector2 GLvector2::operator- (const float& c)
|
||||||
|
{
|
||||||
|
return glVector (x - c, y - c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector2::operator-= (const GLvector2& c)
|
||||||
|
{
|
||||||
|
x -= c.x;
|
||||||
|
y -= c.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector2::operator-= (const float& c)
|
||||||
|
{
|
||||||
|
x -= c;
|
||||||
|
y -= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector2 GLvector2::operator* (const GLvector2& c)
|
||||||
|
{
|
||||||
|
return glVector (x * c.x, y * c.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector2 GLvector2::operator* (const float& c)
|
||||||
|
{
|
||||||
|
return glVector (x * c, y * c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector2::operator*= (const GLvector2& c)
|
||||||
|
{
|
||||||
|
x *= c.x;
|
||||||
|
y *= c.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector2::operator*= (const float& c)
|
||||||
|
{
|
||||||
|
x *= c;
|
||||||
|
y *= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector2 GLvector2::operator/ (const GLvector2& c)
|
||||||
|
{
|
||||||
|
return glVector (x / c.x, y / c.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector2 GLvector2::operator/ (const float& c)
|
||||||
|
{
|
||||||
|
return glVector (x / c, y / c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector2::operator/= (const GLvector2& c)
|
||||||
|
{
|
||||||
|
x /= c.x;
|
||||||
|
y /= c.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector2::operator/= (const float& c)
|
||||||
|
{
|
||||||
|
x /= c;
|
||||||
|
y /= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLvector2::operator== (const GLvector2& c)
|
||||||
|
{
|
||||||
|
if (x == c.x && y == c.y)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,257 @@
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
glVector3.cpp
|
||||||
|
|
||||||
|
2006 Shamus Young
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Functions for dealing with 3d vectors.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <gl\gl.h>
|
||||||
|
|
||||||
|
#include "macro.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "glTypes.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector glVectorReflect (GLvector3 ray, GLvector3 normal)
|
||||||
|
{
|
||||||
|
|
||||||
|
float dot;
|
||||||
|
|
||||||
|
dot = glVectorDotProduct (ray, normal);
|
||||||
|
//return glVectorSubtract (ray, glVectorScale (normal, 2.0f * dot));
|
||||||
|
return ray - (normal * (2.0f * dot));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector3 glVector (float x, float y, float z)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector3 result;
|
||||||
|
|
||||||
|
result.x = x;
|
||||||
|
result.y = y;
|
||||||
|
result.z = z;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector3 glVectorInterpolate (GLvector3 v1, GLvector3 v2, float scalar)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector3 result;
|
||||||
|
|
||||||
|
result.x = MathInterpolate (v1.x, v2.x, scalar);
|
||||||
|
result.y = MathInterpolate (v1.y, v2.y, scalar);
|
||||||
|
result.z = MathInterpolate (v1.z, v2.z, scalar);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float glVectorLength (GLvector3 v)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (float)sqrt (v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float glVectorDotProduct (GLvector3 v1, GLvector3 v2)
|
||||||
|
{
|
||||||
|
|
||||||
|
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector3 glVectorCrossProduct (GLvector3 v1, GLvector3 v2)
|
||||||
|
{
|
||||||
|
|
||||||
|
GLvector3 result;
|
||||||
|
|
||||||
|
result.x = v1.y * v2.z - v2.y * v1.z;
|
||||||
|
result.y = v1.z * v2.x - v2.z * v1.x;
|
||||||
|
result.z = v1.x * v2.y - v2.x * v1.y;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector3 glVectorInvert (GLvector3 v)
|
||||||
|
{
|
||||||
|
|
||||||
|
v.x *= -v.x;
|
||||||
|
v.y *= -v.y;
|
||||||
|
v.z *= -v.z;
|
||||||
|
return v;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector3 glVectorScale (GLvector3 v, float scale)
|
||||||
|
{
|
||||||
|
|
||||||
|
v.x *= scale;
|
||||||
|
v.y *= scale;
|
||||||
|
v.z *= scale;
|
||||||
|
return v;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector3 glVectorNormalize (GLvector3 v)
|
||||||
|
{
|
||||||
|
|
||||||
|
float length;
|
||||||
|
|
||||||
|
length = glVectorLength (v);
|
||||||
|
if (length < 0.000001f)
|
||||||
|
return v;
|
||||||
|
return glVectorScale (v, 1.0f / length);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
+
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
GLvector GLvector::operator+ (const GLvector& c)
|
||||||
|
{
|
||||||
|
return glVector (x + c.x, y + c.y, z + c.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector GLvector::operator+ (const float& c)
|
||||||
|
{
|
||||||
|
return glVector (x + c, y + c, z + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector::operator+= (const GLvector& c)
|
||||||
|
{
|
||||||
|
x += c.x;
|
||||||
|
y += c.y;
|
||||||
|
z += c.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector::operator+= (const float& c)
|
||||||
|
{
|
||||||
|
x += c;
|
||||||
|
y += c;
|
||||||
|
z += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector GLvector::operator- (const GLvector& c)
|
||||||
|
{
|
||||||
|
return glVector (x - c.x, y - c.y, z - c.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector GLvector::operator- (const float& c)
|
||||||
|
{
|
||||||
|
return glVector (x - c, y - c, z - c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector::operator-= (const GLvector& c)
|
||||||
|
{
|
||||||
|
x -= c.x;
|
||||||
|
y -= c.y;
|
||||||
|
z -= c.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector::operator-= (const float& c)
|
||||||
|
{
|
||||||
|
x -= c;
|
||||||
|
y -= c;
|
||||||
|
z -= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector GLvector::operator* (const GLvector& c)
|
||||||
|
{
|
||||||
|
return glVector (x * c.x, y * c.y, z * c.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector GLvector::operator* (const float& c)
|
||||||
|
{
|
||||||
|
return glVector (x * c, y * c, z * c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector::operator*= (const GLvector& c)
|
||||||
|
{
|
||||||
|
x *= c.x;
|
||||||
|
y *= c.y;
|
||||||
|
z *= c.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector::operator*= (const float& c)
|
||||||
|
{
|
||||||
|
x *= c;
|
||||||
|
y *= c;
|
||||||
|
z *= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector GLvector::operator/ (const GLvector& c)
|
||||||
|
{
|
||||||
|
return glVector (x / c.x, y / c.y, z / c.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvector GLvector::operator/ (const float& c)
|
||||||
|
{
|
||||||
|
return glVector (x / c, y / c, z / c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector::operator/= (const GLvector& c)
|
||||||
|
{
|
||||||
|
x /= c.x;
|
||||||
|
y /= c.y;
|
||||||
|
z /= c.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLvector::operator/= (const float& c)
|
||||||
|
{
|
||||||
|
x /= c;
|
||||||
|
y /= c;
|
||||||
|
z /= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLvector::operator== (const GLvector& c)
|
||||||
|
{
|
||||||
|
if (x == c.x && y == c.y && z == c.z)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
Loading…
Reference in New Issue