/* city.c - Don Yang (uguu.org) Cell type interpretation: bits 0-1: base size bits 2-3: roof type bits 4-7: base height bits 8-9: color 05/30/03 */ #include"global.h" #include"city.h" #define BuildingHeight(type) (GLfloat)((((type) >> 4) & 15) * 0.07f + 1.4f) /* Colors */ static const GLfloat DAmbient[4][4] = { {0.2f, 0.2f, 0.2f, 1.0f}, {0.2f, 0.25f, 0.2f, 1.0f}, {0.2f, 0.2f, 0.25f, 1.0f}, {0.2f, 0.25f, 0.25f, 1.0f} }; static const GLfloat DDiffuse[4][4] = { {0.8f, 0.8f, 0.8f, 1.0f}, {0.7f, 1.0f, 0.7f, 1.0f}, {0.7f, 0.7f, 1.0f, 1.0f}, {0.7f, 1.0f, 1.0f, 1.0f} }; static const GLfloat DSpecular[4] = {0.2f, 0.2f, 0.2f, 1.0f}; static const GLfloat DEmission[4] = {0.1f, 0.1f, 0.1f, 1.0f}; static const GLfloat NAmbient[4] = {0.1f, 0.1f, 0.1f, 1.0f}; static const GLfloat NDiffuse[4] = {0.6f, 0.6f, 0.6f, 1.0f}; static const GLfloat NSpecular[4] = {0.2f, 0.2f, 0.2f, 1.0f}; static const GLfloat NEmission[4] = {0.0f, 0.1f, 0.2f, 1.0f}; /* Geometry data */ static const GLfloat RoofNormalX = 1.0f, RoofNormalY = 1.3f; static const GLfloat Edge[4] = {0.6f, 1.5f, 2.3f, 3.2f}; static const GLfloat OutlineScale[4] = {1.1f, 1.09f, 1.08f, 1.06f}; static GLfloat OutlineOffset[256]; /* Display lists */ static GLuint ObjRoofBase = 0; /* Local functions */ static void DrawWall(GLfloat h, GLfloat e); /********************************************************* DrawCityOutline */ void DrawCityOutline(unsigned int type) { GLfloat h, e; glTranslatef(0.0f, OutlineOffset[type & 255], 0.0f); glScalef(OutlineScale[type & 3], OutlineScale[type & 3], OutlineScale[type & 3]); /* Wall */ DrawWall(h = BuildingHeight(type), e = Edge[type & 3]); /* Floor */ glBegin(GL_QUADS); glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-e, 0.0f, e); glVertex3f(-e, 0.0f,-e); glVertex3f( e, 0.0f,-e); glVertex3f( e, 0.0f, e); glEnd(); /* Roof */ glTranslatef(0.0f, h, 0.0f); glCallList(ObjRoofBase + (type & 15)); } /* DrawCityOutline() */ /*********************************************************** DrawCityTileD */ void DrawCityTileD(unsigned int type) { GLfloat h; glMaterialfv(GL_FRONT, GL_AMBIENT, DAmbient[(type >> 8) & 3]); glMaterialfv(GL_FRONT, GL_DIFFUSE, DDiffuse[(type >> 8) & 3]); /* Wall */ DrawWall(h = BuildingHeight(type), Edge[type & 3]); /* Roof */ glTranslatef(0.0f, h, 0.0f); glCallList(ObjRoofBase + (type & 15)); } /* DrawCityTileD() */ /*********************************************************** DrawCityTileN */ void DrawCityTileN(unsigned int type) { GLfloat h; /* Wall */ DrawWall(h = BuildingHeight(type), Edge[type & 3]); /* Roof */ glTranslatef(0.0f, h, 0.0f); glCallList(ObjRoofBase + (type & 15)); } /* DrawCityTileN() */ /*********************************************************** InitCityTiles */ void InitCityTiles(void) { GLfloat h, s, e; unsigned int i; int size; ObjRoofBase = glGenLists(16); for(size = 0; size < 4; size++) { h = (GLfloat)((e = Edge[size]) * RoofNormalX / RoofNormalY); /* Roof type 0 */ glNewList(ObjRoofBase + size, GL_COMPILE); glBegin(GL_QUADS); glNormal3f(-RoofNormalX, RoofNormalY, 0.0f); glVertex3f( -e, 0.0f, -e); glVertex3f( -e, 0.0f, e); glVertex3f(0.0f, h, e); glVertex3f(0.0f, h, -e); glNormal3f(RoofNormalX, RoofNormalY, 0.0f); glVertex3f( e, 0.0f, e); glVertex3f( e, 0.0f, -e); glVertex3f(0.0f, h, -e); glVertex3f(0.0f, h, e); glEnd(); glBegin(GL_TRIANGLES); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f( -e, 0.0f, e); glVertex3f( e, 0.0f, e); glVertex3f(0.0f, h, e); glNormal3f(0.0f, 0.0f,-1.0f); glVertex3f( e, 0.0f, -e); glVertex3f( -e, 0.0f, -e); glVertex3f(0.0f, h, -e); glEnd(); glEndList(); /* Roof type 1 */ glNewList(ObjRoofBase + size + 4, GL_COMPILE); glBegin(GL_TRIANGLES); glNormal3f(-RoofNormalX, RoofNormalY, 0.0f); glVertex3f(0.0f, h, 0.0f); glVertex3f( -e, 0.0f, -e); glVertex3f( -e, 0.0f, e); glNormal3f(0.0f, RoofNormalY, RoofNormalX); glVertex3f(0.0f, h, 0.0f); glVertex3f( -e, 0.0f, e); glVertex3f( e, 0.0f, e); glNormal3f(RoofNormalX, RoofNormalY, 0.0f); glVertex3f(0.0f, h, 0.0f); glVertex3f( e, 0.0f, e); glVertex3f( e, 0.0f, -e); glNormal3f(0.0f, RoofNormalY, -RoofNormalX); glVertex3f(0.0f, h, 0.0f); glVertex3f( e, 0.0f, -e); glVertex3f( -e, 0.0f, -e); glEnd(); glEndList(); /* Roof type 2 (duplicate of type 0) */ glNewList(ObjRoofBase + size + 8, GL_COMPILE); glCallList(ObjRoofBase + size); glEndList(); /* Roof type 3 */ glNewList(ObjRoofBase + size + 12, GL_COMPILE); glBegin(GL_QUADS); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-e, 0.0f, e); glVertex3f( e, 0.0f, e); glVertex3f( e, 0.0f,-e); glVertex3f(-e, 0.0f,-e); glEnd(); glEndList(); } /* Compute outline offsets. This is to keep expanded outline geometry center-aligned with original. */ for(i = 0; i < 256; i++) { h = BuildingHeight(i); s = OutlineScale[i & 3]; e = Edge[i & 3]; OutlineOffset[i] = (i & 12) == 12 ? -0.5f * (h * (s - 1.0f)) : -0.5f * ((h + e * RoofNormalX / RoofNormalY) * (s - 1.0f)); } } /* InitCityTiles() */ /********************************************************** SetupCityTileD */ void SetupCityTileD(void) { glShadeModel(GL_FLAT); glMaterialfv(GL_FRONT, GL_SPECULAR, DSpecular); glMaterialfv(GL_FRONT, GL_EMISSION, DEmission); } /* SetupCityTileD() */ /********************************************************** SetupCityTileN */ void SetupCityTileN(void) { glShadeModel(GL_FLAT); glMaterialfv(GL_FRONT, GL_AMBIENT, NAmbient); glMaterialfv(GL_FRONT, GL_DIFFUSE, NDiffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, NSpecular); glMaterialfv(GL_FRONT, GL_EMISSION, NEmission); } /* SetupCityTileN() */ /********************************************************* UninitCityTiles */ void UninitCityTiles(void) { if( ObjRoofBase != 0 ) glDeleteLists(ObjRoofBase, 16); } /* UninitCityTiles() */ /*************************************************************** DrawWall */ static void DrawWall(GLfloat h, GLfloat e) { glBegin(GL_QUAD_STRIP); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-e, h,-e); glVertex3f(-e, 0.0f,-e); glVertex3f(-e, h, e); glVertex3f(-e, 0.0f, e); glNormal3f( 0.0f, 0.0f, 1.0f); glVertex3f( e, h, e); glVertex3f( e, 0.0f, e); glNormal3f( 1.0f, 0.0f, 0.0f); glVertex3f( e, h,-e); glVertex3f( e, 0.0f,-e); glNormal3f( 0.0f, 0.0f,-1.0f); glVertex3f(-e, h,-e); glVertex3f(-e, 0.0f,-e); glEnd(); #if 0 /* Same as above, obviously slower */ glBegin(GL_QUADS); glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-e, h, e); glVertex3f(-e, h,-e); glVertex3f(-e, 0.0f,-e); glVertex3f(-e, 0.0f, e); glNormal3f( 0.0f, 0.0f, 1.0f); glVertex3f( e, h, e); glVertex3f(-e, h, e); glVertex3f(-e, 0.0f, e); glVertex3f( e, 0.0f, e); glNormal3f( 1.0f, 0.0f, 0.0f); glVertex3f( e, h,-e); glVertex3f( e, h, e); glVertex3f( e, 0.0f, e); glVertex3f( e, 0.0f,-e); glNormal3f( 0.0f, 0.0f,-1.0f); glVertex3f(-e, h,-e); glVertex3f( e, h,-e); glVertex3f( e, 0.0f,-e); glVertex3f(-e, 0.0f,-e); glEnd(); #endif } /* DrawWall() */