00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <land/VisibilityPatchGrid.h>
00022 #include <landscape/Landscape.h>
00023 #include <water/Water2Patches.h>
00024 #include <sky/Sky.h>
00025 #include <landscapemap/LandscapeMaps.h>
00026 #include <landscape/GraphicalLandscapeMap.h>
00027 #include <client/ScorchedClient.h>
00028 #include <engine/GameState.h>
00029 #include <GLEXT/GLStateExtension.h>
00030 #include <GLEXT/GLVertexBufferObject.h>
00031 #include <GLEXT/GLCamera.h>
00032 #include <GLSL/GLSLShaderSetup.h>
00033 #include <graph/OptionsDisplay.h>
00034
00035 VisibilityPatchGrid *VisibilityPatchGrid::instance()
00036 {
00037 static VisibilityPatchGrid instance;
00038 return &instance;
00039 }
00040
00041 VisibilityPatchGrid::VisibilityPatchGrid() :
00042 landPatches_(0), targetPatches_(0),
00043 waterPatches_(0), visibilityPatches_(0),
00044 epoc_(0)
00045 {
00046 }
00047
00048 VisibilityPatchGrid::~VisibilityPatchGrid()
00049 {
00050 }
00051
00052 void VisibilityPatchGrid::clear()
00053 {
00054 delete [] landPatches_;
00055 landPatches_ = 0;
00056
00057 delete [] waterPatches_;
00058 waterPatches_ = 0;
00059
00060 delete [] targetPatches_;
00061 targetPatches_ = 0;
00062
00063 delete [] visibilityPatches_;
00064 visibilityPatches_ = 0;
00065 }
00066
00067 void VisibilityPatchGrid::generate()
00068 {
00069 clear();
00070 epoc_++;
00071
00072
00073 int mapWidth = ScorchedClient::instance()->getLandscapeMaps().
00074 getGroundMaps().getLandscapeWidth();
00075 int mapHeight = ScorchedClient::instance()->getLandscapeMaps().
00076 getGroundMaps().getLandscapeHeight();
00077 int actualWidth = mapWidth + 4096;
00078 int actualHeight = mapHeight + 4096;
00079 actualWidth = (actualWidth / 512) * 512;
00080 actualHeight = (actualHeight / 512) * 512;
00081
00082
00083 landIndexs_.generate(32, mapWidth);
00084
00085
00086 midX_ = -actualWidth / 2 + mapWidth / 2;
00087 midY_ = -actualHeight / 2 + mapHeight / 2;
00088 midX_ = (midX_ / 32) * 32;
00089 midY_ = (midY_ / 32) * 32;
00090
00091 {
00092
00093 landWidth_ = mapWidth / 32;
00094 landHeight_ = mapHeight / 32;
00095
00096
00097 landPatches_ = new LandVisibilityPatch[landWidth_ * landHeight_];
00098
00099
00100 LandVisibilityPatch *currentPatch = landPatches_;
00101 for (int y=0; y<landHeight_; y++)
00102 {
00103 for (int x=0; x<landWidth_; x++, currentPatch++)
00104 {
00105 LandVisibilityPatch *leftPatch = (x==0?0:currentPatch-1);
00106 LandVisibilityPatch *rightPatch = (x==landWidth_-1?0:currentPatch+1);
00107 LandVisibilityPatch *topPatch = (y==0?0:currentPatch-landWidth_);
00108 LandVisibilityPatch *bottomPatch = (y==landHeight_-1?0:currentPatch+landWidth_);
00109
00110 currentPatch->setLocation(x * 32, y * 32,
00111 leftPatch, rightPatch, topPatch, bottomPatch);
00112 }
00113 }
00114 }
00115
00116 {
00117
00118 targetWidth_ = actualWidth / 32;
00119 targetHeight_ = actualHeight / 32;
00120
00121
00122 targetPatches_ = new TargetVisibilityPatch[targetWidth_ * targetHeight_];
00123
00124
00125 TargetVisibilityPatch *currentPatch = targetPatches_;
00126 for (int y=0; y<targetHeight_; y++)
00127 {
00128 for (int x=0; x<targetWidth_; x++, currentPatch++)
00129 {
00130 currentPatch->setLocation(x * 32 + midX_, y * 32 + midY_);
00131 }
00132 }
00133 }
00134
00135 {
00136
00137 waterWidth_ = actualWidth / 128;
00138 waterHeight_ = actualHeight / 128;
00139
00140
00141 waterPatches_ = new WaterVisibilityPatch[waterWidth_ * waterHeight_];
00142
00143
00144 WaterVisibilityPatch *currentPatch = waterPatches_;
00145 for (int y=0, py=0; y<waterHeight_; y++, py++)
00146 {
00147 for (int x=0, px=0; x<waterWidth_; x++, currentPatch++, px++)
00148 {
00149 WaterVisibilityPatch *leftPatch = (x==0?0:currentPatch-1);
00150 WaterVisibilityPatch *rightPatch = (x==waterWidth_-1?0:currentPatch+1);
00151 WaterVisibilityPatch *topPatch = (y==0?0:currentPatch-waterWidth_);
00152 WaterVisibilityPatch *bottomPatch = (y==waterHeight_-1?0:currentPatch+waterWidth_);
00153
00154 currentPatch->setLocation(x * 128 + midX_, y * 128 + midY_,
00155 px % 2, py % 2,
00156 leftPatch, rightPatch, topPatch, bottomPatch);
00157 }
00158 }
00159 }
00160
00161 {
00162
00163 visibilityWidth_ = actualWidth / 512;
00164 visibilityHeight_ = actualHeight / 512;
00165
00166
00167 visibilityPatches_ = new VisibilityPatchQuad[visibilityWidth_ * visibilityHeight_];
00168
00169
00170 VisibilityPatchQuad *currentPatch = visibilityPatches_;
00171 for (int y=0; y<visibilityHeight_; y++)
00172 {
00173 for (int x=0; x<visibilityWidth_; x++, currentPatch++)
00174 {
00175 currentPatch->setLocation(this, x * 512 + midX_, y * 512 + midY_, 512,
00176 mapWidth, mapHeight);
00177 }
00178 }
00179 }
00180
00181 {
00182 patchInfo_.generate(
00183 landWidth_ * landHeight_,
00184 waterWidth_ * waterHeight_,
00185 targetWidth_ * targetHeight_);
00186 }
00187
00188 surround_.generate();
00189 }
00190
00191 void VisibilityPatchGrid::recalculateErrors(FixedVector &position, fixed size)
00192 {
00193 int sizei = size.asInt();
00194 int midX = position[0].asInt();
00195 int midY = position[1].asInt();
00196
00197 int startX = midX - sizei;
00198 int startY = midY - sizei;
00199 int endX = midX + sizei;
00200 int endY = midY + sizei;
00201
00202 startX /= 32;
00203 startY /= 32;
00204 endX /= 32;
00205 endY /= 32;
00206
00207 if (endX < 0 || endY < 0) return;
00208 if (startX >= landWidth_ || startY >= landHeight_) return;
00209
00210 startX = MAX(0, startX);
00211 startY = MAX(0, startY);
00212 endX = MIN(landWidth_ - 1, endX);
00213 endY = MIN(landHeight_ - 1, endY);
00214
00215 for (int x=startX; x<=endX; x++)
00216 {
00217 for (int y=startY; y<=endY; y++)
00218 {
00219 LandVisibilityPatch &patch = landPatches_[x + y * landWidth_];
00220 patch.setRecalculateErrors();
00221 }
00222 }
00223 }
00224
00225 LandVisibilityPatch *VisibilityPatchGrid::getLandVisibilityPatch(int x, int y)
00226 {
00227 DIALOG_ASSERT(epoc_);
00228
00229 int realX = x / 32;
00230 int realY = y / 32;
00231
00232 if (realX < 0 || realY < 0 ||
00233 realX >= landWidth_ || realY >= landHeight_)
00234 {
00235 return 0;
00236 }
00237
00238 return &landPatches_[realX + realY * landWidth_];
00239 }
00240
00241 TargetVisibilityPatch *VisibilityPatchGrid::getTargetVisibilityPatch(int x, int y)
00242 {
00243 DIALOG_ASSERT(epoc_);
00244
00245 int realX = (x - midX_) / 32;
00246 int realY = (y - midY_) / 32;
00247
00248 if (realX < 0 || realY < 0 ||
00249 realX >= targetWidth_ || realY >= targetHeight_)
00250 {
00251 return 0;
00252 }
00253
00254 return &targetPatches_[realX + realY * targetWidth_];
00255 }
00256
00257 WaterVisibilityPatch *VisibilityPatchGrid::getWaterVisibilityPatch(int x, int y)
00258 {
00259 DIALOG_ASSERT(epoc_);
00260
00261 int realX = (x - midX_) / 128;
00262 int realY = (y - midY_) / 128;
00263
00264 if (realX < 0 || realY < 0 ||
00265 realX >= waterWidth_ || realY >= waterHeight_)
00266 {
00267 return 0;
00268 }
00269
00270 return &waterPatches_[realX + realY * waterWidth_];
00271 }
00272
00273 void VisibilityPatchGrid::calculateVisibility()
00274 {
00275 Vector &cameraPos = GLCamera::getCurrentCamera()->getCurrentPos();
00276
00277 patchInfo_.reset();
00278
00279
00280 VisibilityPatchQuad *currentPatch = visibilityPatches_;
00281 for (int y=0; y<visibilityHeight_; y++)
00282 {
00283 for (int x=0; x<visibilityWidth_; x++, currentPatch++)
00284 {
00285 currentPatch->calculateVisibility(patchInfo_, cameraPos);
00286 }
00287 }
00288 }
00289
00290 void VisibilityPatchGrid::drawLand(int addIndex, bool simple)
00291 {
00292 GraphicalLandscapeMap *landscapeMap = (GraphicalLandscapeMap *)
00293 ScorchedClient::instance()->getLandscapeMaps().
00294 getGroundMaps().getHeightMap().getGraphicalMap();
00295
00296 if (!OptionsDisplay::instance()->getNoGLDrawElements() &&
00297 GLStateExtension::hasDrawRangeElements())
00298 {
00299
00300 if (landIndexs_.getBufferObject())
00301 {
00302 landIndexs_.getBufferObject()->bind();
00303 }
00304
00305
00306 if (landscapeMap->getBufferObject())
00307 {
00308 landscapeMap->getBufferObject()->bind();
00309 }
00310
00311 glEnableClientState(GL_VERTEX_ARRAY);
00312 if (!simple)
00313 {
00314 glEnableClientState(GL_NORMAL_ARRAY);
00315 if (GLStateExtension::hasMultiTex())
00316 {
00317 glClientActiveTextureARB(GL_TEXTURE1_ARB);
00318 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00319 if (GLStateExtension::getTextureUnits() > 2)
00320 {
00321 glClientActiveTextureARB(GL_TEXTURE2_ARB);
00322 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00323 }
00324 }
00325 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00326 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00327 }
00328 }
00329
00330 if (simple)
00331 {
00332 LandVisibilityPatch *currentPatch = landPatches_;
00333 for (int y=0; y<landHeight_; y++)
00334 {
00335 for (int x=0; x<landWidth_; x++, currentPatch++)
00336 {
00337 MipMapPatchIndex *landIndex = landIndexs_.getIndex(4, 0);
00338 if (landIndex) currentPatch->draw(*landIndex, true);
00339 }
00340 }
00341 }
00342 else
00343 {
00344 void *currentPatchPtr = 0;
00345 TargetListIterator patchItor(patchInfo_.getLandVisibility());
00346 while (currentPatchPtr = patchItor.getNext())
00347 {
00348 LandVisibilityPatch *currentPatch = (LandVisibilityPatch *) currentPatchPtr;
00349 unsigned int index = currentPatch->getVisibilityIndex();
00350 if (index == -1)
00351 {
00352 continue;
00353 }
00354
00355 unsigned int borders = 0;
00356 int leftIndex = currentPatch->getLeftPatch()?
00357 currentPatch->getLeftPatch()->getVisibilityIndex():-1;
00358 int rightIndex = currentPatch->getRightPatch()?
00359 currentPatch->getRightPatch()->getVisibilityIndex():-1;
00360 int topIndex = currentPatch->getTopPatch()?
00361 currentPatch->getTopPatch()->getVisibilityIndex():-1;
00362 int bottomIndex = currentPatch->getBottomPatch()?
00363 currentPatch->getBottomPatch()->getVisibilityIndex():-1;
00364
00365 MipMapPatchIndex *landIndex =
00366 landIndexs_.getIndex(index, leftIndex, rightIndex, topIndex, bottomIndex, addIndex);
00367 if (landIndex) currentPatch->draw(*landIndex, false);
00368 }
00369 }
00370
00371 if (!OptionsDisplay::instance()->getNoGLDrawElements() &&
00372 GLStateExtension::hasDrawRangeElements())
00373 {
00374 glDisableClientState(GL_VERTEX_ARRAY);
00375 if (!simple)
00376 {
00377 glDisableClientState(GL_NORMAL_ARRAY);
00378 if (GLStateExtension::hasMultiTex())
00379 {
00380 glClientActiveTextureARB(GL_TEXTURE1_ARB);
00381 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00382 if (GLStateExtension::getTextureUnits() > 2)
00383 {
00384 glClientActiveTextureARB(GL_TEXTURE2_ARB);
00385 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00386 }
00387 }
00388 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00389 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00390 }
00391
00392
00393 if (landIndexs_.getBufferObject())
00394 {
00395 landIndexs_.getBufferObject()->unbind();
00396 }
00397
00398
00399 if (landscapeMap->getBufferObject())
00400 {
00401 landscapeMap->getBufferObject()->unbind();
00402 }
00403 }
00404 }
00405
00406 void VisibilityPatchGrid::drawLandLODLevels()
00407 {
00408 {
00409 void *currentPatchPtr = 0;
00410 TargetListIterator patchItor(patchInfo_.getLandVisibility());
00411 while (currentPatchPtr = patchItor.getNext())
00412 {
00413 LandVisibilityPatch *currentPatch = (LandVisibilityPatch *) currentPatchPtr;
00414 unsigned int index = currentPatch->getVisibilityIndex();
00415 if (index == -1) continue;
00416
00417 unsigned int borders = 0;
00418 int leftIndex = currentPatch->getLeftPatch()?
00419 currentPatch->getLeftPatch()->getVisibilityIndex():-1;
00420 int rightIndex = currentPatch->getRightPatch()?
00421 currentPatch->getRightPatch()->getVisibilityIndex():-1;
00422 int topIndex = currentPatch->getTopPatch()?
00423 currentPatch->getTopPatch()->getVisibilityIndex():-1;
00424 int bottomIndex = currentPatch->getBottomPatch()?
00425 currentPatch->getBottomPatch()->getVisibilityIndex():-1;
00426
00427 MipMapPatchIndex *landIndex =
00428 landIndexs_.getIndex(index, leftIndex, rightIndex, topIndex, bottomIndex, 0);
00429 if (landIndex) currentPatch->drawLODLevel(*landIndex);
00430 }
00431 }
00432 }
00433
00434 void VisibilityPatchGrid::drawSurround()
00435 {
00436 surround_.draw(ScorchedClient::instance()->getLandscapeMaps().
00437 getGroundMaps().getHeightMap(), true, true);
00438 }
00439
00440 void VisibilityPatchGrid::drawWater(Water2Patches &patches,
00441 MipMapPatchIndexs &indexes, Vector &cameraPosition,
00442 Vector landscapeSize,
00443 GLSLShaderSetup *waterShader)
00444 {
00445 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "WATER_DRAW");
00446
00447 if (!OptionsDisplay::instance()->getNoGLDrawElements() &&
00448 GLStateExtension::hasDrawRangeElements())
00449 {
00450 glEnableClientState(GL_VERTEX_ARRAY);
00451 glEnableClientState(GL_NORMAL_ARRAY);
00452
00453
00454 if (patches.getBufferObject())
00455 {
00456 patches.getBufferObject()->bind();
00457 }
00458
00459
00460 if (indexes.getBufferObject())
00461 {
00462 indexes.getBufferObject()->bind();
00463 }
00464 }
00465
00466 for (int w=0; w<4; w++)
00467 {
00468 Water2Patch *patch = patches.getPatch(w);
00469
00470 if (!OptionsDisplay::instance()->getNoGLDrawElements() &&
00471 GLStateExtension::hasDrawRangeElements())
00472 {
00473
00474 float *data = 0;
00475 if (patch->getBufferOffSet() != -1)
00476 {
00477 data = (float*) NULL + (patch->getBufferOffSet() / sizeof(unsigned int));
00478 }
00479 else
00480 {
00481 data = &patch->getInternalData()->x;
00482 }
00483
00484
00485 glVertexPointer(3, GL_FLOAT, sizeof(Water2Patch::Data), data);
00486
00487
00488 glNormalPointer(GL_FLOAT, sizeof(Water2Patch::Data), data + 3);
00489 }
00490
00491 static float startproj[16], startmodel[16];
00492 glGetFloatv(GL_PROJECTION_MATRIX, startproj);
00493 glGetFloatv(GL_MODELVIEW_MATRIX, startmodel);
00494
00495
00496 void *currentPatchPtr = 0;
00497 TargetListIterator patchItor(patchInfo_.getWaterVisibility(w));
00498 while (currentPatchPtr = patchItor.getNext())
00499 {
00500 WaterVisibilityPatch *currentPatch = (WaterVisibilityPatch *) currentPatchPtr;
00501 unsigned int index = currentPatch->getVisibilityIndex();
00502 if (index == -1) continue;
00503
00504 unsigned int borders = 0;
00505 int leftIndex = currentPatch->getLeftPatch()?
00506 currentPatch->getLeftPatch()->getVisibilityIndex():-1;
00507 int rightIndex = currentPatch->getRightPatch()?
00508 currentPatch->getRightPatch()->getVisibilityIndex():-1;
00509 int topIndex = currentPatch->getTopPatch()?
00510 currentPatch->getTopPatch()->getVisibilityIndex():-1;
00511 int bottomIndex = currentPatch->getBottomPatch()?
00512 currentPatch->getBottomPatch()->getVisibilityIndex():-1;
00513
00514 glPushMatrix();
00515 glTranslatef(
00516 currentPatch->getOffset()[0],
00517 currentPatch->getOffset()[1],
00518 currentPatch->getOffset()[2]);
00519
00520
00521 if (waterShader)
00522 {
00523 if (!OptionsDisplay::instance()->getSimpleWaterShaders())
00524 {
00525 Vector landfoam;
00526 landfoam[0] = currentPatch->getOffset()[0];
00527 landfoam[1] = currentPatch->getOffset()[1];
00528 landfoam[2] = ((currentPatch->getPosition()[0] >= 0.0f &&
00529 currentPatch->getPosition()[1] >= 0.0f &&
00530 currentPatch->getPosition()[0] <= landscapeSize[0] &&
00531 currentPatch->getPosition()[1] <= landscapeSize[1])?1.0f:0.0f);
00532 waterShader->set_uniform("landfoam", landfoam);
00533 }
00534
00535
00536
00537 Landscape::instance()->getSky().getSun().setLightPosition(true);
00538
00539
00540 glActiveTexture(GL_TEXTURE1);
00541 glMatrixMode(GL_TEXTURE);
00542 glLoadIdentity();
00543 glTranslatef(0.5f,0.5f,0.0f);
00544 glScalef(0.5f,0.5f,1.0f);
00545 glMultMatrixf(startproj);
00546 glMultMatrixf(startmodel);
00547 glTranslatef(
00548 currentPatch->getOffset()[0],
00549 currentPatch->getOffset()[1],
00550 currentPatch->getOffset()[2]);
00551 glMatrixMode(GL_MODELVIEW);
00552
00553
00554 glActiveTexture(GL_TEXTURE0);
00555 }
00556
00557 MipMapPatchIndex *patchIndex =
00558 indexes.getIndex(index, leftIndex, rightIndex, topIndex, bottomIndex, 0);
00559 if (patchIndex) patch->draw(*patchIndex);
00560
00561 glPopMatrix();
00562 }
00563 }
00564
00565 if (!OptionsDisplay::instance()->getNoGLDrawElements() &&
00566 GLStateExtension::hasDrawRangeElements())
00567 {
00568
00569 if (patches.getBufferObject())
00570 {
00571 patches.getBufferObject()->unbind();
00572 }
00573
00574
00575 if (indexes.getBufferObject())
00576 {
00577 indexes.getBufferObject()->unbind();
00578 }
00579
00580 glDisableClientState(GL_VERTEX_ARRAY);
00581 glDisableClientState(GL_NORMAL_ARRAY);
00582 }
00583
00584 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_DRAW");
00585 }