diff --git a/Entity.cpp b/Entity.cpp index c1578a6..8b54427 100644 --- a/Entity.cpp +++ b/Entity.cpp @@ -52,6 +52,7 @@ static int polycount; static int compile_x; static int compile_y; static int compile_count; +static int compile_end; /*----------------------------------------------------------------------------- @@ -173,6 +174,7 @@ static void do_compile () compile_y++; if (compile_y == GRID_SIZE) compiled = true; + compile_end = GetTickCount (); } compile_count++; @@ -199,7 +201,6 @@ float EntityProgress () return (float)compile_count / (GRID_SIZE * GRID_SIZE); - } @@ -222,8 +223,11 @@ void EntityUpdate () } //We want to do several cells at once. Enough to get things done, but //not so many that the program is unresponsive. - stop_time = GetTickCount () + 100; - while (!compiled && GetTickCount () < stop_time) + 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 (); } @@ -238,12 +242,21 @@ 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)) diff --git a/Light.cpp b/Light.cpp index 5f03097..18ca3c5 100644 --- a/Light.cpp +++ b/Light.cpp @@ -24,6 +24,7 @@ #include "glTypes.h" #include "camera.h" +#include "entity.h" #include "light.h" #include "macro.h" #include "math.h" @@ -76,6 +77,8 @@ 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++) { diff --git a/Render.cpp b/Render.cpp index c674ced..e510b03 100644 --- a/Render.cpp +++ b/Render.cpp @@ -217,7 +217,7 @@ static void do_effects (int type) fade = WorldFade (); bloom_radius = 15; bloom_step = bloom_radius / 3; - if (!TextureReady () && fade == 0.0f) + if (!TextureReady ()) return; //Now change projection modes so we can render full-screen effects glDisable(GL_DEPTH_TEST); @@ -230,9 +230,9 @@ static void do_effects (int type) 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); glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_BLOOM)); @@ -326,26 +326,31 @@ static void do_effects (int type) break; } //Do the fade to / from darkness used to hide scene transitions - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDisable (GL_TEXTURE_2D); - glColor4f (0, 0, 0, fade); - glBegin (GL_QUADS); - glVertex2i (0, 0); - glVertex2i (0, render_height); - glVertex2i (render_width, render_height); - glVertex2i (render_width, 0); - glEnd (); - if (TextureReady () && !EntityReady () && fade != 0.0f) { - radius = render_width / 16; - do_progress ((float)render_width / 2, (float)render_height / 2, (float)radius, fade, EntityProgress ()); - RenderPrint (render_width / 2 - LOGO_PIXELS, render_height / 2 + LOGO_PIXELS, 0, glRgba (0.5f), "%1.2f%%", EntityProgress () * 100.0f); - RenderPrint (1, "%s v%d.%d.%03d", APP_TITLE, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); + 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); } @@ -711,6 +716,27 @@ float RenderFogDistance () } +/*----------------------------------------------------------------------------- + + 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); + +} + /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ @@ -721,32 +747,26 @@ 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); - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - if (TextureReady () && !EntityReady ()) { - do_effects (-1); + 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); - if (show_fog) { - glEnable (GL_FOG); - glFogf (GL_FOG_START, fog_distance - 100); - glFogf (GL_FOG_END, fog_distance); - color = glRgba (0.0f); - glFogfv (GL_FOG_COLOR, &color.red); - } else - glDisable (GL_FOG); glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); glEnable (GL_CULL_FACE); glCullFace (GL_BACK); glEnable (GL_BLEND); @@ -766,7 +786,15 @@ void RenderUpdate (void) 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); @@ -782,7 +810,19 @@ void RenderUpdate (void) glDisable (GL_BLEND); } EntityRender (); - LightRender (); + + 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); @@ -791,13 +831,11 @@ void RenderUpdate (void) } do_effects (effect); //Framerate tracker - if (show_fps) { + 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 (); - glDepthMask (true); SwapBuffers (hDC); } diff --git a/Render.h b/Render.h index dc7bd33..aa78163 100644 --- a/Render.h +++ b/Render.h @@ -5,6 +5,7 @@ void RenderFlatToggle (); float RenderFogDistance (); bool RenderFog (); void RenderFogToggle (); +void RenderFogFX (float scalar); void RenderFPSToggle (); void RenderInit (); void RenderLetterboxToggle (); diff --git a/Texture.cpp b/Texture.cpp index fa348ef..6224011 100644 --- a/Texture.cpp +++ b/Texture.cpp @@ -149,8 +149,6 @@ public: static CTexture* head; static bool textures_done; -static GLrgba horizon_color; -static GLrgba cloud_color; static bool prefix_used[PREFIX_COUNT]; static bool name_used[NAME_COUNT]; static bool suffix_used[SUFFIX_COUNT]; @@ -294,8 +292,6 @@ static void window (int x, int y, int size, int id, GLrgba color) margin = size / 3; half = size / 2; - //color = (color * 0.9f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT); - //glColor3fv (&color.red); switch (id) { case TEXTURE_BUILDING1: //filled, 1-pixel frame drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color); @@ -343,7 +339,6 @@ static void window (int x, int y, int size, int id, GLrgba color) static void do_bloom (CTexture* t) { - LIMIT_INTERVAL (10); glBindTexture(GL_TEXTURE_2D, 0); glViewport(0, 0, t->_size , t->_size); glCullFace (GL_BACK); @@ -459,6 +454,7 @@ void CTexture::Rebuild () int name_num, prefix_num, suffix_num; int max_size; float radius; + float grey; GLvector2 pos; GLrgba color; bool use_framebuffer; @@ -467,20 +463,21 @@ void CTexture::Rebuild () int lapsed; start = GetTickCount (); - glBindTexture(GL_TEXTURE_2D, _glid); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, _size, _size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); - if (_clamp) { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } //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. @@ -492,6 +489,7 @@ void CTexture::Rebuild () 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); @@ -581,7 +579,6 @@ void CTexture::Rebuild () glEnd (); break; case TEXTURE_LIGHT: - // glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); radius = ((float)_half) - 3; @@ -686,7 +683,7 @@ void CTexture::Rebuild () inv_scale = 1.0f - (scale); if (scale < 0.4f) - color = cloud_color; + color = WorldBloomColor () * 0.1f; else color = glRgba (0.0f); color.alpha = 1.0f; @@ -721,12 +718,16 @@ void CTexture::Rebuild () 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: + 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 (&horizon_color.red); + glColor3fv (&color.red); glVertex2i (0, _size - 2); glVertex2i (_size, _size - 2); glEnd (); @@ -796,16 +797,10 @@ unsigned TextureRandomBuilding (int index) void TextureReset (void) { - float hue, sat; - textures_done = false; build_time = 0; for (CTexture* t = head; t; t = t->_next) t->Clear (); - hue = 0.5f + (float)RandomVal (20) / 100.0f; - sat = 0.1f + (float)RandomVal (80) / 100.0f; - horizon_color = glRgbaFromHsl (hue, sat, 0.15f); - cloud_color = glRgbaFromHsl (hue, 0.15f, 0.1f); ZeroMemory (prefix_used, sizeof (prefix_used)); ZeroMemory (name_used, sizeof (name_used)); ZeroMemory (suffix_used, sizeof (suffix_used)); diff --git a/Win.cpp b/Win.cpp index 4638109..5482c17 100644 --- a/Win.cpp +++ b/Win.cpp @@ -193,50 +193,15 @@ void AppUpdate () { CameraUpdate (); + EntityUpdate (); WorldUpdate (); TextureUpdate (); VisibleUpdate (); CarUpdate (); - EntityUpdate (); RenderUpdate (); } -/*----------------------------------------------------------------------------- - ------------------------------------------------------------------------------*/ - -void CALLBACK Appx (HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) -{ - - static int ii; - //for (int i = 0; i < 1000;i++) - AppUpdate (); - ii++; - if (ii > 1) - ii++; - //PostQuitMessage (1); - //exit (1); - -} - -static void do_timer () -{ - - TIMECAPS tc; - int resolution; - - if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { - resolution = 0; - } - resolution = min(max(tc.wPeriodMin, 1), tc.wPeriodMax); - if (!timeSetEvent (1, resolution,(LPTIMECALLBACK)Appx, 123, TIME_PERIODIC | TIME_CALLBACK_FUNCTION )) - resolution = 0; - -} - - - /*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ @@ -445,7 +410,8 @@ LONG WINAPI ScreenSaverProc(HWND hwnd_in,UINT message,WPARAM wparam,LPARAM lpara break; case WM_CREATE: hwnd = hwnd_in; - AppInit (); + if (SCREENSAVER) + AppInit (); SetTimer (hwnd, 1, 7, NULL); return 0; case WM_TIMER: diff --git a/Win.h b/Win.h index 7fa7794..e06f5c3 100644 --- a/Win.h +++ b/Win.h @@ -3,15 +3,17 @@ #define APP "pixelcity" #define VERSION_MAJOR 1 #define VERSION_MINOR 0 -#define VERSION_REVISION 5 +#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 0 +#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 ? 120 : 999)//seconds +#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 diff --git a/World.cpp b/World.cpp index 0038a94..ded7feb 100644 --- a/World.cpp +++ b/World.cpp @@ -112,6 +112,7 @@ static int skyscrapers; static GLbbox hot_zone; static int logo_index; static unsigned start_time; +static int scene_begin; /*----------------------------------------------------------------------------- @@ -272,7 +273,7 @@ void do_building (plot p) return; //If the area is too big for one building, sub-divide it. - if (area > 1400) { + if (area > 800) { if (COIN_FLIP) { p.width /= 2; if (COIN_FLIP) @@ -295,7 +296,7 @@ void do_building (plot p) 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); @@ -304,6 +305,7 @@ void do_building (plot p) 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); @@ -313,7 +315,7 @@ void do_building (plot p) return; } */ - tower_count = -1; + //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; @@ -410,6 +412,7 @@ static void do_reset (void) broadway_done = false; skyscrapers = 0; logo_index = 0; + scene_begin = 0; tower_count = blocky_count = modern_count = 0; hot_zone = glBboxClear (); EntityClear (); @@ -681,6 +684,36 @@ float WorldFade (void) } +/*----------------------------------------------------------------------------- + +-----------------------------------------------------------------------------*/ + +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; + +} /*----------------------------------------------------------------------------- @@ -690,7 +723,7 @@ void WorldUpdate (void) { unsigned fade_delta; - unsigned now, elapsed; + int now; now = GetTickCount (); if (reset_needed) { @@ -713,6 +746,7 @@ void WorldUpdate (void) fade_state = FADE_IDLE; fade_current = 0.0f; start_time = time (NULL); + scene_begin = GetTickCount (); } } else { fade_current = (float)fade_delta / FADE_TIME; @@ -728,8 +762,7 @@ void WorldUpdate (void) fade_state = FADE_IN; fade_start = now; } - elapsed = time (NULL) - start_time; - if (fade_state == FADE_IDLE && elapsed > RESET_INTERVAL) + if (fade_state == FADE_IDLE && WorldSceneElapsed () > RESET_INTERVAL) WorldReset (); } diff --git a/World.h b/World.h index f79ab51..2bb52f4 100644 --- a/World.h +++ b/World.h @@ -8,6 +8,8 @@ void WorldInit (void); float WorldFade (void); void WorldRender (); void WorldReset (void); +int WorldSceneBegin (); +int WorldSceneElapsed (); void WorldTerm (void); void WorldUpdate (void);