00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00034 #include "../Include/Globals.h"
00035 #include "../Include/Terrain.h"
00036 #include "../Include/Utility.h"
00037 #include "../Include/Ui.h"
00038
00039
00040
00041
00042
00043
00044 CDetailTile::CDetailTile (unsigned int x, unsigned int z)
00045 {
00046 level = TERRAIN_SUBDIVISION_DETAIL_TILE;
00047 this->x = x;
00048 this->z = z;
00049
00050
00051 STileTextureInfo info;
00052 info.texid = 0;
00053 info.lls = info.llt = 0.0f;
00054 info.urs = info.urt = 1.0f;
00055 memcpy (&texinfo[TILE_DETAIL_LOW], &info, sizeof(STileTextureInfo));
00056 memcpy (&texinfo[TILE_DETAIL_MEDIUM], &info, sizeof(STileTextureInfo));
00057 memcpy (&texinfo[TILE_DETAIL_HIGH], &info, sizeof(STileTextureInfo));
00058 detail = TILE_DETAIL_MEDIUM;
00059
00060
00061 dtdb->GetCompositeTextureName (x, z, defaultTextureName);
00062
00063 elevLookup = NULL;
00064
00065
00066
00067
00068
00069
00070 int n = 64;
00071 globe_x = x / n;
00072 globe_z = z / n;
00073
00074
00075 double globe_sw_lon, globe_ne_lon, globe_sw_lat, globe_ne_lat;
00076 globe_tile_lon_bounds (globe_x, globe_sw_lon, globe_ne_lon);
00077 globe_tile_lat_bounds (globe_z, globe_sw_lat, globe_ne_lat);
00078 globe_sw_lon *= 3600;
00079 globe_sw_lat *= 3600;
00080 globe_ne_lon *= 3600;
00081 globe_ne_lat *= 3600;
00082
00083
00084 double dlat = (globe_ne_lat - globe_sw_lat) / n;
00085 double dlon = (globe_ne_lon - globe_sw_lon) / n;
00086
00087
00088 double sw_lat = globe_sw_lat + (dlat * (z % n));
00089 double sw_lon = globe_sw_lon + (dlon * (x % n));
00090 double ne_lat = sw_lat + dlat;
00091 double ne_lon = sw_lon + dlon;
00092 SetCorners (sw_lat, sw_lon, ne_lat, ne_lon);
00093
00094
00095 top = new ssgBranch;
00096 char name[64];
00097 sprintf (name, "DT %d,%d", x, z);
00098 top->setName (name);
00099 }
00100
00101
00102 CDetailTile::~CDetailTile (void)
00103 {
00104
00105 for (int i=0; i<3; i++) {
00106 STileTextureInfo &info = texinfo[i];
00107 if (info.texid != 0) {
00108 glDeleteTextures (1, &info.texid);
00109 }
00110 }
00111
00112
00113
00114
00115
00116 if (elevLookup != NULL) delete elevLookup;
00117 }
00118
00119
00120
00121
00122
00123 void CDetailTile::AssignDefaultTextureName (const char* name)
00124 {
00125 strcpy (defaultTextureName, name);
00126 }
00127
00128 void CDetailTile::AssignTexture (ETileDetail detail, STileTextureInfo &info)
00129 {
00130
00131 memcpy (&texinfo[detail], &info, sizeof(STileTextureInfo));
00132
00133
00134 if (IsCreated() && (this->detail == detail)) {
00135 switch (elevLookup->glType) {
00136 case GL_TRIANGLE_FAN:
00137 break;
00138
00139 case GL_TRIANGLE_STRIP:
00140 UpdateStripTexCoords (info);
00141 break;
00142 }
00143 }
00144 }
00145
00146
00147
00148
00149 void CDetailTile::LoadDefaultTexture (ETileDetail detail)
00150 {
00151 texid = 0;
00152
00153 if (!globals->settings->terrainReliefShaded) {
00154
00155
00156
00157 CRawImage *raw = dtdb->GetCompositeTexture (defaultTextureName, detail);
00158
00159 if (raw != NULL) {
00160
00161
00162 bool mipmap = false;
00163 switch (detail) {
00164 case TILE_DETAIL_LOW:
00165 mipmap = true;
00166 break;
00167
00168 case TILE_DETAIL_MEDIUM:
00169 mipmap = true;
00170 break;
00171
00172 case TILE_DETAIL_HIGH:
00173 mipmap = false;
00174 break;
00175
00176 default:
00177 gtfo ("Invalid texture detail level!");
00178 }
00179 texid = raw->GetTexture (mipmap);
00180
00181
00182 delete raw;
00183
00184
00185
00186
00187 float offset = 0.0;
00188 switch (detail) {
00189 case TILE_DETAIL_MEDIUM:
00190 offset = 16.0 / 256.0;
00191 break;
00192 case TILE_DETAIL_HIGH:
00193 offset = 8.0 / 256.0;
00194 break;
00195 }
00196
00197
00198 STileTextureInfo info;
00199 info.texid = texid;
00200 info.lls = info.llt = offset;
00201 info.urs = info.urt = 1.0f - offset;
00202 AssignTexture (detail, info);
00203 }
00204 }
00205 }
00206
00207
00208 void CDetailTile::SetDetail (ETileDetail detail)
00209 {
00210 this->detail = detail;
00211
00212
00213
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 }
00225
00226
00227
00228
00229
00230
00231 void CDetailTile::CreateFanGeometry (CElevationLookup *elev)
00232 {
00233
00234 SVector vsw, vnw, vse, vne;
00235 vnw = PosToFlatCartesian (nw, globe_x, globe_z);
00236 vne = PosToFlatCartesian (ne, globe_x, globe_z);
00237 vse = PosToFlatCartesian (se, globe_x, globe_z);
00238 vsw = PosToFlatCartesian (sw, globe_x, globe_z);
00239
00240
00241 float ewDistance = vne.x - vnw.x;
00242 float nsDistance = vsw.y - vnw.y;
00243
00244 ssgVertexArray *va = NULL;
00245 ssgColourArray *rgba = NULL;
00246 ssgTexCoordArray *ta = NULL;
00247
00248
00249 int nPoints = elev->u.fanData.nPoints;
00250 va = new ssgVertexArray(nPoints);
00251 for (int i=0; i<nPoints; i++) {
00252 SElevationLookupPoint *p = (SElevationLookupPoint *)(elev->points->getEntity(i));
00253 sgVec3 v;
00254 sgSetVec3 (v,
00255 vsw.x + (p->x * ewDistance),
00256 vsw.y + (p->z * nsDistance),
00257 p->elevation);
00258 va->add (v);
00259 }
00260
00261
00262 ssgSimpleState *state = new ssgSimpleState ();
00263 state->setShadeModel (GL_SMOOTH);
00264 state->disable (GL_LIGHTING);
00265 state->enable (GL_CULL_FACE);
00266 state->enable (GL_BLEND);
00267 state->disable (GL_ALPHA_TEST);
00268
00269
00270 if (globals->settings->terrainReliefShaded) {
00271
00272 state->disable (GL_TEXTURE_2D);
00273 state->enable (GL_COLOR_MATERIAL);
00274 state->setColourMaterial (GL_AMBIENT_AND_DIFFUSE);
00275 state->setMaterial (GL_EMISSION, 0, 0, 0, 1);
00276 state->setMaterial (GL_SPECULAR, 0, 0, 0, 1);
00277
00278 rgba = new ssgColourArray (nPoints);
00279 for (int i=0; i<nPoints; i++) {
00280 SElevationLookupPoint *p = (SElevationLookupPoint *)(elev->points->getEntity(i));
00281 float r, g, b;
00282 dtdb->GetReliefShadingRGB (p->elevation, r, g, b);
00283 sgVec4 c;
00284 sgSetVec4 (c, r, g, b, 1.0);
00285 rgba->add (c);
00286 }
00287 } else {
00288
00289 state->enable (GL_TEXTURE_2D);
00290 state->disable (GL_COLOR_MATERIAL);
00291
00292 if (globals->terrainmgr->debugLevel == DETAIL_TILES) {
00293
00294
00295 SSurface *surface = CreateSurface (64, 64);
00296 unsigned int bg = MakeRGB (128, 128, 128);
00297 unsigned int fg = MakeRGB (255, 255, 255);
00298 unsigned int dot = MakeRGB (255, 0, 0);
00299 surface->xScreen = surface->yScreen = 0;
00300 EraseSurfaceRGB (surface, bg);
00301 DrawLine (surface, 0, 0, 63, 0, fg);
00302 DrawLine (surface, 63, 0, 63, 63, fg);
00303 DrawLine (surface, 63, 63, 0, 63, fg);
00304 DrawLine (surface, 63, 0, 0, 0, fg);
00305 char label[16];
00306 sprintf (label, "%03d,%03d", globe_x, globe_z);
00307 DrawTextC (surface, &globals->fonts.ftasci10, 32, 1, fg, label);
00308 int qx = (x / 32) % 2;
00309 int qz = (z / 32) % 2;
00310 sprintf (label, "Q%1d%1d", qx, qz);
00311 DrawTextC (surface, &globals->fonts.ftasci10, 32, 13, fg, label);
00312 int sx = (x / 4) % 8;
00313 int sz = (z / 4) % 8;
00314 sprintf (label, "S%1d%1d", sx, sz);
00315 DrawTextC (surface, &globals->fonts.ftasci10, 32, 25, fg, label);
00316 int dx = x % 4;
00317 int dz = z % 4;
00318 sprintf (label, "D%02d", (dx * 4) + dz);
00319 DrawTextC (surface, &globals->fonts.ftasci10, 32, 37, fg, label);
00320 DrawDot (surface, 31, 31, dot);
00321 DrawDot (surface, 32, 31, dot);
00322 DrawDot (surface, 31, 32, dot);
00323 DrawDot (surface, 32, 32, dot);
00324 texid = TextureFromSurface (surface, true);
00325 FreeSurface (surface);
00326 state->setTexture (texid);
00327 } else {
00328
00330 state->setTexture ((GLuint) 0);
00331
00332 }
00333
00334
00335 ta = new ssgTexCoordArray (nPoints);
00336 for (int i=0; i<nPoints; i++) {
00337 SElevationLookupPoint *p = (SElevationLookupPoint *)(elev->points->getEntity(i));
00338 sgVec2 t;
00339 sgSetVec2 (t, p->x, p->z);
00340 ta->add (t);
00341 }
00342 }
00343
00344
00345 ssgVtxTable *vtab = new ssgVtxTable (GL_TRIANGLE_FAN, va, NULL, ta, rgba);
00346 vtab->setState (state);
00347 top->addKid (vtab);
00348 }
00349
00350
00351 void CDetailTile::UpdateFanTexCoords (STileTextureInfo &info)
00352 {
00353
00354 ssgVtxTable *vtab = (ssgVtxTable *)top->getKid(0);
00355 ssgSimpleState *state = (ssgSimpleState *)vtab->getState ();
00356 ssgTexCoordArray *ta = vtab->getTexCoords ();
00357
00358
00359 state->setTexture (info.texid);
00360
00361
00362 float sDelta = info.urs - info.lls;
00363 float tDelta = info.urt - info.llt;
00364
00365 int fanSize = elevLookup->u.fanData.nPoints;
00366 for (int i=0; i<fanSize; i++) {
00367 SElevationLookupPoint *p =
00368 (SElevationLookupPoint *)elevLookup->points->getEntity(i);
00369 sgVec2 t;
00370 sgSetVec2 (t, info.lls + (p->x * sDelta), info.llt + (p->z * tDelta));
00371 ta->set (t, i);
00372 }
00373 }
00374
00375
00376
00377
00378
00379
00380 void CDetailTile::CreateStripGeometry (CElevationLookup *elev)
00381 {
00382
00383 SVector vsw, vnw, vse, vne;
00384 vnw = PosToFlatCartesian (nw, globe_x, globe_z);
00385 vne = PosToFlatCartesian (ne, globe_x, globe_z);
00386 vse = PosToFlatCartesian (se, globe_x, globe_z);
00387 vsw = PosToFlatCartesian (sw, globe_x, globe_z);
00388
00389
00390 float ewDistance = vne.x - vnw.x;
00391 float nsDistance = vsw.y - vnw.y;
00392
00393 ssgVertexArray *va = NULL;
00394 ssgColourArray *rgba = NULL;
00395 ssgTexCoordArray *ta = NULL;
00396 ssgSimpleState *state = NULL;
00397
00398 SElevationLookupPoint *p = NULL;
00399
00400
00401 for (int i=0; i<elev->u.stripData.nStrips; i++) {
00402
00403 int nPoints = elev->u.stripData.stripSize;
00404
00405
00406 va = new ssgVertexArray(nPoints);
00407 p = (SElevationLookupPoint *)(elev->points->getEntity(i * nPoints));
00408 for (int j=0; j<nPoints; j++) {
00409 sgVec3 v;
00410 sgSetVec3 (v,
00411 vsw.x + (p->x * ewDistance),
00412 vsw.y + (p->z * nsDistance),
00413 p->elevation);
00414 va->add (v);
00415
00416
00417 p = (SElevationLookupPoint *)(elev->points->getNextEntity());
00418 }
00419
00420
00421 state = new ssgSimpleState ();
00422 state->setShadeModel (GL_SMOOTH);
00423 state->disable (GL_LIGHTING);
00424 state->enable (GL_CULL_FACE);
00425 state->enable (GL_BLEND);
00426 state->disable (GL_ALPHA_TEST);
00427
00428
00429 if (globals->settings->terrainReliefShaded) {
00430
00431 state->disable (GL_TEXTURE_2D);
00432 state->enable (GL_COLOR_MATERIAL);
00433 state->setColourMaterial (GL_AMBIENT_AND_DIFFUSE);
00434 state->setMaterial (GL_EMISSION, 0, 0, 0, 1);
00435 state->setMaterial (GL_SPECULAR, 0, 0, 0, 1);
00436
00437
00438 rgba = new ssgColourArray (nPoints);
00439 p = (SElevationLookupPoint *)(elev->points->getEntity(i * nPoints));
00440 for (int j=0; j<nPoints; j++) {
00441 float r, g, b;
00442 dtdb->GetReliefShadingRGB (p->elevation, r, g, b);
00443 sgVec4 c;
00444 sgSetVec4 (c, r, g, b, 1.0);
00445 rgba->add (c);
00446
00447
00448 p = (SElevationLookupPoint *)(elev->points->getNextEntity());
00449 }
00450 } else {
00451
00452 state->enable (GL_TEXTURE_2D);
00453 state->disable (GL_COLOR_MATERIAL);
00454
00455 if (globals->terrainmgr->debugLevel == DETAIL_TILES) {
00456
00457
00458 SSurface *surface = CreateSurface (64, 64);
00459 unsigned int bg = MakeRGB (128, 128, 128);
00460 unsigned int fg = MakeRGB (255, 255, 255);
00461 unsigned int dot = MakeRGB (255, 0, 0);
00462 surface->xScreen = surface->yScreen = 0;
00463 EraseSurfaceRGB (surface, bg);
00464 DrawLine (surface, 0, 0, 63, 0, fg);
00465 DrawLine (surface, 63, 0, 63, 63, fg);
00466 DrawLine (surface, 63, 63, 0, 63, fg);
00467 DrawLine (surface, 63, 0, 0, 0, fg);
00468 char label[16];
00469 sprintf (label, "%03d,%03d", globe_x, globe_z);
00470 DrawTextC (surface, &globals->fonts.ftasci10, 32, 1, fg, label);
00471 int qx = (x / 32) % 2;
00472 int qz = (z / 32) % 2;
00473 sprintf (label, "Q%1d%1d", qx, qz);
00474 DrawTextC (surface, &globals->fonts.ftasci10, 32, 13, fg, label);
00475 int sx = (x / 4) % 8;
00476 int sz = (z / 4) % 8;
00477 sprintf (label, "S%1d%1d", sx, sz);
00478 DrawTextC (surface, &globals->fonts.ftasci10, 32, 25, fg, label);
00479 int dx = x % 4;
00480 int dz = z % 4;
00481 sprintf (label, "D%02d", (dx * 4) + dz);
00482 DrawTextC (surface, &globals->fonts.ftasci10, 32, 37, fg, label);
00483 DrawDot (surface, 31, 31, dot);
00484 DrawDot (surface, 32, 31, dot);
00485 DrawDot (surface, 31, 32, dot);
00486 DrawDot (surface, 32, 32, dot);
00487 texid = TextureFromSurface (surface, true);
00488 FreeSurface (surface);
00489 state->setTexture (texid);
00490 } else {
00492 state->setTexture ((GLuint) 0);
00493 }
00494
00495
00496 dtdb->GetCompositeTextureName (x, z, defaultTextureName);
00497
00498
00499 ta = new ssgTexCoordArray (nPoints);
00500 p = (SElevationLookupPoint *)(elev->points->getEntity(i * nPoints));
00501 for (int j=0; j<nPoints; j++) {
00502 sgVec2 t;
00503 sgSetVec2 (t, p->x, p->z);
00504 ta->add (t);
00505
00506
00507 p = (SElevationLookupPoint *)(elev->points->getNextEntity());
00508 }
00509 }
00510
00511
00512 ssgVtxTable *vtab = new ssgVtxTable (GL_TRIANGLE_STRIP, va, NULL, ta, rgba);
00513 vtab->setState (state);
00514 top->addKid (vtab);
00515 }
00516 }
00517
00518 void CDetailTile::UpdateStripTexCoords (STileTextureInfo &info)
00519 {
00520 int n = elevLookup->u.stripData.nStrips;
00521 for (int i=0; i<n; i++) {
00522
00523 ssgVtxTable *vtab = (ssgVtxTable *)top->getKid(i);
00524 ssgSimpleState *state = (ssgSimpleState *)vtab->getState ();
00525 ssgTexCoordArray *ta = vtab->getTexCoords ();
00526
00527
00528 state->setTexture (info.texid);
00529
00530
00531 float sDelta = info.urs - info.lls;
00532 float tDelta = info.urt - info.llt;
00533
00534 int stripSize = elevLookup->u.stripData.stripSize;
00535 for (int j=0; j<stripSize; j++) {
00536 SElevationLookupPoint *p =
00537 (SElevationLookupPoint *)elevLookup->points->getEntity(i * stripSize + j);
00538 sgVec2 t;
00539 sgSetVec2 (t, info.lls + (p->x * sDelta), info.llt + (p->z * tDelta));
00540 ta->set (t, j);
00541 }
00542 }
00543 }
00544
00545 void CDetailTile::Create (void)
00546 {
00547
00548
00549
00550
00551 STileTextureInfo &info = texinfo[detail];
00552 if (info.texid == 0) {
00553 LoadDefaultTexture (detail);
00554 }
00555
00556
00557
00558 elevLookup = tedb->GetDetailTileElevations (x, z);
00559 if (elevLookup == NULL) {
00560 gtfo ("CDetailTile : Could not get elevations for DT %d,%d", x, z);
00561 }
00562
00563 switch (elevLookup->glType) {
00564 case GL_TRIANGLE_FAN:
00565 CreateFanGeometry (elevLookup);
00566 UpdateFanTexCoords (info);
00567 break;
00568
00569 case GL_TRIANGLE_STRIP:
00570 CreateStripGeometry (elevLookup);
00571 UpdateStripTexCoords (info);
00572 break;
00573 }
00574
00575 CTerrainTile::Create ();
00576 }
00577
00578 void CDetailTile::Destroy (void)
00579 {
00580 if (elevLookup != NULL) {
00581 delete elevLookup;
00582 elevLookup = NULL;
00583 }
00584
00585 CTerrainTile::Destroy ();
00586 }
00587
00588