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 FigureRender () { static float nn; if (moveit) nn += 0.03f; fig2.RotateBone (BONE_SPINE1, glVector (0.0f, 0.0f, sin (nn * 3) * 25.0f)); fig2.RotateBone (BONE_RFINGERS1, glVector (0.0f, -abs (sin (nn * 1)) * -80.0f, 0.0f)); //fig2.RotateBone (BONE_RELBOW, glVector (abs (cos (nn * 1)) * 45.0f, 0.0f, 0.0f)); //fig2.RotateBone (BONE_LSHOULDER, glVector (0.0f, abs (sin (nn * 3)) * 80.0f, 0.0f)); //fig2.RotateBone (BONE_LELBOW, glVector (0.0f, 0.0f, abs (cos (nn * 2)) * 90.0f)); fig2.RotateBone (BONE_LWRIST, glVector (0.0f, abs (cos (nn * 2)) * 90.0f, 0.0f)); //fig2.RotateBone (BONE_RHIP, glVector (sin (nn) * 25.0f, 0.0f, 0.0f)); //fig2.RotateBone (BONE_RKNEE, glVector (-abs (cos (nn * 2) * 45.0f), 0.0f, 0.0f)); /* for (unsigned i = 0; i < anim._frame[frame].joint.size (); i++) { //if (anim._frame[frame].joint[i].id > BONE_PELVIS) fig.RotateBone (anim._frame[frame].joint[i].id, anim._frame[frame].joint[i].rotation); } */ if (stand) { //fig.Animate (&anim_stand, nn); //fig2.Animate (&anim_stand, nn); } else { //fig.Animate (&anim, nn); //fig2.Animate (&anim, nn); } frame++; //frame %= anim._frame.size (); //fig.Update (); //fig2.Update (); if (InputKeyPressed (SDLK_f)) { fig.PositionSet (AvatarPosition () + glVector (0.0f, -2.0f, 0.0f)); fig2.PositionSet (AvatarPosition () + glVector (0.0f, 2.0f, 0.0f)); } if (InputKeyPressed (SDLK_g)) moveit = !moveit; if (InputKeyPressed (SDLK_h)) stand = !stand; glBindTexture (GL_TEXTURE_2D, 0); //glDisable (GL_LIGHTING); //fig.Render (); //fig2.Render (); //glEnable (GL_LIGHTING); }
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); }
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 (); }
void CCar::Render () { GLvector pos; int angle; int turn; if (!m_ready) return; if (!Visible (m_drive_position)) return; if (m_front) glColor3f (1, 1, 0.8f); else glColor3f (1, 0.2f, 0); glBegin (GL_QUADS); angle = dangles[m_direction]; pos = m_drive_position;// angle = 360 - (int)MathAngle (m_position.x, m_position.z, pos.x, pos.z); angle %= 360; turn = (int)MathAngleDifference ((float)m_drive_angle, (float)angle); m_drive_angle += SIGN (turn); pos += glVector (0.5f, 0.0f, 0.5f); glTexCoord2f (0, 0); glVertex3f (pos.x + angles[angle].x, -CAR_SIZE, pos.z + angles[angle].y); glTexCoord2f (1, 0); glVertex3f (pos.x - angles[angle].x, -CAR_SIZE, pos.z - angles[angle].y); glTexCoord2f (1, 1); glVertex3f (pos.x - angles[angle].x, CAR_SIZE, pos.z - angles[angle].y); glTexCoord2f (0, 1); glVertex3f (pos.x + angles[angle].x, CAR_SIZE, pos.z + angles[angle].y); /* glVertex3f (m_position.x, m_position.y, m_position.z); glVertex3f (m_position.x, m_position.y, m_position.z + 1); glVertex3f (m_position.x + 1, m_position.y, m_position.z + 1); glVertex3f (m_position.x + 1, m_position.y, m_position.z); */ /* glTexCoord2f (0, 0); glVertex3f (m_position.x, m_position.y, m_position.z + 0.2f); glTexCoord2f (0, 2); glVertex3f (m_position.x, m_position.y, m_position.z + 1 - 0.2f); glTexCoord2f (1, 2); glVertex3f (m_position.x + 1, m_position.y, m_position.z + 1 - 0.2f); glTexCoord2f (1, 0); glVertex3f (m_position.x + 1, m_position.y, m_position.z + 0.2f); */ glEnd (); }
void FigureInit () { unsigned i; GLmesh* skin; for (i = 0; i < sizeof (bl) / sizeof (BoneList); i++) fig.PushBone (bl[i].id, bl[i].id_parent, bl[i].pos); skin = fig.Skin (); add_hull (&fig, glVector ( 0.1f, 0.05f, 0.5f), -0.1f, -0.4f, BONE_RKNEE); add_hull (&fig, glVector (-0.1f, 0.05f, 0.5f), -0.1f, -0.4f, BONE_LKNEE); add_hull (&fig, glVector ( 0.1f, 0.05f, 1.0f), -0.1f, -0.5f, BONE_RHIP); add_hull (&fig, glVector (-0.1f, 0.05f, 1.0f), -0.1f, -0.5f, BONE_LHIP); add_hull (&fig, glVector ( 0.2f, 0.05f, 1.5f), -0.1f, -0.1f, BONE_RSHOULDER); add_hull (&fig, glVector ( 0.5f, 0.05f, 1.5f), -0.1f, -0.1f, BONE_RELBOW); add_hull (&fig, glVector (-0.2f, 0.05f, 1.5f), -0.1f, -0.1f, BONE_LSHOULDER); add_hull (&fig, glVector (-0.5f, 0.05f, 1.5f), -0.1f, -0.1f, BONE_LELBOW); fig.Prepare (); anim.LoadBvh ("Anims//run.bvh"); anim_stand.LoadBvh ("Anims//stand.bvh"); fig2.LoadX ("models//male.x"); // fig2.BoneInflate (BONE_HEAD, 0.01f); /* { FILE* file; file = fopen ("stand.bvh", "w+b"); if (!file) return; for (i = 0; i < fig._bone.size (); i++) { fprintf (file, "Joint %s\n", CAnim::NameFromBone (fig._bone[i]._id)); fprintf (file, "CHANNELS 3\n"); } fprintf (file, "Motion\n"); fprintf (file, "Frames: 1\n"); fprintf (file, "Frame Time: 1.0\n"); for (i = 0; i < fig._bone.size (); i++) fprintf (file, "0.0 0.0 0.0 "); fprintf (file, "\n"); fclose (file); } */ }
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); }
void TextInit () { int x, y; int i; for (i = 0; i < max_CHARS; i++) { x = i % FONT_GRID; y = 255 - (i / FONT_GRID); glyph[i] = glVector ((float)x * GLYPH, (float)y * GLYPH); } }
void TerraformPrepare () { int x, y; Region r; GLcoord from_center; GLcoord offset; //Set some defaults offset.x = RandomVal () % 1024; offset.y = RandomVal () % 1024; for (x = 0; x < WORLD_GRID; x++) { for (y = 0; y < WORLD_GRID; y++) { memset (&r, 0, sizeof (Region)); sprintf (r.title, "NOTHING"); r.geo_bias = r.geo_detail = 0; r.mountain_height = 0; r.grid_pos.x = x; r.grid_pos.y = y; r.tree_threshold = 0.15f; from_center.x = abs (x - WORLD_GRID_CENTER); from_center.y = abs (y - WORLD_GRID_CENTER); //Geo scale is a number from -1 to 1. -1 is lowest ocean. 0 is sea level. //+1 is highest elevation on the island. This is used to guide other derived numbers. r.geo_scale = glVectorLength (glVector ((float)from_center.x, (float)from_center.y)); r.geo_scale /= (WORLD_GRID_CENTER - OCEAN_BUFFER); //Create a steep drop around the edge of the world if (r.geo_scale > 1.0f) r.geo_scale = 1.0f + (r.geo_scale - 1.0f) * 4.0f; r.geo_scale = 1.0f - r.geo_scale; r.geo_scale += (Entropy ((x + offset.x), (y + offset.y)) - 0.5f); r.geo_scale += (Entropy ((x + offset.x) * FREQUENCY, (y + offset.y) * FREQUENCY) - 0.2f); r.geo_scale = clamp (r.geo_scale, -1.0f, 1.0f); if (r.geo_scale > 0.0f) r.geo_water = 1.0f + r.geo_scale * 16.0f; r.color_atmosphere = glRgba (0.0f, 0.0f, 0.0f); r.geo_bias = 0.0f; r.geo_detail = 0.0f; r.color_map = glRgba (0.0f); r.climate = CLIMATE_INVALID; WorldRegionSet (x, y, r); } } }
static bool try_lake (int try_x, int try_y, int id) { Region r; int xx, yy; int size; float depth; float water_level; GLvector2 to_center; size = 4; //if (!is_free (try_x, try_y, size)) //return false; //Find the lowest water level in our lake water_level = 9999.9f; for (xx = -size; xx <= size; xx++) { for (yy = -size; yy <= size; yy++) { r = WorldRegionGet (xx + try_x, yy + try_y); if (r.climate != CLIMATE_INVALID && r.climate != CLIMATE_RIVER && r.climate != CLIMATE_RIVER_BANK) return false; if (r.moisture < 0.5f) return false; water_level = min (water_level, r.geo_water); } } for (xx = -size; xx <= size; xx++) { for (yy = -size; yy <= size; yy++) { to_center = glVector ((float)xx, (float)yy); depth = to_center.Length (); if (depth >= (float)size) continue; depth = (float)size - depth; r = WorldRegionGet (xx + try_x, yy + try_y); sprintf (r.title, "Lake%d", id); r.geo_water = water_level; r.geo_detail = 2.0f; r.geo_bias = -4.0f * depth; r.climate = CLIMATE_LAKE; r.flags_shape |= REGION_FLAG_NOBLEND; WorldRegionSet (xx + try_x, yy + try_y, r); } } return true; }
void add_hull (CFigure* f, GLvector p, float d, float h, BoneId id) { unsigned base; GLmesh* m; m = f->Skin (); base = m->Vertices (); m->PushVertex (glVector (p.x, p.y, p.z), UP, glVector (0.0f, 0.0f)); m->PushVertex (glVector (p.x, p.y + d, p.z), UP, glVector (0.0f, 0.0f)); m->PushVertex (glVector (p.x, p.y + d, p.z + h), UP, glVector (0.0f, 0.0f)); m->PushVertex (glVector (p.x, p.y, p.z + h), UP, glVector (0.0f, 0.0f)); m->PushQuad (base + 0, base + 1, base + 2, base + 3); m->PushQuad (base + 3, base + 2, base + 1, base + 0); f->PushWeight (id, base, 1.0f); f->PushWeight (id, base + 1, 1.0f); f->PushWeight (id, base + 2, 1.0f); f->PushWeight (id, base + 3, 1.0f); }
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; } }
GLvector2 GLvector2::operator+ (const float& c) { return glVector (x + c, y + c); }
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); }
GLvector2 GLvector2::operator+ (const GLvector2& c) { return glVector (x + c.x, y + c.y); }
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 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 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 (); }
GLvector2 GLvector2::operator* (const GLvector2& c) { return glVector (x * c.x, y * c.y); }
GLvector2 GLvector2::operator- (const GLvector2& c) { return glVector (x - c.x, y - c.y); }
GLvector2 GLvector2::operator/ (const GLvector2& c) { return glVector (x / c.x, y / c.y); }
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 = ADDON_NONE; 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::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); }
GLvector2 GLvector2::operator- (const float& c) { return glVector (x - c, y - c); }
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 (); }
GLvector2 GLvector2::operator* (const float& c) { return glVector (x * c, y * c); }
static void do_compile () { ent_list_t::iterator 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 = entity_list.begin(); i < entity_list.end(); ++i) { GLvector pos = (*i)->Center (); if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !(*i)->Alpha ()) { glBindTexture(GL_TEXTURE_2D, (*i)->Texture ()); (*i)->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 = entity_list.begin(); i < entity_list.end(); ++i) { GLvector pos = (*i)->Center (); if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !(*i)->Alpha ()) { (*i)->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 = entity_list.begin(); i < entity_list.end(); ++i) { GLvector pos = (*i)->Center (); if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !(*i)->Alpha ()) { (*i)->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 = entity_list.begin(); i < entity_list.end(); ++i) { GLvector pos = (*i)->Center (); if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && (*i)->Alpha ()) { glBindTexture(GL_TEXTURE_2D, (*i)->Texture ()); (*i)->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 = GetTimeInMillis (); } compile_count++; }
GLvector2 GLvector2::operator/ (const float& c) { return glVector (x / c, y / c); }
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; default: return 0.0f; } 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; }