00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00029 #include "../Include/Globals.h"
00030 #include "../Include/Terrain.h"
00031 #include "../Include/Utility.h"
00032 #include "../Include/Ui.h"
00033 #include "../Include/Qtr.h"
00034 #include "../Include/VTP.h"
00035 #include "../Include/Endian.h"
00036
00037
00038
00039
00040 CElevationLookup::CElevationLookup (void)
00041 {
00042 glType = 0;
00043 points = NULL;
00044 }
00045
00046 CElevationLookup::~CElevationLookup (void)
00047 {
00048 int i, n;
00049
00050 if (points != NULL) {
00051 n = points->getNumEntities();
00052 for (i=0; i<n; i++) {
00053 SElevationLookupPoint *p = (SElevationLookupPoint *)points->getEntity(i);
00054 delete p;
00055 }
00056 points->removeAllEntities();
00057 delete points;
00058 }
00059 }
00060
00061
00062
00063
00064
00065 CElevationBlock::CElevationBlock (int x, int z, int size)
00066 {
00067 this->x = x;
00068 this->z = z;
00069 this->size = size;
00070 type = ELEVATION_TYPE_UNKNOWN;
00071 }
00072
00073 CElevationBlock::~CElevationBlock (void)
00074 {
00075 }
00076
00077 int CElevationBlock::GetSize (void)
00078 {
00079 return size;
00080 }
00081
00082 bool CElevationBlock::DetailTileInBlock (int x, int z)
00083 {
00084 bool rc = false;
00085
00086
00087 int minX = this->x;
00088 int maxX = minX + size;
00089 int minZ = this->z;
00090 int maxZ = minZ + size;
00091
00092 rc = ((x >= minX) && (x < maxX) && (z >= minZ) && (z < maxZ));
00093
00094 return rc;
00095 }
00096
00097 EElevationType CElevationBlock::GetElevationType (void)
00098 {
00099 return type;
00100 }
00101
00102
00103
00104
00105
00106 CElevationBlockQTR::CElevationBlockQTR (int x, int z, const char* qtrFilename)
00107 : CElevationBlock (x, z, 512)
00108 {
00109 type = ELEVATION_TYPE_CENTER;
00110 qtrFile = new CQTRFile (qtrFilename);
00111 }
00112
00113 CElevationBlockQTR::~CElevationBlockQTR (void)
00114 {
00115 delete qtrFile;
00116 }
00117
00118
00119
00120
00121
00122 int CElevationBlockQTR::GetDetailTileResolution (void)
00123 {
00124 return 1;
00125 }
00126
00127 void CElevationBlockQTR::GetDetailTileElevations (int x, int z, float **data)
00128 {
00129
00130
00136 int gx = x % 512;
00137 int gz = 511 - (z % 512);
00138 if (qtrFile != NULL) {
00139 int depth = TERRAIN_SUBDIVISION_DETAIL_TILE - TERRAIN_SUBDIVISION_QTR;
00140 data[0][0] =
00141 qtrFile->Search (depth, 0, gx, gz);
00142 }
00143 }
00144
00145
00146
00147
00148 CElevationBlockBT::CElevationBlockBT (int x, int z, const char* btFilename)
00149 : CElevationBlock (x, z, 512)
00150 {
00151 type = ELEVATION_TYPE_CENTER;
00152
00154 }
00155
00156 CElevationBlockBT::~CElevationBlockBT (void)
00157 {
00158 }
00159
00160
00161
00162
00163
00164 int CElevationBlockBT::GetDetailTileResolution (void)
00165 {
00166 return 1;
00167 }
00168
00169 void CElevationBlockBT::GetDetailTileElevations (int x, int z, float **data)
00170 {
00171 data[0][0] = 0.0f;
00172 }
00173
00174
00175 void CElevationBlockBT::Load (const char* btFilename)
00176 {
00177
00178 PODFILE* pbt = popen (&globals->pfs, btFilename);
00179 if (!pbt) {
00180 globals->logWarning->Write ("ERROR reading %s\n", btFilename);
00181 return;
00182 }
00183
00184
00185 SBTHeader btHeader;
00186 pread (&btHeader, 1, SIZEOF_BT_HEADER, pbt);
00187
00188
00189 btHeader.columns = LittleEndian (btHeader.columns);
00190 btHeader.rows = LittleEndian (btHeader.rows);
00191 btHeader.size = LittleEndian (btHeader.size);
00192 btHeader.fp = LittleEndian (btHeader.fp);
00193 btHeader.space_units = LittleEndian (btHeader.space_units);
00194 btHeader.utm_zone = LittleEndian (btHeader.utm_zone);
00195 btHeader.datum = LittleEndian (btHeader.datum);
00196 btHeader.left = LittleEndian (btHeader.left);
00197 btHeader.right = LittleEndian (btHeader.right);
00198 btHeader.bottom = LittleEndian (btHeader.bottom);
00199 btHeader.top = LittleEndian (btHeader.top);
00200 btHeader.prj = LittleEndian (btHeader.prj);
00201 btHeader.scale = LittleEndian (btHeader.scale);
00202
00203
00204 if (btHeader.columns != btHeader.rows) {
00205 gtfo ("ERROR : BT is not square, cols=%d rows=%d\n",
00206 btHeader.columns, btHeader.rows);
00207 pclose (pbt);
00208 gtfo ();
00209 }
00210
00212 if (btHeader.columns != 513) {
00213 gtfo ("ERROR : BT must be 513 elements square (not %d)\n",
00214 btHeader.columns);
00215 pclose (pbt);
00216 gtfo ();
00217 }
00218
00219 int bt_size = btHeader.columns * btHeader.rows;
00220 int i;
00221
00222
00223 short *bt_data = new short[bt_size];
00224
00225 if (btHeader.fp) {
00226
00227 switch (btHeader.size) {
00228 case 2:
00229 {
00230
00231 float *fdata = new float[bt_size];
00232 pread (fdata, sizeof(float), bt_size, pbt);
00233 for (i=0; i<bt_size; i++) {
00234 bt_data[i] = (short)(fdata[i] * FEET_PER_METRE);
00235 }
00236 delete fdata;
00237 }
00238 break;
00239 case 4:
00240 {
00241
00242 double *ddata = new double[bt_size];
00243 pread (ddata, sizeof(double), bt_size, pbt);
00244 for (i=0; i<bt_size; i++) {
00245 bt_data[i] = (short)(ddata[i] * FEET_PER_METRE);
00246 }
00247 delete ddata;
00248 }
00249 break;
00250 }
00251 } else {
00252
00253 switch (btHeader.size) {
00254 case 2:
00255 {
00256
00257 short *sdata = new short[bt_size];
00258 pread (sdata, sizeof(short), bt_size, pbt);
00259 for (i=0; i<bt_size; i++) {
00260 bt_data[i] = (short)(sdata[i] * FEET_PER_METRE);
00261 }
00262 delete sdata;
00263 }
00264 break;
00265
00266 case 4:
00267 {
00268
00269 int *idata = new int[bt_size];
00270 pread (idata, sizeof(int), bt_size, pbt);
00271 for (i=0; i<bt_size; i++) {
00272 bt_data[i] = (short)(idata[i] * FEET_PER_METRE);
00273 }
00274 delete idata;
00275 }
00276 break;
00277 }
00278 }
00279
00280
00281 pclose (pbt);
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 delete bt_data;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 CElevationBlockGrid::CElevationBlockGrid (int x, int z,
00323 int size, int subdivision,
00324 float** data)
00325 : CElevationBlock (x, z, size)
00326 {
00327 type = ELEVATION_TYPE_CORNER;
00328
00329 this->subdivision = subdivision;
00330 this->data = data;
00331 }
00332
00333 CElevationBlockGrid::~CElevationBlockGrid (void)
00334 {
00335 }
00336
00337 int CElevationBlockGrid::GetDetailTileResolution (void)
00338 {
00339 return subdivision+1;
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 void CElevationBlockGrid::GetDetailTileElevations (int x, int z, float **data)
00356 {
00357
00358 int dx = x - this->x;
00359 int dz = z - this->z;
00360
00361
00362 int dimn = GetDetailTileResolution();
00363 for (int i=0; i<dimn; i++) {
00364 for (int j=0; j<dimn; j++) {
00365 data[i][j] = this->data[i + dz][j + dx];
00366 }
00367 }
00368 }
00369
00370
00371
00372
00373
00374 CElevationTRNSuperTile::CElevationTRNSuperTile (int x, int z, int subdivision)
00375 {
00376 this->x = x;
00377 this->z = z;
00378 this->subdivision = subdivision;
00379 elev = NULL;
00380 dtArray = new CElevationBlockGrid**[subdivision];
00381 for (int i=0; i<subdivision; i++) {
00382 dtArray[i] = new CElevationBlockGrid*[subdivision];
00383 for (int j=0; j<subdivision; j++) {
00384 dtArray[i][j] = NULL;
00385 }
00386 }
00387 }
00388
00389 CElevationTRNSuperTile::~CElevationTRNSuperTile (void)
00390 {
00391 if (elev != NULL) delete elev;
00392 for (int i=0; i<subdivision; i++) {
00393 for (int j=0; j<subdivision; j++) {
00394 delete dtArray[i][j];
00395 }
00396 delete[] dtArray[i];
00397 }
00398 delete[] dtArray;
00399 }
00400
00401
00402
00403
00404
00405 CElevationTRNQuarterGlobeTile::CElevationTRNQuarterGlobeTile (int x, int z, int subdivision)
00406 {
00407 this->x = x;
00408 this->z = z;
00409 this->subdivision = subdivision;
00410 stArray = new CElevationTRNSuperTile**[subdivision];
00411 for (int i=0; i<subdivision; i++) {
00412 stArray[i] = new CElevationTRNSuperTile*[subdivision];
00413 for (int j=0; j<subdivision; j++) {
00414 stArray[i][j] = NULL;
00415 }
00416 }
00417 }
00418
00419 CElevationTRNQuarterGlobeTile::~CElevationTRNQuarterGlobeTile (void)
00420 {
00421 for (int i=0; i<subdivision; i++) {
00422 for (int j=0; j<subdivision; j++) {
00423 delete stArray[i][j];
00424 }
00425 delete[] stArray[i];
00426 }
00427 delete[] stArray;
00428 }
00429
00430
00431
00432
00433
00434 CTileElevationDatabase::CTileElevationDatabase (void)
00435 {
00436 qtrList = new ulList (8);
00437 trnList = new ulList (64);
00438
00440 btList = NULL;
00441 }
00442
00443 CTileElevationDatabase::~CTileElevationDatabase (void)
00444 {
00445 int i, n;
00446
00447
00448 if (trnList != NULL) {
00449 n = trnList->getNumEntities();
00450 for (i=0; i<n; i++) {
00451 CElevationTRNQuarterGlobeTile *trn =
00452 (CElevationTRNQuarterGlobeTile *)trnList->getEntity(i);
00453 delete trn;
00454 }
00455 delete trnList;
00456 }
00457
00458
00459 if (btList != NULL) {
00460 n = btList->getNumEntities();
00461 for (i=0; i<n; i++) {
00462 CElevationBlock *block = (CElevationBlock *)btList->getEntity(i);
00463 delete block;
00464 }
00465 delete btList;
00466 }
00467
00468
00469 if (qtrList != NULL) {
00470 n = qtrList->getNumEntities();
00471 for (i=0; i<n; i++) {
00472 CElevationBlock *block = (CElevationBlock *)qtrList->getEntity(i);
00473 delete block;
00474 }
00475 delete qtrList;
00476 }
00477 }
00478
00479
00480
00481
00482 void CTileElevationDatabase::AddQTRBlock (CElevationBlockQTR *block)
00483 {
00484 qtrList->addEntity (block);
00485 }
00486
00487
00488
00489
00490 CElevationTRNQuarterGlobeTile *CTileElevationDatabase::AddTRN (int x, int z,
00491 int subdivision)
00492 {
00493 CElevationTRNQuarterGlobeTile *rc = new CElevationTRNQuarterGlobeTile (x, z, subdivision);
00494 trnList->addEntity (rc);
00495 return rc;
00496 }
00497
00498
00499
00500
00501 void CTileElevationDatabase::RemoveTRN (int x, int z)
00502 {
00503 CElevationTRNQuarterGlobeTile *trn = SearchTRN (x, z);
00504 if (trn != NULL) {
00505 delete trn;
00506 trnList->removeEntity (trn);
00507 }
00508 }
00509
00510 CElevationTRNQuarterGlobeTile *CTileElevationDatabase::SearchTRN (int x, int z)
00511 {
00512 CElevationTRNQuarterGlobeTile *rc = NULL;
00513
00514 int i, n;
00515 n = trnList->getNumEntities();
00516 for (i=0; (i<n) && (rc==NULL); i++) {
00517 CElevationTRNQuarterGlobeTile *trn =
00518 (CElevationTRNQuarterGlobeTile *)trnList->getEntity(i);
00519 if ((trn->x == x) && (trn->z == z)) {
00520 rc = trn;
00521 }
00522 }
00523
00524 return rc;
00525 }
00526
00527
00528
00529
00530 bool CTileElevationDatabase::RemoveQTRBlock (CElevationBlockQTR *block)
00531 {
00532 bool found = false;
00533 int i, n;
00534 n = qtrList->getNumEntities();
00535 for (i=0; i<n && !found; i++) {
00536 CElevationBlockQTR *b = (CElevationBlockQTR *)qtrList->getEntity(i);
00537 found = (block == b);
00538 }
00539
00540 if (found) {
00541 qtrList->removeEntity (i);
00542 }
00543
00544 return found;
00545 }
00546
00547
00548
00549
00550 int CTileElevationDatabase::DetailTileToQtrTile (int x, int z)
00551 {
00552 int qtr_x = x / 512;
00553 int qtr_z = 31 - (z / 512);
00554 return (qtr_z * 32) + qtr_x;
00555 }
00556
00557
00558
00559
00560 void CTileElevationDatabase::QtrBaseDetailTile (int qtr, int *x, int *z)
00561 {
00562 int qtr_x = qtr % 32;
00563 int qtr_z = 31 - (qtr / 32);
00564 *x = qtr_x * 512;
00565 *z = qtr_z * 512;
00566 }
00567
00568
00569
00570
00571 CElevationBlockBT *CTileElevationDatabase::LoadBT (int qtr)
00572 {
00573 CElevationBlockBT *rc = NULL;
00574
00575
00576 int x, z;
00577 QtrBaseDetailTile (qtr, &x, &z);
00578
00579
00580
00581 char btFilename[64];
00582 sprintf (btFilename, "BT\\FMQTR%03X.BT", qtr);
00583 if (pexists (&globals->pfs, btFilename)) {
00584 rc = new CElevationBlockBT (x, z, btFilename);
00585 }
00586
00587 return rc;
00588 }
00589
00590
00591
00592
00593 CElevationBlockQTR *CTileElevationDatabase::LoadQTR (int qtr)
00594 {
00595 CElevationBlockQTR *rc = NULL;
00596
00597
00598 int x, z;
00599 QtrBaseDetailTile (qtr, &x, &z);
00600
00601
00602
00603 char qtrFilename[64];
00604 sprintf (qtrFilename, "DATA\\%03X.QTR", qtr);
00605 if (pexists (&globals->pfs, qtrFilename)) {
00606 rc = new CElevationBlockQTR (x, z, qtrFilename);
00607 }
00608
00609 return rc;
00610 }
00611
00612
00613
00614
00615 CElevationBlock *CTileElevationDatabase::Search (int x, int z)
00616 {
00617 CElevationBlock *block = NULL;
00618 int i, n;
00619
00620
00621 int qx = x / 32;
00622 int qz = z / 32;
00623 CElevationTRNQuarterGlobeTile *trn = SearchTRN (qx, qz);
00624 if (trn != NULL) {
00625
00626 int sx = (x / 4) % 8;
00627 int sz = (z / 4) % 8;
00628 CElevationTRNSuperTile *stTrn = trn->stArray[sx][sz];
00629 if (stTrn != NULL) {
00630
00631 int dx = x % 4;
00632 int dz = z % 4;
00633 if (stTrn->dtArray[dx][dz] != NULL) {
00634
00635 block = stTrn->dtArray[dx][dz];
00636 } else {
00637
00638 block = stTrn->elev;
00639 }
00640 }
00641 }
00642
00644
00645
00646 if (block == NULL) {
00647 n = qtrList->getNumEntities();
00648 for (i=0; i<n; i++) {
00649 CElevationBlock *testBlock = (CElevationBlock *)qtrList->getEntity(i);
00650 if (testBlock->DetailTileInBlock(x, z)) {
00651
00652 block = testBlock;
00653 break;
00654 }
00655 }
00656 }
00657
00658
00659 if (block == NULL) {
00660 block = LoadQTR (DetailTileToQtrTile (x, z));
00661 qtrList->addEntity (block);
00662 }
00663
00664 return block;
00665 }
00666
00667
00668
00669
00670 EElevationType CTileElevationDatabase::GetElevationType (int x, int z)
00671 {
00672 EElevationType rc = ELEVATION_TYPE_UNKNOWN;
00673 CElevationBlock *block = Search (x, z);
00674 if (block != NULL) rc = block->GetElevationType();
00675 return rc;
00676 }
00677
00678 int CTileElevationDatabase::GetDetailTileResolution (int x, int z)
00679 {
00680 int rc = 0;
00681
00682 CElevationBlock *block = Search (x, z);
00683 if (block != NULL) {
00684 rc = block->GetDetailTileResolution();
00685 }
00686
00687 return rc;
00688 }
00689
00690 static void AllocateElevationArray (int dimn, float ***array)
00691 {
00692 *array = new float*[dimn];
00693 for (int i=0; i<dimn; i++) {
00694 (*array)[i] = new float[dimn];
00695 }
00696 }
00697
00698 static void FreeElevationArray (int dimn, float **array)
00699 {
00700 for (int i=0; i<dimn; i++) {
00701 delete[] array[i];
00702 }
00703 delete[] array;
00704 }
00705
00706 static float max3 (float f1, float f2, float f3)
00707 {
00708 float rc = f1;
00709
00710 if (f2 > rc) rc = f2;
00711 if (f3 > rc) rc = f3;
00712
00713 return rc;
00714 }
00715
00716
00717
00718
00719
00720
00721
00722 float InterpolatedData (float x, float z, int res, float **data)
00723 {
00724 float rc = 0.0f;
00725
00726 float fres = (float)(res-1);
00727
00728
00729 int ix0, ix1, iz0, iz1;
00730
00731 if (z == 0.0f) {
00732 iz0 = iz1 = 0;
00733 } else if (z == 1.0f) {
00734 iz0 = iz1 = res-1;
00735 } else {
00736 iz0 = (int)(floorf(fres * z));
00737 iz1 = iz0 + 1;
00738 }
00739
00740 if (x == 0.0f) {
00741 ix0 = ix1 = 0;
00742 } else if (x == 1.0f) {
00743 ix0 = ix1 = res-1;
00744 } else {
00745 ix0 = (int)(floorf(fres * x));
00746 ix1 = ix0 + 1;
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 float h1 = data[iz0][ix0];
00759 float h2 = data[iz0][ix1];
00760 float h3 = data[iz1][ix0];
00761 float h4 = data[iz1][ix1];
00762
00763
00764 float delta = 1.0f / fres;
00765 x -= ix0 * delta;
00766 z -= iz0 * delta;
00767
00768
00769 rc = h1 + ((h2 - h1) * x) + ((h3 - h1) * z) + ((h1 - h2 - h3 + h4) * x * z);
00770
00771 return rc;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 CElevationLookup *CTileElevationDatabase::GetDetailTileElevations (int x, int z)
00783 {
00784 int i, j;
00785
00786 CElevationLookup *rc = NULL;
00787
00788
00789 float **nwTile = NULL;
00790 float **wTile = NULL;
00791 float **swTile = NULL;
00792 float **sTile = NULL;
00793 float **seTile = NULL;
00794 float **eTile = NULL;
00795 float **neTile = NULL;
00796 float **nTile = NULL;
00797
00798 int nwResolution = 0;
00799 int wResolution = 0;
00800 int swResolution = 0;
00801 int sResolution = 0;
00802 int seResolution = 0;
00803 int eResolution = 0;
00804 int neResolution = 0;
00805 int nResolution = 0;
00806
00807 CElevationBlock *nwBlock = NULL;
00808 CElevationBlock *wBlock = NULL;
00809 CElevationBlock *swBlock = NULL;
00810 CElevationBlock *sBlock = NULL;
00811 CElevationBlock *seBlock = NULL;
00812 CElevationBlock *eBlock = NULL;
00813 CElevationBlock *neBlock = NULL;
00814 CElevationBlock *nBlock = NULL;
00815
00816
00817 CElevationBlock *thisBlock = Search (x, z);
00818 float **thisTile = NULL;
00819 int thisResolution;
00820
00821
00822 if (thisBlock != NULL) {
00823
00824 thisResolution = thisBlock->GetDetailTileResolution();
00825 EElevationType type = thisBlock->GetElevationType();
00826 switch (type) {
00827 case ELEVATION_TYPE_CENTER:
00828 {
00829
00830
00831
00832
00833
00834 bool nwDone = false, swDone = false, seDone = false, neDone = false;
00835 int nWest = 0, nSouth = 0, nEast = 0, nNorth = 0;
00836 float westEdge[7], southEdge[7], eastEdge[7], northEdge[7];
00837 float centerElev = 0, nwElev = 0, swElev = 0, seElev = 0, neElev = 0;
00838
00839
00840 AllocateElevationArray (thisResolution, &thisTile);
00841 thisBlock->GetDetailTileElevations (x, z, thisTile);
00842 centerElev = thisTile[0][0];
00843 FreeElevationArray (thisResolution, thisTile);
00844
00845
00846 wBlock = Search (x-1, z);
00847 wResolution = wBlock->GetDetailTileResolution();
00848 if (wBlock->GetElevationType () == ELEVATION_TYPE_CORNER) {
00849
00850 AllocateElevationArray (wBlock->GetDetailTileResolution(), &wTile);
00851 wBlock->GetDetailTileElevations (x-1, z, wTile);
00852
00853
00854 nwElev = wTile[wResolution-1][wResolution-1];
00855 nwDone = true;
00856
00857 swElev = wTile[0][wResolution-1];
00858 swDone = true;
00859
00860
00861 if (wResolution > 2) {
00862 nWest = wResolution - 2;
00863
00864
00865 for (int i=0; i<nWest; i++) {
00866 westEdge[i] = wTile[wResolution-2-i][wResolution-1];
00867 }
00868 }
00869 }
00870
00871
00872 eBlock = Search (x+1, z);
00873 eResolution = eBlock->GetDetailTileResolution();
00874 if (eBlock->GetElevationType () == ELEVATION_TYPE_CORNER) {
00875
00877 AllocateElevationArray (eResolution, &eTile);
00878 eBlock->GetDetailTileElevations (x+1, z, eTile);
00879
00880
00881 neElev = eTile[eResolution-1][0];
00882 neDone = true;
00883
00884 seElev = eTile[0][0];
00885 seDone = true;
00886
00887
00888 if (eResolution > 2) {
00889 nEast = eResolution - 2;
00890
00891
00892 for (int i=0; i<nEast; i++) {
00893 eastEdge[i] = eTile[i+1][0];
00894 }
00895 }
00896 }
00897
00898
00899 nBlock = Search (x, z+1);
00900 nResolution = nBlock->GetDetailTileResolution();
00901 if (nBlock->GetElevationType () == ELEVATION_TYPE_CORNER) {
00902
00904 AllocateElevationArray (nBlock->GetDetailTileResolution(), &nTile);
00905 nBlock->GetDetailTileElevations (x, z+1, nTile);
00906
00907
00908 neElev = nTile[0][nResolution-1];
00909 neDone = true;
00910
00911 nwElev = nTile[0][0];
00912 nwDone = true;
00913
00914
00915 if (nResolution > 2) {
00916 nNorth = nResolution - 2;
00917
00918
00919 for (int i=0; i<nNorth; i++) {
00920 northEdge[i] = nTile[0][nResolution-2-i];
00921 }
00922 }
00923 }
00924
00925
00926 sBlock = Search (x, z-1);
00927 sResolution = sBlock->GetDetailTileResolution();
00928 if (sBlock->GetElevationType () == ELEVATION_TYPE_CORNER) {
00929
00931 AllocateElevationArray (sResolution, &sTile);
00932 sBlock->GetDetailTileElevations (x, z-1, sTile);
00933
00934
00935 seElev = sTile[sResolution-1][sResolution-1];
00936 seDone = true;
00937
00938 swElev = sTile[sResolution-1][0];
00939 swDone = true;
00940
00941
00942 if (sResolution > 2) {
00943 nSouth = sResolution - 2;
00944
00945
00946 for (int i=0; i<nSouth; i++) {
00947 southEdge[i] = sTile[sResolution-1][i+1];
00948 }
00949 }
00950 }
00951
00952
00953 if (!nwDone) {
00954
00955 if (nwBlock == NULL) {
00956 nwBlock = Search (x-1, z+1);
00957 nwResolution = nwBlock->GetDetailTileResolution();
00958 }
00959 switch (nwBlock->GetElevationType()) {
00960 case ELEVATION_TYPE_CORNER:
00961 {
00962
00963 AllocateElevationArray (nwResolution, &nwTile);
00964 nwBlock->GetDetailTileElevations (x-1, z+1, nwTile);
00965
00966
00967 nwElev = nwTile[0][nwResolution-1];
00968 nwDone = true;
00969 }
00970 break;
00971
00972 case ELEVATION_TYPE_CENTER:
00973
00974 if (nTile == NULL) {
00975 nBlock = Search (x, z+1);
00976 nResolution = nBlock->GetDetailTileResolution();
00977 AllocateElevationArray (nResolution, &nTile);
00978 nBlock->GetDetailTileElevations (x, z+1, nTile);
00979 }
00980 if (nwTile == NULL) {
00981 nwBlock = Search (x-1, z+1);
00982 nwResolution = nwBlock->GetDetailTileResolution();
00983 AllocateElevationArray (nwResolution, &nwTile);
00984 nwBlock->GetDetailTileElevations (x-1, z+1, nwTile);
00985 }
00986 if (wTile == NULL) {
00987 wBlock = Search (x-1, z);
00988 wResolution = wBlock->GetDetailTileResolution();
00989 AllocateElevationArray (wResolution, &wTile);
00990 wBlock->GetDetailTileElevations (x-1, z, wTile);
00991 }
00992 nwElev = (centerElev + nTile[0][0] + nwTile[0][0] + wTile[0][0]) / 4.0f;
00993 nwDone = true;
00994 break;
00995
00996 default:
00997 globals->logWarning->Write ("No elevation data for NW corner of %d,%d", x, z);
00998 nwElev = centerElev;
00999 }
01000 }
01001
01002
01003 if (!swDone) {
01004
01005 if (swBlock == NULL) {
01006 swBlock = Search (x-1, z-1);
01007 }
01008 switch (swBlock->GetElevationType()) {
01009 case ELEVATION_TYPE_CORNER:
01010 {
01011
01012 swResolution = swBlock->GetDetailTileResolution();
01013 AllocateElevationArray (swResolution, &swTile);
01014 swBlock->GetDetailTileElevations (x-1, z-1, swTile);
01015
01016
01017 swElev = swTile[swResolution-1][swResolution-1];
01018 swDone = true;
01019 }
01020 break;
01021
01022 case ELEVATION_TYPE_CENTER:
01023
01024 if (wTile == NULL) {
01025 wBlock = Search (x-1, z);
01026 wResolution = wBlock->GetDetailTileResolution();
01027 AllocateElevationArray (wResolution, &wTile);
01028 wBlock->GetDetailTileElevations (x-1, z, wTile);
01029 }
01030 if (swTile == NULL) {
01031 swBlock = Search (x-1, z-1);
01032 swResolution = swBlock->GetDetailTileResolution();
01033 AllocateElevationArray (swResolution, &swTile);
01034 swBlock->GetDetailTileElevations (x-1, z-1, swTile);
01035 }
01036 if (sTile == NULL) {
01037 sBlock = Search (x, z-1);
01038 sResolution = sBlock->GetDetailTileResolution();
01039 AllocateElevationArray (sResolution, &sTile);
01040 sBlock->GetDetailTileElevations (x, z-1, sTile);
01041 }
01042 swElev = (centerElev + wTile[0][0] + swTile[0][0] + sTile[0][0]) / 4.0f;
01043 swDone = true;
01044 break;
01045
01046 default:
01047 globals->logWarning->Write ("No elevation data for SW corner of %d,%d", x, z);
01048 swElev = centerElev;
01049 }
01050 }
01051
01052
01053 if (!seDone) {
01054
01055 if (seBlock == NULL) {
01056 seBlock = Search (x+1, z-1);
01057 }
01058 switch (seBlock->GetElevationType()) {
01059 case ELEVATION_TYPE_CORNER:
01060 {
01061
01062 seResolution = seBlock->GetDetailTileResolution();
01063 AllocateElevationArray (seResolution, &seTile);
01064 seBlock->GetDetailTileElevations (x+1, z-1, seTile);
01065
01066
01067 seElev = seTile[seResolution-1][0];
01068 seDone = true;
01069 }
01070 break;
01071
01072 case ELEVATION_TYPE_CENTER:
01073
01074 if (sTile == NULL) {
01075 sBlock = Search (x, z-1);
01076 sResolution = sBlock->GetDetailTileResolution();
01077 AllocateElevationArray (sResolution, &sTile);
01078 sBlock->GetDetailTileElevations (x, z-1, sTile);
01079 }
01080 if (seTile == NULL) {
01081 seBlock = Search (x+1, z-1);
01082 seResolution = seBlock->GetDetailTileResolution();
01083 AllocateElevationArray (seResolution, &seTile);
01084 seBlock->GetDetailTileElevations (x+1, z-1, seTile);
01085 }
01086 if (eTile == NULL) {
01087 eBlock = Search (x+1, z);
01088 eResolution = eBlock->GetDetailTileResolution();
01089 AllocateElevationArray (eResolution, &eTile);
01090 eBlock->GetDetailTileElevations (x+1, z, eTile);
01091 }
01092 seElev = (centerElev + sTile[0][0] + seTile[0][0] + eTile[0][0]) / 4.0f;
01093 seDone = true;
01094 break;
01095
01096 default:
01097 globals->logWarning->Write ("No elevation data for SE corner of %d,%d", x, z);
01098 seElev = centerElev;
01099 }
01100 }
01101
01102
01103 if (!neDone) {
01104 if (neBlock == NULL) {
01105 neBlock = Search (x+1, z+1);
01106 }
01107 switch (neBlock->GetElevationType()) {
01108 case ELEVATION_TYPE_CORNER:
01109 {
01110
01111 neResolution = neBlock->GetDetailTileResolution();
01112 AllocateElevationArray (neResolution, &neTile);
01113 neBlock->GetDetailTileElevations (x+1, z+1, neTile);
01114
01115
01116 neElev = neTile[0][0];
01117 neDone = true;
01118 }
01119 break;
01120
01121 case ELEVATION_TYPE_CENTER:
01122
01123 if (eTile == NULL) {
01124 eBlock = Search (x+1, z);
01125 eResolution = eBlock->GetDetailTileResolution();
01126 AllocateElevationArray (eResolution, &eTile);
01127 eBlock->GetDetailTileElevations (x+1, z, eTile);
01128 }
01129 if (neTile == NULL) {
01130 neBlock = Search (x+1, z+1);
01131 neResolution = neBlock->GetDetailTileResolution();
01132 AllocateElevationArray (neResolution, &neTile);
01133 neBlock->GetDetailTileElevations (x+1, z+1, neTile);
01134 }
01135 if (nTile == NULL) {
01136 nBlock = Search (x, z+1);
01137 nResolution = nBlock->GetDetailTileResolution();
01138 AllocateElevationArray (nResolution, &nTile);
01139 nBlock->GetDetailTileElevations (x, z+1, nTile);
01140 }
01141 neElev = (centerElev + eTile[0][0] + neTile[0][0] + nTile[0][0]) / 4.0f;
01142 neDone = true;
01143 break;
01144
01145 default:
01146 globals->logWarning->Write ("No elevation data for NE corner of %d,%d", x, z);
01147 neElev = centerElev;
01148 }
01149 }
01150
01151
01152 if (nwTile != NULL) FreeElevationArray (nwResolution, nwTile);
01153 if (wTile != NULL) FreeElevationArray (wResolution, wTile);
01154 if (swTile != NULL) FreeElevationArray (swResolution, swTile);
01155 if (sTile != NULL) FreeElevationArray (sResolution, sTile);
01156 if (seTile != NULL) FreeElevationArray (seResolution, seTile);
01157 if (eTile != NULL) FreeElevationArray (eResolution, eTile);
01158 if (neTile != NULL) FreeElevationArray (neResolution, neTile);
01159 if (nTile != NULL) FreeElevationArray (nResolution, nTile);
01160
01161
01162 int i;
01163 float dx, dz;
01164 int nPoints = 6 + nWest + nSouth + nEast + nNorth;
01165 rc = new CElevationLookup;
01166 rc->glType = GL_TRIANGLE_FAN;
01167 rc->u.fanData.nPoints = nPoints;
01168 rc->points = new ulList(nPoints);
01169
01170 SElevationLookupPoint *p;
01171
01172
01173 p = new SElevationLookupPoint;
01174 p->x = 0.5f;
01175 p->z = 0.5f;
01176 p->elevation = centerElev;
01177 rc->points->addEntity(p);
01178
01179
01180 p = new SElevationLookupPoint;
01181 p->x = 0.0f;
01182 p->z = 0.0f;
01183 p->elevation = nwElev;
01184 rc->points->addEntity(p);
01185
01186
01187 dz = 1.0f / (nWest + 1);
01188 for (i=0; i<nWest; i++) {
01189 p = new SElevationLookupPoint;
01190 p->x = 0.0f;
01191 p->z = (float)(i+1) * dz;
01192 p->elevation = westEdge[i];
01193 rc->points->addEntity(p);
01194 }
01195
01196
01197 p = new SElevationLookupPoint;
01198 p->x = 0.0f;
01199 p->z = 1.0f;
01200 p->elevation = swElev;
01201 rc->points->addEntity(p);
01202
01203
01204 dx = 1.0f / (nSouth + 1);
01205 for (i=0; i<nSouth; i++) {
01206 p = new SElevationLookupPoint;
01207 p->x = (float)(i+1) * dx;
01208 p->z = 1.0f;
01209 p->elevation = southEdge[i];
01210 rc->points->addEntity(p);
01211 }
01212
01213
01214 p = new SElevationLookupPoint;
01215 p->x = 1.0f;
01216 p->z = 1.0f;
01217 p->elevation = seElev;
01218 rc->points->addEntity(p);
01219
01220
01221 dz = 1.0f / (nEast + 1);
01222 for (i=0; i<nEast; i++) {
01223 p = new SElevationLookupPoint;
01224 p->x = 1.0f;
01225 p->z = 1.0f - ((float)(i+1) * dz);
01226 p->elevation = eastEdge[i];
01227 rc->points->addEntity(p);
01228 }
01229
01230
01231 p = new SElevationLookupPoint;
01232 p->x = 1.0f;
01233 p->z = 0.0f;
01234 p->elevation = neElev;
01235 rc->points->addEntity(p);
01236
01237
01238 dx = 1.0f / (nNorth + 1);
01239 for (i=0; i<nNorth; i++) {
01240 p = new SElevationLookupPoint;
01241 p->x = 1.0f - ((float)(i+1) * dx);
01242 p->z = 0.0f;
01243 p->elevation = northEdge[i];
01244 rc->points->addEntity(p);
01245 }
01246
01247
01248 p = new SElevationLookupPoint;
01249 p->x = 0.0f;
01250 p->z = 0.0f;
01251 p->elevation = nwElev;
01252 rc->points->addEntity(p);
01253 }
01254 break;
01255
01256 case ELEVATION_TYPE_CORNER:
01257 {
01258
01259
01260
01261
01262
01263 int tileResolution = thisBlock->GetDetailTileResolution();
01264
01265 int northResolution = 0;
01266 CElevationBlock *northBlock = Search (x, z+1);
01267 if (northBlock->GetElevationType() == ELEVATION_TYPE_CORNER) {
01268 northResolution = northBlock->GetDetailTileResolution();
01269 }
01270
01271 int southResolution = 0;
01272 CElevationBlock *southBlock = Search (x, z-1);
01273 if (southBlock->GetElevationType() == ELEVATION_TYPE_CORNER) {
01274 southResolution = southBlock->GetDetailTileResolution();
01275 }
01276
01277 int westResolution = 0;
01278 CElevationBlock *westBlock = Search (x-1, z);
01279 if (westBlock->GetElevationType() == ELEVATION_TYPE_CORNER) {
01280 westResolution = westBlock->GetDetailTileResolution();
01281 }
01282
01283 int eastResolution = 0;
01284 CElevationBlock *eastBlock = Search (x+1, z);
01285 if (eastBlock->GetElevationType() == ELEVATION_TYPE_CORNER) {
01286 eastResolution = eastBlock->GetDetailTileResolution();
01287 }
01288
01289
01290 int xTile = max3 (tileResolution, northResolution, southResolution);
01291 int zTile = max3 (tileResolution, westResolution, eastResolution);
01292 float **overallData;
01293 overallData = new float*[zTile];
01294 for (i=0; i<zTile; i++) {
01295 overallData[i] = new float[xTile];
01296 }
01297
01298
01299 if ((xTile > tileResolution) || (zTile > tileResolution)) {
01300
01301
01302 float **tileData;
01303 AllocateElevationArray (tileResolution, &tileData);
01304 thisBlock->GetDetailTileElevations (x, z, tileData);
01305 float dx = 1.0f / (float)(xTile - 1);
01306 float dz = 1.0f / (float)(zTile - 1);
01307 for (i=0; i<zTile; i++) {
01308 for (j=0; j<xTile; j++) {
01309 float xInt = j * dx;
01310 float zInt = i * dz;
01311 overallData[i][j] = InterpolatedData (xInt, zInt, tileResolution, tileData);
01312 }
01313 }
01314 FreeElevationArray (tileResolution, tileData);
01315
01316
01317 if (northResolution > tileResolution) {
01318
01319
01320 float **northData;
01321 AllocateElevationArray (northResolution, &northData);
01322 northBlock->GetDetailTileElevations(x, z+1, northData);
01323 if (xTile > northResolution) {
01324
01325
01326 for (j=0; j<xTile; j++) {
01327 overallData[zTile-1][j] = InterpolatedData (0.0f, (float)j * dx,
01328 northResolution, northData);
01329 }
01330 } else {
01331
01332
01333 for (j=0; j<xTile; j++) {
01334 overallData[zTile-1][j] = northData[0][j];
01335 }
01336 }
01337 FreeElevationArray (northResolution, northData);
01338 }
01339
01340
01341 if (southResolution > tileResolution) {
01342
01343
01344 float **southData;
01345 AllocateElevationArray (southResolution, &southData);
01346 southBlock->GetDetailTileElevations(x, z-1, southData);
01347 if (xTile > southResolution) {
01348
01349
01350 for (j=0; j<xTile; j++) {
01351 overallData[0][j] = InterpolatedData (1.0f, (float)j * dx,
01352 southResolution, southData);
01353 }
01354 } else {
01355
01356
01357 for (j=0; j<xTile; j++) {
01358 overallData[0][j] = southData[southResolution-1][j];
01359 }
01360 }
01361 FreeElevationArray (southResolution, southData);
01362 }
01363
01364
01365 if (westResolution > tileResolution) {
01366
01367
01368 float **westData;
01369 AllocateElevationArray (westResolution, &westData);
01370 westBlock->GetDetailTileElevations(x-1, z, westData);
01371 if (zTile > westResolution) {
01372
01373
01374 for (i=0; i<zTile; i++) {
01375 overallData[i][0] = InterpolatedData ((float)i * dz, 1.0f,
01376 westResolution, westData);
01377 }
01378 } else {
01379
01380
01381 for (i=0; i<zTile; i++) {
01382 overallData[i][0] = westData[i][westResolution-1];
01383 }
01384 }
01385 FreeElevationArray (westResolution, westData);
01386 }
01387
01388
01389 if (eastResolution > tileResolution) {
01390
01391
01392 float **eastData;
01393 AllocateElevationArray (eastResolution, &eastData);
01394 eastBlock->GetDetailTileElevations(x+1, z, eastData);
01395 if (zTile > eastResolution) {
01396
01397
01398 for (i=0; i<zTile; i++) {
01399 overallData[i][xTile-1] = InterpolatedData ((float)i * dz, 0.0f,
01400 eastResolution, eastData);
01401 }
01402 } else {
01403
01404
01405 for (i=0; i<zTile; i++) {
01406 overallData[i][xTile-1] = eastData[i][0];
01407 }
01408 }
01409 FreeElevationArray (eastResolution, eastData);
01410 }
01411 } else {
01412
01413
01414 thisBlock->GetDetailTileElevations (x, z, overallData);
01415 }
01416
01417
01418 rc = new CElevationLookup;
01419 rc->glType = GL_TRIANGLE_STRIP;
01420 int nStrips = zTile - 1;
01421 int stripSize = 2 * xTile;
01422 rc->u.stripData.nStrips = nStrips;
01423 rc->u.stripData.stripSize = stripSize;
01424 rc->points = new ulList(nStrips * stripSize);
01425
01426 float dx = 1.0f / (float)(xTile - 1);
01427 float dz = 1.0f / (float)(zTile - 1);
01428 SElevationLookupPoint *p;
01429 for (i=0; i<nStrips; i++) {
01430 for (j=0; j<xTile; j++) {
01431
01432 p = new SElevationLookupPoint;
01433 p->x = (float)j * dx;
01434 p->z = (float)(nStrips-i-1) * dz;
01435 p->elevation = overallData[i+1][j];
01436 rc->points->addEntity(p);
01437
01438
01439 p = new SElevationLookupPoint;
01440 p->x = (float)j * dx;
01441 p->z = (float)(nStrips-i) * dz;
01442 p->elevation = overallData[i][j];
01443 rc->points->addEntity(p);
01444 }
01445 }
01446
01447
01448 for (i=0; i<zTile; i++) {
01449 delete[] overallData[i];
01450 }
01451 delete[] overallData;
01452 }
01453 break;
01454 }
01455 } else {
01456 globals->logWarning->Write ("TEDB : Could not find elevations for DT %d,%d", x, z);
01457 }
01458
01459
01460 return rc;
01461 }
01462
01463
01464 CTileElevationDatabase *tedb = NULL;