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 (); }
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); }