diff --git a/building.cpp b/building.cpp index 115e7e5..7d77493 100644 --- a/building.cpp +++ b/building.cpp @@ -1,845 +1,844 @@ -/*----------------------------------------------------------------------------- - - Building.cpp - - 2009 Shamus Young - -------------------------------------------------------------------------------- - - This module contains the class to construct the buildings. - ------------------------------------------------------------------------------*/ - -#define MAX_VBUFFER 256 - -#include -#include -#include -#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" -#include "win.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); - _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; - cube c; - 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]); - c.index_list.push_back(base_index + i); - } - _mesh->CubeAdd (c); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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; - cube c; - 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]); - c.index_list.push_back(base_index + i); - } - _mesh_flat->CubeAdd (c); - -} - -/*----------------------------------------------------------------------------- - - 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; - fan f; - int i; - GLvector center; - - for (i = 0; i < 5; i++) - f.index_list.push_back(_mesh_flat->VertexCount () + i); - f.index_list.push_back(f.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 (f); - -} - -/*----------------------------------------------------------------------------- - - 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; - quad_strip qs; - int column; - int mid; - int odd; - GLvertex v; - bool blank; - bool last_blank; - - qs.index_list.reserve(100); - - 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; - 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); - qs.index_list.push_back(_mesh->VertexCount () - 1); - v.position.y = (float)(start_y + height); - v.uv.y = (float)(start_y + height) / SEGMENTS_PER_TEXTURE;; - _mesh->VertexAdd (v); - qs.index_list.push_back(_mesh->VertexCount () - 1); - } - //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 (qs); - return v.uv.x; - -} - -/*----------------------------------------------------------------------------- - - 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; - //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; - quad_strip qs; - float u, v1, v2; - float cap_height; - float ledge; - - for(int i=0; i<=10; i++) - qs.index_list.push_back(i); - - //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 (qs); - 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; - quad_strip qs; - fan f; - int points; - int skip_interval; - int skip_counter; - int skip_delta; - int i; - 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); - } - qs.index_list.reserve(points); - //Add the outer walls - for (i = 0; i < points; i++) - qs.index_list.push_back(i); - _mesh->QuadStripAdd (qs); - _mesh_flat->QuadStripAdd (qs); - //add the fan to cap the top of the buildings - f.index_list.push_back(points); - for (i = 0; i < points / 2; i++) - f.index_list.push_back(points - (1 + i * 2)); - p.position.x = _center.x; - p.position.z = _center.z; - _mesh_flat->VertexAdd (p); - _mesh_flat->FanAdd (f); - 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; - int narrowing_interval; - int tiers; - float ledge; - float uv_start; - bool blank_corners; - bool roof_spike; - 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 (4) + 1; - //How the windows are grouped - grouping = RandomVal (3) + 2; - //if the corners of the building have no windows - blank_corners = RandomVal (4) > 0; - //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 (4); - //How often (in tiers) does the building get narrorwer? - narrowing_interval = 1 + RandomVal (10); - //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; - tiers = 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; - tiers++; - if ((tiers % narrowing_interval) == 0) { - 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 (); - -} - +/*----------------------------------------------------------------------------- + + Building.cpp + + 2009 Shamus Young + +------------------------------------------------------------------------------- + + This module contains the class to construct the buildings. + +-----------------------------------------------------------------------------*/ + +#define MAX_VBUFFER 256 + +#include +#include +#include +#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" +#include "win.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); + _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; + cube c; + 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]); + c.index_list.push_back(base_index + i); + } + _mesh->CubeAdd (c); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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; + cube c; + 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]); + c.index_list.push_back(base_index + i); + } + _mesh_flat->CubeAdd (c); + +} + +/*----------------------------------------------------------------------------- + + 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; + fan f; + int i; + GLvector center; + + for (i = 0; i < 5; i++) + f.index_list.push_back(_mesh_flat->VertexCount () + i); + f.index_list.push_back(f.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 (f); + +} + +/*----------------------------------------------------------------------------- + + 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; + quad_strip qs; + int column; + int mid; + int odd; + GLvertex v; + bool blank; + bool last_blank; + + qs.index_list.reserve(100); + + 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; + 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); + qs.index_list.push_back(_mesh->VertexCount () - 1); + v.position.y = (float)(start_y + height); + v.uv.y = (float)(start_y + height) / SEGMENTS_PER_TEXTURE;; + _mesh->VertexAdd (v); + qs.index_list.push_back(_mesh->VertexCount () - 1); + } + //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 (qs); + return v.uv.x; + +} + +/*----------------------------------------------------------------------------- + + 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; + //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; + quad_strip qs; + float u, v1, v2; + float cap_height; + float ledge; + + for(int i=0; i<=10; i++) + qs.index_list.push_back(i); + + //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 (qs); + 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; + quad_strip qs; + fan f; + int points; + int skip_interval; + int skip_counter; + int skip_delta; + int i; + 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); + } + qs.index_list.reserve(points); + //Add the outer walls + for (i = 0; i < points; i++) + qs.index_list.push_back(i); + _mesh->QuadStripAdd (qs); + _mesh_flat->QuadStripAdd (qs); + //add the fan to cap the top of the buildings + f.index_list.push_back(points); + for (i = 0; i < points / 2; i++) + f.index_list.push_back(points - (1 + i * 2)); + p.position.x = _center.x; + p.position.z = _center.z; + _mesh_flat->VertexAdd (p); + _mesh_flat->FanAdd (f); + 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; + int narrowing_interval; + int tiers; + float ledge; + float uv_start; + bool blank_corners; + bool roof_spike; + 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 (4) + 1; + //How the windows are grouped + grouping = RandomVal (3) + 2; + //if the corners of the building have no windows + blank_corners = RandomVal (4) > 0; + //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 (4); + //How often (in tiers) does the building get narrorwer? + narrowing_interval = 1 + RandomVal (10); + //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; + tiers = 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; + tiers++; + if ((tiers % narrowing_interval) == 0) { + 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 (); + +} diff --git a/building.h b/building.h index db0ff80..1c99230 100644 --- a/building.h +++ b/building.h @@ -1,53 +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 (); - -}; +#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 (); + +}; diff --git a/camera.cpp b/camera.cpp index f70c064..5819455 100644 --- a/camera.cpp +++ b/camera.cpp @@ -1,403 +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 -#include -#include - -#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 GLvector movement; -static bool cam_auto; -static float tracker; -static unsigned last_update; -static int camera_behavior; -static unsigned last_move; - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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, 50); //limit to 1/20th 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 / 300.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) -{ - - angle.y -= delta; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CameraPitch (float delta) -{ - - angle.x -= delta; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CameraPan (float delta) -{ - - float move_x, move_y; - - 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; - - 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 CameraVertical (float val) -{ - - movement.y += val; - last_move = GetTickCount (); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CameraLateral (float val) -{ - - movement.x += val; - last_move = GetTickCount (); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CameraMedial (float val) -{ - - movement.z += val; - last_move = GetTickCount (); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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) -{ - - CameraPan (movement.x); - CameraForward (movement.z); - position.y += movement.y / 10.0f; - if (GetTickCount () - last_move > 1000) - movement *= 0.9f; - else - movement *= 0.99f; - if (SCREENSAVER) - cam_auto = true; - if (cam_auto) - do_auto_cam (); - 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); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CameraTerm (void) -{ - - //just store our most recent position in the ini - IniVectorSet ("CameraAngle", angle); - IniVectorSet ("CameraPosition", position); - -} +/*----------------------------------------------------------------------------- + + 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 +#include +#include + +#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 GLvector movement; +static bool cam_auto; +static float tracker; +static unsigned last_update; +static int camera_behavior; +static unsigned last_move; + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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, 50); //limit to 1/20th 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 / 300.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) +{ + + angle.y -= delta; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CameraPitch (float delta) +{ + + angle.x -= delta; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CameraPan (float delta) +{ + + float move_x, move_y; + + 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; + + 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 CameraVertical (float val) +{ + + movement.y += val; + last_move = GetTickCount (); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CameraLateral (float val) +{ + + movement.x += val; + last_move = GetTickCount (); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CameraMedial (float val) +{ + + movement.z += val; + last_move = GetTickCount (); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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) +{ + + CameraPan (movement.x); + CameraForward (movement.z); + position.y += movement.y / 10.0f; + if (GetTickCount () - last_move > 1000) + movement *= 0.9f; + else + movement *= 0.99f; + if (SCREENSAVER) + cam_auto = true; + if (cam_auto) + do_auto_cam (); + 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); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CameraTerm (void) +{ + + //just store our most recent position in the ini + IniVectorSet ("CameraAngle", angle); + IniVectorSet ("CameraPosition", position); + +} diff --git a/camera.h b/camera.h index fb8ded0..5f6d899 100644 --- a/camera.h +++ b/camera.h @@ -1,24 +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 CameraPan (float delta_x); -void CameraPitch (float delta_y); -void CameraYaw (float delta_x); -void CameraVertical (float val); -void CameraLateral (float val); -void CameraMedial (float val); \ No newline at end of file +#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 CameraPan (float delta_x); +void CameraPitch (float delta_y); +void CameraYaw (float delta_x); +void CameraVertical (float val); +void CameraLateral (float val); +void CameraMedial (float val); diff --git a/car.cpp b/car.cpp index 4c0f9df..712db5e 100644 --- a/car.cpp +++ b/car.cpp @@ -1,307 +1,307 @@ -/*----------------------------------------------------------------------------- - - 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 -#include -#include -#include -#include -#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" -#include "win.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; - float top; - - if (!m_ready) - return; - if (!Visible (m_drive_position)) - return; - if (m_front) { - glColor3f (1, 1, 0.8f); - top = CAR_SIZE; - } else { - glColor3f (0.5, 0.2f, 0); - top = 0.0f; - } - - 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, top, pos.z - angles[angle].y); - glTexCoord2f (0, 1); - glVertex3f (pos.x + angles[angle].x, top, pos.z + angles[angle].y); - - glEnd (); - -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + 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 +#include +#include +#include +#include +#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" +#include "win.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; + float top; + + if (!m_ready) + return; + if (!Visible (m_drive_position)) + return; + if (m_front) { + glColor3f (1, 1, 0.8f); + top = CAR_SIZE; + } else { + glColor3f (0.5, 0.2f, 0); + top = 0.0f; + } + + 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, top, pos.z - angles[angle].y); + glTexCoord2f (0, 1); + glVertex3f (pos.x + angles[angle].x, top, pos.z + angles[angle].y); + + glEnd (); + +} diff --git a/car.h b/car.h index 47529bd..d52b5ad 100644 --- a/car.h +++ b/car.h @@ -1,30 +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 (); - +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 (); + diff --git a/deco.cpp b/deco.cpp index d756d16..1bb9833 100644 --- a/deco.cpp +++ b/deco.cpp @@ -1,291 +1,291 @@ -/*----------------------------------------------------------------------------- - - 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 -#include -#include -#include -#include -#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 () -{ - - delete _mesh; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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; - fan f; - - for(int i=0; i<6; i++) - f.index_list.push_back(i); - - 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 (f); - 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; - quad_strip qs; - float u1, u2, v1, v2; - float top; - float height, length; - GLvector2 center2d; - GLvector to; - GLvector out; - int logo_index; - - qs.index_list.push_back(0); - qs.index_list.push_back(1); - qs.index_list.push_back(3); - qs.index_list.push_back(2); - - _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 (qs); - _texture = TextureId (TEXTURE_LOGOS); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CDeco::CreateLightStrip (float x, float z, float width, float depth, float height, GLrgba color) -{ - - GLvertex p; - quad_strip qs1; - float u, v; - - qs1.index_list.push_back(0); - qs1.index_list.push_back(1); - qs1.index_list.push_back(3); - qs1.index_list.push_back(2); - _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)); - } - _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); - _mesh->QuadStripAdd (qs1); - _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; - quad_strip qs; - - _color = color; - _center = glVector (0.0f, 0.0f, 0.0f); - qs.index_list.reserve(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); - qs.index_list.push_back(index++); - //Top point - p.position.y += height;p.uv = glVector (u, v1); - _mesh->VertexAdd (p); - qs.index_list.push_back(index++); - } - _mesh->QuadStripAdd (qs); - _texture = TextureId (TEXTURE_TRIM); - _mesh->Compile (); - -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + 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 +#include +#include +#include +#include +#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 () +{ + + delete _mesh; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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; + fan f; + + for(int i=0; i<6; i++) + f.index_list.push_back(i); + + 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 (f); + 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; + quad_strip qs; + float u1, u2, v1, v2; + float top; + float height, length; + GLvector2 center2d; + GLvector to; + GLvector out; + int logo_index; + + qs.index_list.push_back(0); + qs.index_list.push_back(1); + qs.index_list.push_back(3); + qs.index_list.push_back(2); + + _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 (qs); + _texture = TextureId (TEXTURE_LOGOS); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CDeco::CreateLightStrip (float x, float z, float width, float depth, float height, GLrgba color) +{ + + GLvertex p; + quad_strip qs1; + float u, v; + + qs1.index_list.push_back(0); + qs1.index_list.push_back(1); + qs1.index_list.push_back(3); + qs1.index_list.push_back(2); + _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)); + } + _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); + _mesh->QuadStripAdd (qs1); + _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; + quad_strip qs; + + _color = color; + _center = glVector (0.0f, 0.0f, 0.0f); + qs.index_list.reserve(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); + qs.index_list.push_back(index++); + //Top point + p.position.y += height;p.uv = glVector (u, v1); + _mesh->VertexAdd (p); + qs.index_list.push_back(index++); + } + _mesh->QuadStripAdd (qs); + _texture = TextureId (TEXTURE_TRIM); + _mesh->Compile (); + +} diff --git a/deco.h b/deco.h index 01875dc..367f47d 100644 --- a/deco.h +++ b/deco.h @@ -1,28 +1,28 @@ -#ifndef ENTITY -#include "entity.h" -#endif - -class CDeco : CEntity -{ - GLrgba _color; - class CMesh* _mesh; - int _type; - unsigned _texture; - bool _use_alpha; - -public: - - CDeco (); - ~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 (); - -}; \ No newline at end of file +#ifndef ENTITY +#include "entity.h" +#endif + +class CDeco : CEntity +{ + GLrgba _color; + class CMesh* _mesh; + int _type; + unsigned _texture; + bool _use_alpha; + +public: + + CDeco (); + ~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 (); + +}; diff --git a/entity.cpp b/entity.cpp index 8b6ec86..79d3a01 100644 --- a/entity.cpp +++ b/entity.cpp @@ -1,399 +1,397 @@ -/*----------------------------------------------------------------------------- - - 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 -#include -#include - -#include "camera.h" -#include "entity.h" -#include "macro.h" -#include "math.h" -#include "render.h" -#include "texture.h" -#include "world.h" -#include "visible.h" -#include "win.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 compile_end; - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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_end = GetTickCount (); - } - compile_count++; - - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -bool EntityReady () -{ - - return compiled; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -float EntityProgress () -{ - - return (float)compile_count / (GRID_SIZE * GRID_SIZE); - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void EntityUpdate () -{ - - unsigned stop_time; - - if (!TextureReady ()) { - sorted = false; - return; - } - if (!sorted) { - qsort (entity_list, entity_count, sizeof (struct entity), do_compare); - sorted = true; - } - //We want to do several cells at once. Enough to get things done, but - //not so many that the program is unresponsive. - if (LOADING_SCREEN) { //If we're using a loading screen, we want to build as fast as possible - stop_time = GetTickCount () + 100; - while (!compiled && GetTickCount () < stop_time) - do_compile (); - } else //Take it slow - do_compile (); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void EntityRender () -{ - - int polymode[2]; - bool wireframe; - int x, y; - int elapsed; - - //Draw all textured objects - glGetIntegerv (GL_POLYGON_MODE, &polymode[0]); - wireframe = polymode[0] != GL_FILL; - if (RenderFlat ()) - glDisable (GL_TEXTURE_2D); - //If we're not using a loading screen, make the wireframe fade out via fog - if (!LOADING_SCREEN && wireframe) { - elapsed = 6000 - WorldSceneElapsed (); - if (elapsed >= 0 && elapsed <= 6000) - RenderFogFX ((float)elapsed / 6000.0f); - else - return; - } - 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) -{ - - -} - - +/*----------------------------------------------------------------------------- + + 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 +#include +#include + +#include "camera.h" +#include "entity.h" +#include "macro.h" +#include "math.h" +#include "render.h" +#include "texture.h" +#include "world.h" +#include "visible.h" +#include "win.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 compile_end; + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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_end = GetTickCount (); + } + compile_count++; + + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +bool EntityReady () +{ + + return compiled; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +float EntityProgress () +{ + + return (float)compile_count / (GRID_SIZE * GRID_SIZE); + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void EntityUpdate () +{ + + unsigned stop_time; + + if (!TextureReady ()) { + sorted = false; + return; + } + if (!sorted) { + qsort (entity_list, entity_count, sizeof (struct entity), do_compare); + sorted = true; + } + //We want to do several cells at once. Enough to get things done, but + //not so many that the program is unresponsive. + if (LOADING_SCREEN) { //If we're using a loading screen, we want to build as fast as possible + stop_time = GetTickCount () + 100; + while (!compiled && GetTickCount () < stop_time) + do_compile (); + } else //Take it slow + do_compile (); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void EntityRender () +{ + + int polymode[2]; + bool wireframe; + int x, y; + int elapsed; + + //Draw all textured objects + glGetIntegerv (GL_POLYGON_MODE, &polymode[0]); + wireframe = polymode[0] != GL_FILL; + if (RenderFlat ()) + glDisable (GL_TEXTURE_2D); + //If we're not using a loading screen, make the wireframe fade out via fog + if (!LOADING_SCREEN && wireframe) { + elapsed = 6000 - WorldSceneElapsed (); + if (elapsed >= 0 && elapsed <= 6000) + RenderFogFX ((float)elapsed / 6000.0f); + else + return; + } + 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) +{ + + +} diff --git a/entity.h b/entity.h index c9d1fae..3a86e40 100644 --- a/entity.h +++ b/entity.h @@ -1,37 +1,37 @@ -#ifndef TYPES -#include "glTypes.h" -#endif - -#ifndef ENTITY - -#define ENTITY - -class CEntity -{ -private: -protected: - - GLvector _center; - -public: - CEntity (void); - virtual ~CEntity () {}; - 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; } - GLvector Center () { return _center; } - -}; - -void EntityClear (); -int EntityCount (void); -float EntityProgress (); -bool EntityReady (); -void EntityRender (void); -void EntityUpdate (void); -int EntityPolyCount (void); - -#endif \ No newline at end of file +#ifndef TYPES +#include "glTypes.h" +#endif + +#ifndef ENTITY + +#define ENTITY + +class CEntity +{ +private: +protected: + + GLvector _center; + +public: + CEntity (void); + virtual ~CEntity () {}; + 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; } + GLvector Center () { return _center; } + +}; + +void EntityClear (); +int EntityCount (void); +float EntityProgress (); +bool EntityReady (); +void EntityRender (void); +void EntityUpdate (void); +int EntityPolyCount (void); + +#endif diff --git a/glTypes.h b/glTypes.h index 0be898e..1025799 100644 --- a/glTypes.h +++ b/glTypes.h @@ -1,209 +1,208 @@ -#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 - +#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 diff --git a/glbbox.cpp b/glbbox.cpp index d2af243..dfb6124 100644 --- a/glbbox.cpp +++ b/glbbox.cpp @@ -1,70 +1,68 @@ -/*----------------------------------------------------------------------------- - - glBbox.cpp - - 2006 Shamus Young - -------------------------------------------------------------------------------- - - This module has a few functions useful for manipulating the bounding-box - structs. - ------------------------------------------------------------------------------*/ - -#define MAX_VALUE 999999999999999.9f - -#include - -#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; - -} - - +/*----------------------------------------------------------------------------- + + glBbox.cpp + + 2006 Shamus Young + +------------------------------------------------------------------------------- + + This module has a few functions useful for manipulating the bounding-box + structs. + +-----------------------------------------------------------------------------*/ + +#define MAX_VALUE 999999999999999.9f + +#include + +#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; + +} diff --git a/glmatrix.cpp b/glmatrix.cpp index 22496ad..6762b0b 100644 --- a/glmatrix.cpp +++ b/glmatrix.cpp @@ -1,318 +1,318 @@ -/*----------------------------------------------------------------------------- - - 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) - -#include -#include - -#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); -} +/*----------------------------------------------------------------------------- + + 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) + +#include +#include + +#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); +} diff --git a/glquat.cpp b/glquat.cpp index ebe8286..d33b159 100644 --- a/glquat.cpp +++ b/glquat.cpp @@ -1,78 +1,78 @@ -/*----------------------------------------------------------------------------- - - glQuat.cpp - - 2006 Shamus Young - -------------------------------------------------------------------------------- - - Functions for dealing with Quaternions - ------------------------------------------------------------------------------*/ - -#include -#include -#include -#include - -#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)); -} +/*----------------------------------------------------------------------------- + + glQuat.cpp + + 2006 Shamus Young + +------------------------------------------------------------------------------- + + Functions for dealing with Quaternions + +-----------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#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)); +} diff --git a/glrgba.cpp b/glrgba.cpp index 9405368..a69f5b3 100644 --- a/glrgba.cpp +++ b/glrgba.cpp @@ -1,401 +1,401 @@ -/*----------------------------------------------------------------------------- - - glRgba.cpp - - 2009 Shamus Young - -------------------------------------------------------------------------------- - - Functions for dealing with RGBA color values. - ------------------------------------------------------------------------------*/ - -#include -#include -#include -#include - -#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); -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + glRgba.cpp + + 2009 Shamus Young + +------------------------------------------------------------------------------- + + Functions for dealing with RGBA color values. + +-----------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#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); +} diff --git a/glvector2.cpp b/glvector2.cpp index 8bedd51..4517aed 100644 --- a/glvector2.cpp +++ b/glvector2.cpp @@ -1,223 +1,223 @@ -/*----------------------------------------------------------------------------- - - Vector2.cpp - - 2006 Shamus Young - -------------------------------------------------------------------------------- - - Functions for dealing with 2d (usually texture mapping) values. - ------------------------------------------------------------------------------*/ - -#include -#include -#include -#include - -#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; -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + Vector2.cpp + + 2006 Shamus Young + +------------------------------------------------------------------------------- + + Functions for dealing with 2d (usually texture mapping) values. + +-----------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#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; +} diff --git a/glvector3.cpp b/glvector3.cpp index 1c09409..a81187d 100644 --- a/glvector3.cpp +++ b/glvector3.cpp @@ -1,256 +1,256 @@ -/*----------------------------------------------------------------------------- - - glVector3.cpp - - 2006 Shamus Young - -------------------------------------------------------------------------------- - - Functions for dealing with 3d vectors. - ------------------------------------------------------------------------------*/ - -#include -#include -#include -#include - -#include "macro.h" -#include "math.h" -#include "glTypes.h" - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -GLvector glVectorReflect (GLvector3 ray, GLvector3 normal) -{ - - float dot; - - dot = glVectorDotProduct (ray, normal); - 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; -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + glVector3.cpp + + 2006 Shamus Young + +------------------------------------------------------------------------------- + + Functions for dealing with 3d vectors. + +-----------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "macro.h" +#include "math.h" +#include "glTypes.h" + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +GLvector glVectorReflect (GLvector3 ray, GLvector3 normal) +{ + + float dot; + + dot = glVectorDotProduct (ray, normal); + 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; +} diff --git a/ini.cpp b/ini.cpp index bd3ab45..8c7e49e 100644 --- a/ini.cpp +++ b/ini.cpp @@ -1,137 +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 -#include -#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; - -} +/*----------------------------------------------------------------------------- + + 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 +#include +#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; + +} diff --git a/ini.h b/ini.h index 7a51d81..37842ef 100644 --- a/ini.h +++ b/ini.h @@ -1,8 +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); +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); diff --git a/light.cpp b/light.cpp index 6c94ceb..fa9a9c6 100644 --- a/light.cpp +++ b/light.cpp @@ -1,176 +1,176 @@ -/*----------------------------------------------------------------------------- - - 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 -#include -#include -#include -#include -#include "glTypes.h" - -#include "camera.h" -#include "entity.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 (!EntityReady ()) - return; - 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; - _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; - 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); - -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + 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 +#include +#include +#include +#include +#include "glTypes.h" + +#include "camera.h" +#include "entity.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 (!EntityReady ()) + return; + 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; + _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; + 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); + +} diff --git a/light.h b/light.h index 42ec7e1..a94a0f6 100644 --- a/light.h +++ b/light.h @@ -1,23 +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 (); +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 (); diff --git a/macro.h b/macro.h index e0a8361..284d244 100644 --- a/macro.h +++ b/macro.h @@ -1,15 +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;} +#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;} diff --git a/math.cpp b/math.cpp index d0fd3f5..c36f444 100644 --- a/math.cpp +++ b/math.cpp @@ -1,181 +1,181 @@ -/*----------------------------------------------------------------------------- - - Math.cpp - - 2009 Shamus Young - -------------------------------------------------------------------------------- - - Various useful math functions. - ------------------------------------------------------------------------------*/ - -#include - -#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.0f); - 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; - -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + Math.cpp + + 2009 Shamus Young + +------------------------------------------------------------------------------- + + Various useful math functions. + +-----------------------------------------------------------------------------*/ + +#include + +#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.0f); + 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; + +} diff --git a/math.h b/math.h index a155295..60e0d6c 100644 --- a/math.h +++ b/math.h @@ -1,10 +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); \ No newline at end of file +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); diff --git a/mesh.cpp b/mesh.cpp index 97f8766..599ae1e 100644 --- a/mesh.cpp +++ b/mesh.cpp @@ -1,178 +1,178 @@ -/*----------------------------------------------------------------------------- - - 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 -#include -#include - -#include -#include "glTypes.h" -#include "mesh.h" - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -CMesh::CMesh () -{ - - _list = glGenLists(1); - _compiled = false; - _polycount = 0; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -CMesh::~CMesh () -{ - - glDeleteLists (_list, 1); - _vertex.clear (); - _fan.clear (); - _quad_strip.clear (); - _cube.clear (); - - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CMesh::VertexAdd (const GLvertex& v) -{ - - _vertex.push_back(v); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CMesh::CubeAdd (const cube& c) -{ - - _cube.push_back(c); - _polycount += 5; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CMesh::QuadStripAdd (const quad_strip& qs) -{ - - _quad_strip.push_back(qs); - _polycount += (qs.index_list.size() - 2) / 2; - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CMesh::FanAdd (const fan& f) -{ - - _fan.push_back(f); - _polycount += f.index_list.size() - 2; - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CMesh::Render () -{ - - std::vector::iterator qsi; - std::vector::iterator ci; - std::vector::iterator fi; - std::vector::iterator n; - - if (_compiled) { - glCallList (_list); - return; - } - for (qsi = _quad_strip.begin(); qsi < _quad_strip.end(); ++qsi) { - glBegin (GL_QUAD_STRIP); - for (n = qsi->index_list.begin(); n < qsi->index_list.end(); ++n) { - glTexCoord2fv (&_vertex[*n].uv.x); - glVertex3fv (&_vertex[*n].position.x); - } - glEnd (); - } - for (ci = _cube.begin(); ci < _cube.end(); ++ci) { - glBegin (GL_QUAD_STRIP); - for (n = ci->index_list.begin(); n < ci->index_list.end(); ++n) { - glTexCoord2fv (&_vertex[*n].uv.x); - glVertex3fv (&_vertex[*n].position.x); - } - glEnd (); - - glBegin (GL_QUADS); - glTexCoord2fv (&_vertex[ci->index_list[7]].uv.x); - glVertex3fv (&_vertex[ci->index_list[7]].position.x); - glVertex3fv (&_vertex[ci->index_list[5]].position.x); - glVertex3fv (&_vertex[ci->index_list[3]].position.x); - glVertex3fv (&_vertex[ci->index_list[1]].position.x); - glEnd (); - - glBegin (GL_QUADS); - glTexCoord2fv (&_vertex[ci->index_list[6]].uv.x); - glVertex3fv (&_vertex[ci->index_list[0]].position.x); - glVertex3fv (&_vertex[ci->index_list[2]].position.x); - glVertex3fv (&_vertex[ci->index_list[4]].position.x); - glVertex3fv (&_vertex[ci->index_list[6]].position.x); - glEnd (); - - - } - for (fi = _fan.begin(); fi < _fan.end(); ++fi) { - glBegin (GL_TRIANGLE_FAN); - for (n = fi->index_list.begin(); n < fi->index_list.end(); ++n) { - glTexCoord2fv (&_vertex[*n].uv.x); - glVertex3fv (&_vertex[*n].position.x); - } - glEnd (); - } - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CMesh::Compile () -{ - - glNewList (_list, GL_COMPILE); - Render (); - glEndList(); - _compiled = true; - -} +/*----------------------------------------------------------------------------- + + 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 +#include +#include + +#include +#include "glTypes.h" +#include "mesh.h" + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +CMesh::CMesh () +{ + + _list = glGenLists(1); + _compiled = false; + _polycount = 0; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +CMesh::~CMesh () +{ + + glDeleteLists (_list, 1); + _vertex.clear (); + _fan.clear (); + _quad_strip.clear (); + _cube.clear (); + + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CMesh::VertexAdd (const GLvertex& v) +{ + + _vertex.push_back(v); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CMesh::CubeAdd (const cube& c) +{ + + _cube.push_back(c); + _polycount += 5; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CMesh::QuadStripAdd (const quad_strip& qs) +{ + + _quad_strip.push_back(qs); + _polycount += (qs.index_list.size() - 2) / 2; + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CMesh::FanAdd (const fan& f) +{ + + _fan.push_back(f); + _polycount += f.index_list.size() - 2; + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CMesh::Render () +{ + + std::vector::iterator qsi; + std::vector::iterator ci; + std::vector::iterator fi; + std::vector::iterator n; + + if (_compiled) { + glCallList (_list); + return; + } + for (qsi = _quad_strip.begin(); qsi < _quad_strip.end(); ++qsi) { + glBegin (GL_QUAD_STRIP); + for (n = qsi->index_list.begin(); n < qsi->index_list.end(); ++n) { + glTexCoord2fv (&_vertex[*n].uv.x); + glVertex3fv (&_vertex[*n].position.x); + } + glEnd (); + } + for (ci = _cube.begin(); ci < _cube.end(); ++ci) { + glBegin (GL_QUAD_STRIP); + for (n = ci->index_list.begin(); n < ci->index_list.end(); ++n) { + glTexCoord2fv (&_vertex[*n].uv.x); + glVertex3fv (&_vertex[*n].position.x); + } + glEnd (); + + glBegin (GL_QUADS); + glTexCoord2fv (&_vertex[ci->index_list[7]].uv.x); + glVertex3fv (&_vertex[ci->index_list[7]].position.x); + glVertex3fv (&_vertex[ci->index_list[5]].position.x); + glVertex3fv (&_vertex[ci->index_list[3]].position.x); + glVertex3fv (&_vertex[ci->index_list[1]].position.x); + glEnd (); + + glBegin (GL_QUADS); + glTexCoord2fv (&_vertex[ci->index_list[6]].uv.x); + glVertex3fv (&_vertex[ci->index_list[0]].position.x); + glVertex3fv (&_vertex[ci->index_list[2]].position.x); + glVertex3fv (&_vertex[ci->index_list[4]].position.x); + glVertex3fv (&_vertex[ci->index_list[6]].position.x); + glEnd (); + + + } + for (fi = _fan.begin(); fi < _fan.end(); ++fi) { + glBegin (GL_TRIANGLE_FAN); + for (n = fi->index_list.begin(); n < fi->index_list.end(); ++n) { + glTexCoord2fv (&_vertex[*n].uv.x); + glVertex3fv (&_vertex[*n].position.x); + } + glEnd (); + } + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CMesh::Compile () +{ + + glNewList (_list, GL_COMPILE); + Render (); + glEndList(); + _compiled = true; + +} diff --git a/mesh.h b/mesh.h index 4513a62..08677c9 100644 --- a/mesh.h +++ b/mesh.h @@ -1,41 +1,40 @@ - -#include - -struct cube -{ - std::vector index_list; // probably always .size() == 10... -}; - -struct quad_strip -{ - std::vector index_list; -}; - -struct fan -{ - std::vector index_list; -}; - -class CMesh -{ -public: - CMesh (); - ~CMesh (); - unsigned _list; - int _polycount; - std::vector _vertex; - std::vector _cube; - std::vector _quad_strip; - std::vector _fan; - bool _compiled; - - void VertexAdd (const GLvertex& v); - int VertexCount () { return _vertex.size(); } - int PolyCount () { return _polycount; } - void CubeAdd (const cube& c); - void QuadStripAdd (const quad_strip& qs); - void FanAdd (const fan& f); - void Render (); - void Compile (); - -}; +#include + +struct cube +{ + std::vector index_list; // probably always .size() == 10... +}; + +struct quad_strip +{ + std::vector index_list; +}; + +struct fan +{ + std::vector index_list; +}; + +class CMesh +{ +public: + CMesh (); + ~CMesh (); + unsigned _list; + int _polycount; + std::vector _vertex; + std::vector _cube; + std::vector _quad_strip; + std::vector _fan; + bool _compiled; + + void VertexAdd (const GLvertex& v); + int VertexCount () { return _vertex.size(); } + int PolyCount () { return _polycount; } + void CubeAdd (const cube& c); + void QuadStripAdd (const quad_strip& qs); + void FanAdd (const fan& f); + void Render (); + void Compile (); + +}; diff --git a/random.cpp b/random.cpp index 41888c0..e7f5cea 100644 --- a/random.cpp +++ b/random.cpp @@ -1,93 +1,92 @@ -/*----------------------------------------------------------------------------- - r a n d o m ------------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------- - The Mersenne Twister by Matsumoto and Nishimura . - 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 -#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; - -} - +/*----------------------------------------------------------------------------- + r a n d o m +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + The Mersenne Twister by Matsumoto and Nishimura . + 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 +#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; + +} diff --git a/random.h b/random.h index e9d8420..5cb607d 100644 --- a/random.h +++ b/random.h @@ -1,5 +1,5 @@ -#define COIN_FLIP (RandomVal (2) == 0) - -unsigned long RandomVal (int range); -unsigned long RandomVal (void); -void RandomInit (unsigned long seed); +#define COIN_FLIP (RandomVal (2) == 0) + +unsigned long RandomVal (int range); +unsigned long RandomVal (void); +void RandomInit (unsigned long seed); diff --git a/render.cpp b/render.cpp index d66b1d6..224db2c 100644 --- a/render.cpp +++ b/render.cpp @@ -1,842 +1,842 @@ -/*----------------------------------------------------------------------------- - - 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 -#include -#include -#include -#include - -#include -#include - -#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_COUNT, - EFFECT_DEBUG, - EFFECT_DEBUG_OVERBLOOM, -}; -#else -enum -{ - EFFECT_NONE, - EFFECT_BLOOM, - EFFECT_COUNT, - EFFECT_DEBUG_OVERBLOOM, - EFFECT_DEBUG, - 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 unsigned next_fps; -static unsigned current_fps; -static unsigned frames; -static bool show_wireframe; -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) { - 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 ()) - return; - //Now change projection modes so we can render full-screen effects - 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); - glDisable (GL_FOG); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - //Render full-screen effects - glBlendFunc (GL_ONE, GL_ONE); - glEnable (GL_TEXTURE_2D); - glDisable(GL_DEPTH_TEST); - glDepthMask (false); - 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 * 2; - 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.01f; - 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 - if (LOADING_SCREEN) { - if (fade > 0.0f) { - 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); - RenderPrint (1, "%s v%d.%d.%03d", APP_TITLE, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); - } - } - glPopMatrix (); - glMatrixMode (GL_PROJECTION); - glPopMatrix (); - glMatrixMode (GL_MODELVIEW); - glEnable(GL_DEPTH_TEST); - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -int RenderMaxTextureSize () -{ - - int mts; - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mts); - mts = MIN (mts, render_width); - return MIN (mts, render_height); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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); - glMatrixMode (GL_PROJECTION); - glPushMatrix (); - glLoadIdentity (); - glOrtho (0, render_width, render_height, 0, 0.1f, 2048); - glDisable(GL_DEPTH_TEST); - glDepthMask (false); - glMatrixMode (GL_MODELVIEW); - glPushMatrix (); - glLoadIdentity(); - glTranslatef(0, 0, -1.0f); - glDisable (GL_BLEND); - glDisable (GL_FOG); - glDisable (GL_TEXTURE_2D); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - 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 + 2, text); - text = strtok (NULL, "\n"); - line++; - } - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void do_fps () -{ - - LIMIT_INTERVAL (1000); - current_fps = frames; - frames = 0; - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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); - } - //If the program is running for the first time, set the defaults. - if (!IniInt ("SetDefaults")) { - IniIntSet ("SetDefaults", 1); - IniIntSet ("Effect", EFFECT_BLOOM); - IniIntSet ("ShowFog", 1); - } - //load in our settings - letterbox = IniInt ("Letterbox") != 0; - show_wireframe = IniInt ("Wireframe") != 0; - show_fps = IniInt ("ShowFPS") != 0; - show_fog = IniInt ("ShowFog") != 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; - -} - -/*----------------------------------------------------------------------------- - - This is used to set a gradient fog that goes from camera to some portion of - the normal fog distance. This is used for making wireframe outlines and - flat surfaces fade out after rebuild. Looks cool. - ------------------------------------------------------------------------------*/ - -void RenderFogFX (float scalar) -{ - - if (scalar >= 1.0f) { - glDisable (GL_FOG); - return; - } - glFogf (GL_FOG_START, 0.0f); - glFogf (GL_FOG_END, fog_distance * 2.0f * scalar); - glEnable (GL_FOG); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void RenderUpdate (void) -{ - - GLvector pos; - GLvector angle; - GLrgba color; - int elapsed; - - frames++; - do_fps (); - glViewport (0, 0, WinWidth (), WinHeight ()); - glDepthMask (true); - glClearColor (0.0f, 0.0f, 0.0f, 1.0f); - glEnable(GL_DEPTH_TEST); - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - if (letterbox) - glViewport (0, letterbox_offset, render_width, render_height); - if (LOADING_SCREEN && TextureReady () && !EntityReady ()) { - do_effects (EFFECT_NONE); - SwapBuffers (hDC); - return; - } - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glShadeModel(GL_SMOOTH); - glFogi (GL_FOG_MODE, GL_LINEAR); - glDepthFunc(GL_LEQUAL); - 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 (1.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. - glDisable (GL_FOG); - SkyRender (); - 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); - } - 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 (); - if (!LOADING_SCREEN) { - elapsed = 3000 - WorldSceneElapsed (); - if (elapsed >= 0 && elapsed <= 3000) { - RenderFogFX ((float)elapsed / 3000.0f); - glDisable (GL_TEXTURE_2D); - glEnable (GL_BLEND); - glBlendFunc (GL_ONE, GL_ONE); - EntityRender (); - } - } - if (EntityReady ()) - LightRender (); - CarRender (); - if (show_wireframe) { - glDisable (GL_TEXTURE_2D); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - EntityRender (); - } - do_effects (effect); - //Framerate tracker - if (show_fps) - RenderPrint (1, "FPS=%d : Entities=%d : polys=%d", current_fps, EntityCount () + LightCount () + CarCount (), EntityPolyCount () + LightCount () + CarCount ()); - //Show the help overlay - if (show_help) - do_help (); - SwapBuffers (hDC); - -} +/*----------------------------------------------------------------------------- + + 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 +#include +#include +#include +#include + +#include +#include + +#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_COUNT, + EFFECT_DEBUG, + EFFECT_DEBUG_OVERBLOOM, +}; +#else +enum +{ + EFFECT_NONE, + EFFECT_BLOOM, + EFFECT_COUNT, + EFFECT_DEBUG_OVERBLOOM, + EFFECT_DEBUG, + 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 unsigned next_fps; +static unsigned current_fps; +static unsigned frames; +static bool show_wireframe; +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) { + 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 ()) + return; + //Now change projection modes so we can render full-screen effects + 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); + glDisable (GL_FOG); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + //Render full-screen effects + glBlendFunc (GL_ONE, GL_ONE); + glEnable (GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glDepthMask (false); + 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 * 2; + 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.01f; + 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 + if (LOADING_SCREEN) { + if (fade > 0.0f) { + 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); + RenderPrint (1, "%s v%d.%d.%03d", APP_TITLE, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); + } + } + glPopMatrix (); + glMatrixMode (GL_PROJECTION); + glPopMatrix (); + glMatrixMode (GL_MODELVIEW); + glEnable(GL_DEPTH_TEST); + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +int RenderMaxTextureSize () +{ + + int mts; + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mts); + mts = MIN (mts, render_width); + return MIN (mts, render_height); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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); + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + glLoadIdentity (); + glOrtho (0, render_width, render_height, 0, 0.1f, 2048); + glDisable(GL_DEPTH_TEST); + glDepthMask (false); + glMatrixMode (GL_MODELVIEW); + glPushMatrix (); + glLoadIdentity(); + glTranslatef(0, 0, -1.0f); + glDisable (GL_BLEND); + glDisable (GL_FOG); + glDisable (GL_TEXTURE_2D); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + 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 + 2, text); + text = strtok (NULL, "\n"); + line++; + } + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void do_fps () +{ + + LIMIT_INTERVAL (1000); + current_fps = frames; + frames = 0; + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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); + } + //If the program is running for the first time, set the defaults. + if (!IniInt ("SetDefaults")) { + IniIntSet ("SetDefaults", 1); + IniIntSet ("Effect", EFFECT_BLOOM); + IniIntSet ("ShowFog", 1); + } + //load in our settings + letterbox = IniInt ("Letterbox") != 0; + show_wireframe = IniInt ("Wireframe") != 0; + show_fps = IniInt ("ShowFPS") != 0; + show_fog = IniInt ("ShowFog") != 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; + +} + +/*----------------------------------------------------------------------------- + + This is used to set a gradient fog that goes from camera to some portion of + the normal fog distance. This is used for making wireframe outlines and + flat surfaces fade out after rebuild. Looks cool. + +-----------------------------------------------------------------------------*/ + +void RenderFogFX (float scalar) +{ + + if (scalar >= 1.0f) { + glDisable (GL_FOG); + return; + } + glFogf (GL_FOG_START, 0.0f); + glFogf (GL_FOG_END, fog_distance * 2.0f * scalar); + glEnable (GL_FOG); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void RenderUpdate (void) +{ + + GLvector pos; + GLvector angle; + GLrgba color; + int elapsed; + + frames++; + do_fps (); + glViewport (0, 0, WinWidth (), WinHeight ()); + glDepthMask (true); + glClearColor (0.0f, 0.0f, 0.0f, 1.0f); + glEnable(GL_DEPTH_TEST); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (letterbox) + glViewport (0, letterbox_offset, render_width, render_height); + if (LOADING_SCREEN && TextureReady () && !EntityReady ()) { + do_effects (EFFECT_NONE); + SwapBuffers (hDC); + return; + } + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glShadeModel(GL_SMOOTH); + glFogi (GL_FOG_MODE, GL_LINEAR); + glDepthFunc(GL_LEQUAL); + 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 (1.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. + glDisable (GL_FOG); + SkyRender (); + 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); + } + 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 (); + if (!LOADING_SCREEN) { + elapsed = 3000 - WorldSceneElapsed (); + if (elapsed >= 0 && elapsed <= 3000) { + RenderFogFX ((float)elapsed / 3000.0f); + glDisable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE); + EntityRender (); + } + } + if (EntityReady ()) + LightRender (); + CarRender (); + if (show_wireframe) { + glDisable (GL_TEXTURE_2D); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + EntityRender (); + } + do_effects (effect); + //Framerate tracker + if (show_fps) + RenderPrint (1, "FPS=%d : Entities=%d : polys=%d", current_fps, EntityCount () + LightCount () + CarCount (), EntityPolyCount () + LightCount () + CarCount ()); + //Show the help overlay + if (show_help) + do_help (); + SwapBuffers (hDC); + +} diff --git a/render.h b/render.h index aa78163..1095652 100644 --- a/render.h +++ b/render.h @@ -1,27 +1,27 @@ -bool RenderBloom (); -void RenderEffectCycle (); -bool RenderFlat (); -void RenderFlatToggle (); -float RenderFogDistance (); -bool RenderFog (); -void RenderFogToggle (); -void RenderFogFX (float scalar); -void RenderFPSToggle (); -void RenderInit (); -void RenderLetterboxToggle (); -int RenderMaxTextureSize (); -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, ...); -void RenderPrint (int line, const char *fmt, ...); - - - - - - - +bool RenderBloom (); +void RenderEffectCycle (); +bool RenderFlat (); +void RenderFlatToggle (); +float RenderFogDistance (); +bool RenderFog (); +void RenderFogToggle (); +void RenderFogFX (float scalar); +void RenderFPSToggle (); +void RenderInit (); +void RenderLetterboxToggle (); +int RenderMaxTextureSize (); +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, ...); +void RenderPrint (int line, const char *fmt, ...); + + + + + + + diff --git a/sky.cpp b/sky.cpp index 11b70d9..db8d373 100644 --- a/sky.cpp +++ b/sky.cpp @@ -1,141 +1,141 @@ -/*----------------------------------------------------------------------------- - - 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 -#include -#include - -#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 (!TextureReady ()) - return; - glDepthMask (false); - glPushAttrib (GL_POLYGON_BIT | GL_FOG_BIT); - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - glDisable (GL_CULL_FACE); - glDisable (GL_FOG); - 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); - 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(); - sky = this; - -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + 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 +#include +#include + +#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 (!TextureReady ()) + return; + glDepthMask (false); + glPushAttrib (GL_POLYGON_BIT | GL_FOG_BIT); + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glDisable (GL_CULL_FACE); + glDisable (GL_FOG); + 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); + 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(); + sky = this; + +} diff --git a/sky.h b/sky.h index 8269261..213a1c9 100644 --- a/sky.h +++ b/sky.h @@ -1,24 +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 (); +#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 (); diff --git a/texture.cpp b/texture.cpp index 3174160..bca8137 100644 --- a/texture.cpp +++ b/texture.cpp @@ -1,873 +1,873 @@ -/*----------------------------------------------------------------------------- - - 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, and is badly 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 -#include -#include -#include -#include -#include - -#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" -#include "win.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", - " LLC" -}; - -class CTexture -{ -public: - int _my_id; - unsigned _glid; - int _desired_size; - 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 (); - void DrawSky (); - void DrawHeadlight (); -}; - -static CTexture* head; -static bool textures_done; -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; - 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); - 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; - _desired_size = size; - _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--; - - } - } - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CTexture::DrawSky () -{ - - GLrgba color; - float grey; - float scale, inv_scale; - int i, x, y; - int width, height; - int offset; - int width_adjust; - int height_adjust; - - color = WorldBloomColor (); - grey = (color.red + color.green + color.blue) / 3.0f; - //desaturate, slightly dim - color = (color + glRgba (grey) * 2.0f) / 15.0f; - glDisable (GL_BLEND); - glBegin (GL_QUAD_STRIP); - glColor3f (0,0,0); - glVertex2i (0, _half); - glVertex2i (_size, _half); - glColor3fv (&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)); - //Draw the clouds - for (i = _size - 30; i > 5; i -= 2) { - - 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) { - - inv_scale = 1.0f - (scale); - if (scale < 0.4f) - color = WorldBloomColor () * 0.1f; - else - color = glRgba (0.0f); - color.alpha = 0.2f; - glColor4fv (&color.red); - 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 (); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CTexture::DrawHeadlight () -{ - - float radius; - int i, x, y; - GLvector2 pos; - - //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)); - -} - -/*----------------------------------------------------------------------------- - - 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; - int max_size; - float radius; - GLvector2 pos; - bool use_framebuffer; - unsigned char* bits; - unsigned start; - int lapsed; - - start = GetTickCount (); - //Since we make textures by drawing into the viewport, we can't make them bigger - //than the current view. - _size = _desired_size; - max_size = RenderMaxTextureSize (); - while (_size > max_size) - _size /= 2; - glBindTexture(GL_TEXTURE_2D, _glid); - //Set up the texture - 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); - glDisable (GL_FOG); - 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_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, 1, 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: - DrawHeadlight (); - 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]); - 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_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: - DrawSky (); - 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) -{ - - textures_done = false; - build_time = 0; - for (CTexture* t = head; t; t = t->_next) - t->Clear (); - 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_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); - 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; - -} +/*----------------------------------------------------------------------------- + + 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, and is badly 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 +#include +#include +#include +#include +#include + +#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" +#include "win.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", + " LLC" +}; + +class CTexture +{ +public: + int _my_id; + unsigned _glid; + int _desired_size; + 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 (); + void DrawSky (); + void DrawHeadlight (); +}; + +static CTexture* head; +static bool textures_done; +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; + 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); + 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; + _desired_size = size; + _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--; + + } + } + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CTexture::DrawSky () +{ + + GLrgba color; + float grey; + float scale, inv_scale; + int i, x, y; + int width, height; + int offset; + int width_adjust; + int height_adjust; + + color = WorldBloomColor (); + grey = (color.red + color.green + color.blue) / 3.0f; + //desaturate, slightly dim + color = (color + glRgba (grey) * 2.0f) / 15.0f; + glDisable (GL_BLEND); + glBegin (GL_QUAD_STRIP); + glColor3f (0,0,0); + glVertex2i (0, _half); + glVertex2i (_size, _half); + glColor3fv (&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)); + //Draw the clouds + for (i = _size - 30; i > 5; i -= 2) { + + 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) { + + inv_scale = 1.0f - (scale); + if (scale < 0.4f) + color = WorldBloomColor () * 0.1f; + else + color = glRgba (0.0f); + color.alpha = 0.2f; + glColor4fv (&color.red); + 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 (); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void CTexture::DrawHeadlight () +{ + + float radius; + int i, x, y; + GLvector2 pos; + + //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)); + +} + +/*----------------------------------------------------------------------------- + + 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; + int max_size; + float radius; + GLvector2 pos; + bool use_framebuffer; + unsigned char* bits; + unsigned start; + int lapsed; + + start = GetTickCount (); + //Since we make textures by drawing into the viewport, we can't make them bigger + //than the current view. + _size = _desired_size; + max_size = RenderMaxTextureSize (); + while (_size > max_size) + _size /= 2; + glBindTexture(GL_TEXTURE_2D, _glid); + //Set up the texture + 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); + glDisable (GL_FOG); + 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_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, 1, 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: + DrawHeadlight (); + 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]); + 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_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: + DrawSky (); + 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) +{ + + textures_done = false; + build_time = 0; + for (CTexture* t = head; t; t = t->_next) + t->Clear (); + 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_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); + 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; + +} diff --git a/texture.h b/texture.h index 9cd1747..d55d974 100644 --- a/texture.h +++ b/texture.h @@ -1,47 +1,47 @@ -#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_LIGHT, - TEXTURE_SOFT_CIRCLE, - TEXTURE_SKY, - 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); - +#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_LIGHT, + TEXTURE_SOFT_CIRCLE, + TEXTURE_SKY, + 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); + diff --git a/visible.cpp b/visible.cpp index e4a7611..de9265b 100644 --- a/visible.cpp +++ b/visible.cpp @@ -1,132 +1,131 @@ -/*----------------------------------------------------------------------------- - - 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 -#include - -#include "glTypes.h" -#include "camera.h" -#include "macro.h" -#include "math.h" -#include "visible.h" -#include "world.h" -#include "win.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; - - //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 >= GRID_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 >= GRID_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; - } - } - - -} - +/*----------------------------------------------------------------------------- + + 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 +#include + +#include "glTypes.h" +#include "camera.h" +#include "macro.h" +#include "math.h" +#include "visible.h" +#include "world.h" +#include "win.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; + + //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 >= GRID_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 >= GRID_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; + } + } + + +} diff --git a/visible.h b/visible.h index 329c0a9..f96a1fb 100644 --- a/visible.h +++ b/visible.h @@ -1,11 +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); +#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); diff --git a/win.cpp b/win.cpp index 5482c17..8272a05 100644 --- a/win.cpp +++ b/win.cpp @@ -1,483 +1,483 @@ -/*----------------------------------------------------------------------------- - - Win.cpp - - 2006 Shamus Young - -------------------------------------------------------------------------------- - - Create the main window and make it go. - ------------------------------------------------------------------------------*/ - -#define MOUSE_MOVEMENT 0.5f - -#include -#include -#include -#include -#include -#include -#include - -#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, "winmm.lib") -#pragma comment (lib, "glu32.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; - -LONG WINAPI ScreenSaverProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -static 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); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -static 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); - -} - -/*----------------------------------------------------------------------------- - 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; - -} - - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void AppQuit () -{ - - quit = true; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void AppUpdate () -{ - - CameraUpdate (); - EntityUpdate (); - WorldUpdate (); - TextureUpdate (); - VisibleUpdate (); - CarUpdate (); - RenderUpdate (); - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void AppInit (void) -{ - - RandomInit (time (NULL)); - CameraInit (); - RenderInit (); - TextureInit (); - WorldInit (); - -} - - -/*----------------------------------------------------------------------------- - 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 - -BOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { return FALSE; } -BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; } - -#endif - -LONG WINAPI ScreenSaverProc(HWND hwnd_in,UINT message,WPARAM wparam,LPARAM lparam) -{ - - RECT r; - int key; - float delta_x, delta_y; - POINT p; - - // Handles screen saver messages - switch(message) - { - case WM_SIZE: - width = LOWORD(lparam); // width of client area - height = HIWORD(lparam); // height of client area - if (wparam == SIZE_MAXIMIZED) { - IniIntSet ("WindowMaximized", 1); - } else { - IniIntSet ("WindowWidth", width); - IniIntSet ("WindowHeight", height); - IniIntSet ("WindowMaximized", 0); - } - RenderResize (); - break; - case WM_KEYDOWN: - key = (int) wparam; - if (key == 'R') - WorldReset (); - 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 (!SCREENSAVER) { - //Dev mode keys - if (key == 'C') - CameraAutoToggle (); - if (key == 'B') - CameraNextBehavior (); - if (key == VK_F5) - CameraReset (); - if (key == VK_UP) - CameraMedial (1.0f); - if (key == VK_DOWN) - CameraMedial (-1.0f); - if (key == VK_LEFT) - CameraLateral (1.0f); - if (key == VK_RIGHT) - CameraLateral (-1.0f); - if (key == VK_PRIOR) - CameraVertical (1.0f); - if (key == VK_NEXT) - CameraVertical (-1.0f); - if (key == VK_F5) - CameraReset (); - return 0; - } else - break; - 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; - 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_CREATE: - hwnd = hwnd_in; - if (SCREENSAVER) - AppInit (); - SetTimer (hwnd, 1, 7, NULL); - return 0; - case WM_TIMER: - AppUpdate (); - return 0; - case WM_DESTROY: - PostQuitMessage(0); - return 0; - } -#if SCREENSAVER - return DefScreenSaverProc(hwnd_in,message,wparam,lparam); -#else - return DefWindowProc (hwnd_in,message,wparam,lparam); -#endif - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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)ScreenSaverProc; - 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; - -} \ No newline at end of file +/*----------------------------------------------------------------------------- + + Win.cpp + + 2006 Shamus Young + +------------------------------------------------------------------------------- + + Create the main window and make it go. + +-----------------------------------------------------------------------------*/ + +#define MOUSE_MOVEMENT 0.5f + +#include +#include +#include +#include +#include +#include +#include + +#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, "winmm.lib") +#pragma comment (lib, "glu32.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; + +LONG WINAPI ScreenSaverProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +static 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); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +static 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); + +} + +/*----------------------------------------------------------------------------- + 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; + +} + + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void AppQuit () +{ + + quit = true; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void AppUpdate () +{ + + CameraUpdate (); + EntityUpdate (); + WorldUpdate (); + TextureUpdate (); + VisibleUpdate (); + CarUpdate (); + RenderUpdate (); + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void AppInit (void) +{ + + RandomInit (time (NULL)); + CameraInit (); + RenderInit (); + TextureInit (); + WorldInit (); + +} + + +/*----------------------------------------------------------------------------- + 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 + +BOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { return FALSE; } +BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; } + +#endif + +LONG WINAPI ScreenSaverProc(HWND hwnd_in,UINT message,WPARAM wparam,LPARAM lparam) +{ + + RECT r; + int key; + float delta_x, delta_y; + POINT p; + + // Handles screen saver messages + switch(message) + { + case WM_SIZE: + width = LOWORD(lparam); // width of client area + height = HIWORD(lparam); // height of client area + if (wparam == SIZE_MAXIMIZED) { + IniIntSet ("WindowMaximized", 1); + } else { + IniIntSet ("WindowWidth", width); + IniIntSet ("WindowHeight", height); + IniIntSet ("WindowMaximized", 0); + } + RenderResize (); + break; + case WM_KEYDOWN: + key = (int) wparam; + if (key == 'R') + WorldReset (); + 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 (!SCREENSAVER) { + //Dev mode keys + if (key == 'C') + CameraAutoToggle (); + if (key == 'B') + CameraNextBehavior (); + if (key == VK_F5) + CameraReset (); + if (key == VK_UP) + CameraMedial (1.0f); + if (key == VK_DOWN) + CameraMedial (-1.0f); + if (key == VK_LEFT) + CameraLateral (1.0f); + if (key == VK_RIGHT) + CameraLateral (-1.0f); + if (key == VK_PRIOR) + CameraVertical (1.0f); + if (key == VK_NEXT) + CameraVertical (-1.0f); + if (key == VK_F5) + CameraReset (); + return 0; + } else + break; + 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; + 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_CREATE: + hwnd = hwnd_in; + if (SCREENSAVER) + AppInit (); + SetTimer (hwnd, 1, 7, NULL); + return 0; + case WM_TIMER: + AppUpdate (); + return 0; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } +#if SCREENSAVER + return DefScreenSaverProc(hwnd_in,message,wparam,lparam); +#else + return DefWindowProc (hwnd_in,message,wparam,lparam); +#endif + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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)ScreenSaverProc; + 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; + +} diff --git a/win.h b/win.h index e06f5c3..274723f 100644 --- a/win.h +++ b/win.h @@ -1,50 +1,50 @@ -//Versioning info -#define APP_TITLE "PixelCity" -#define APP "pixelcity" -#define VERSION_MAJOR 1 -#define VERSION_MINOR 0 -#define VERSION_REVISION 10 -//Best to disable screensaver mode when working on the program. -#define SCREENSAVER 0 -//Do we hide scene building behing a loading screen or show it? -#define LOADING_SCREEN 1 -//Controls the density of cars. -#define CARS 500 -//The "dead zone" along the edge of the world, with super-low detail. -#define WORLD_EDGE 200 -//How often to rebuild the city -#define RESET_INTERVAL (SCREENSAVER ? 120000 : 999999)//milliseconds -//How long the screen fade takes when transitioning to a new city -#define FADE_TIME (SCREENSAVER ? 1500 : 1) //milliseconds -//Debug ground texture that shows traffic lanes -#define SHOW_DEBUG_GROUND 0 -//Controls the ammount of space available for buildings. -//Other code is wrtten assuming this will be a power of two. -#define WORLD_SIZE 1024 -#define WORLD_HALF (WORLD_SIZE / 2) -//Bitflags used to track how world space is being used. -#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 -//Random SATURATED color -#define RANDOM_COLOR (glRgbaFromHsl ((float)RandomVal (255)/255,1.0f, 0.75f)) -//Used in orienting roads and cars -enum -{ - NORTH, - EAST, - SOUTH, - WEST -}; - -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); \ No newline at end of file +//Versioning info +#define APP_TITLE "PixelCity" +#define APP "pixelcity" +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 +#define VERSION_REVISION 10 +//Best to disable screensaver mode when working on the program. +#define SCREENSAVER 0 +//Do we hide scene building behing a loading screen or show it? +#define LOADING_SCREEN 1 +//Controls the density of cars. +#define CARS 500 +//The "dead zone" along the edge of the world, with super-low detail. +#define WORLD_EDGE 200 +//How often to rebuild the city +#define RESET_INTERVAL (SCREENSAVER ? 120000 : 999999)//milliseconds +//How long the screen fade takes when transitioning to a new city +#define FADE_TIME (SCREENSAVER ? 1500 : 1) //milliseconds +//Debug ground texture that shows traffic lanes +#define SHOW_DEBUG_GROUND 0 +//Controls the ammount of space available for buildings. +//Other code is wrtten assuming this will be a power of two. +#define WORLD_SIZE 1024 +#define WORLD_HALF (WORLD_SIZE / 2) +//Bitflags used to track how world space is being used. +#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 +//Random SATURATED color +#define RANDOM_COLOR (glRgbaFromHsl ((float)RandomVal (255)/255,1.0f, 0.75f)) +//Used in orienting roads and cars +enum +{ + NORTH, + EAST, + SOUTH, + WEST +}; + +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); diff --git a/world.cpp b/world.cpp index 309122d..4b37564 100644 --- a/world.cpp +++ b/world.cpp @@ -1,789 +1,789 @@ -/*----------------------------------------------------------------------------- - - 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)) - -#include -#include -#include -#include -#include -#include -#include - -#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 "win.h" -#include "world.h" - -using namespace std; - -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 int logo_index; -static unsigned start_time; -static int scene_begin; - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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); - } - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -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 > 800) { - if (COIN_FLIP) { - 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; - } - /* - //Rectangular plots are a good place for Blocky style buildsing to sprawl blockily. - if (p.width > p.depth * 2 || p.depth > p.width * 2 && area > 800) { - height = 20 + RandomVal (10); - blocky_count++; - skyscrapers++; - new CBuilding (BUILDING_BLOCKY, p.x, p.z, height, p.width, p.depth, seed, color); - return; - } - */ - //tower_count = -1; - //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; - - //Re-init Random to make the same city each time. Helpful when running tests. - RandomInit (6); - reset_needed = false; - broadway_done = false; - skyscrapers = 0; - logo_index = 0; - scene_begin = 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 (25) + 25) { - 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 (25) + 25) { - 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 () -{ - - if (!SHOW_DEBUG_GROUND) - return; - //Render a single texture over the city that shows traffic lanes - glDepthMask (false); - glDisable (GL_CULL_FACE); - glDisable (GL_BLEND); - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); - glBindTexture (GL_TEXTURE_2D, 0); - 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; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -int WorldSceneBegin () -{ - - return scene_begin; - -} - -/*----------------------------------------------------------------------------- - - How long since this current iteration of the city went on display, - ------------------------------------------------------------------------------*/ - -int WorldSceneElapsed () -{ - - int elapsed; - - if (!EntityReady () || !WorldSceneBegin ()) - elapsed = 1; - else - elapsed = GetTickCount () - (WorldSceneBegin ()); - elapsed = MAX (elapsed, 1); - return elapsed; - -} - -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void WorldUpdate (void) -{ - - unsigned fade_delta; - int now; - - 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); - scene_begin = GetTickCount (); - } - } 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; - } - if (fade_state == FADE_IDLE && WorldSceneElapsed () > 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; - -} +/*----------------------------------------------------------------------------- + + 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)) + +#include +#include +#include +#include +#include +#include +#include + +#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 "win.h" +#include "world.h" + +using namespace std; + +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 int logo_index; +static unsigned start_time; +static int scene_begin; + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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); + } + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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 > 800) { + if (COIN_FLIP) { + 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; + } + /* + //Rectangular plots are a good place for Blocky style buildsing to sprawl blockily. + if (p.width > p.depth * 2 || p.depth > p.width * 2 && area > 800) { + height = 20 + RandomVal (10); + blocky_count++; + skyscrapers++; + new CBuilding (BUILDING_BLOCKY, p.x, p.z, height, p.width, p.depth, seed, color); + return; + } + */ + //tower_count = -1; + //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; + + //Re-init Random to make the same city each time. Helpful when running tests. + RandomInit (6); + reset_needed = false; + broadway_done = false; + skyscrapers = 0; + logo_index = 0; + scene_begin = 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 (25) + 25) { + 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 (25) + 25) { + 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 () +{ + + if (!SHOW_DEBUG_GROUND) + return; + //Render a single texture over the city that shows traffic lanes + glDepthMask (false); + glDisable (GL_CULL_FACE); + glDisable (GL_BLEND); + glEnable (GL_TEXTURE_2D); + glColor3f (1,1,1); + glBindTexture (GL_TEXTURE_2D, 0); + 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; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +int WorldSceneBegin () +{ + + return scene_begin; + +} + +/*----------------------------------------------------------------------------- + + How long since this current iteration of the city went on display, + +-----------------------------------------------------------------------------*/ + +int WorldSceneElapsed () +{ + + int elapsed; + + if (!EntityReady () || !WorldSceneBegin ()) + elapsed = 1; + else + elapsed = GetTickCount () - (WorldSceneBegin ()); + elapsed = MAX (elapsed, 1); + return elapsed; + +} + +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +void WorldUpdate (void) +{ + + unsigned fade_delta; + int now; + + 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); + scene_begin = GetTickCount (); + } + } 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; + } + if (fade_state == FADE_IDLE && WorldSceneElapsed () > 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; + +} diff --git a/world.h b/world.h index 2bb52f4..4107974 100644 --- a/world.h +++ b/world.h @@ -1,16 +1,16 @@ - -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); -int WorldSceneBegin (); -int WorldSceneElapsed (); -void WorldTerm (void); -void WorldUpdate (void); - - + +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); +int WorldSceneBegin (); +int WorldSceneElapsed (); +void WorldTerm (void); +void WorldUpdate (void); + +