git-svn-id: https://scorched3d.svn.sourceforge.net/svnroot/scorched3d/trunk/scorched...
[scorched3d/parasti.git] / src / client / landscape / Landscape.cpp
blob83ead94c311e3fa243081fa09873226b8c5996f7
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <landscape/Landscape.h>
22 #include <landscape/LandscapePoints.h>
23 #include <landscapemap/LandscapeMaps.h>
24 #include <landscape/LandscapeSoundManager.h>
25 #include <landscape/LandscapeMusicManager.h>
26 #include <landscape/Smoke.h>
27 #include <landscape/Wall.h>
28 #include <landscape/ShadowMap.h>
29 #include <landscape/InfoMap.h>
30 #include <landscape/GraphicalLandscapeMap.h>
31 #include <landscapedef/LandscapeTex.h>
32 #include <landscapedef/LandscapeDefn.h>
33 #include <landscapedef/LandscapeDefinition.h>
34 #include <landscapedef/LandscapeDefinitions.h>
35 #include <lang/LangResource.h>
36 #include <sky/Sky.h>
37 #include <water/Water.h>
38 #include <land/VisibilityPatchGrid.h>
39 #include <movement/TargetMovement.h>
40 #include <image/ImageFactory.h>
41 #include <image/ImageBitmap.h>
42 #include <GLEXT/GLImageModifier.h>
43 #include <GLEXT/GLStateExtension.h>
44 #include <console/ConsoleRuleMethodIAdapter.h>
45 #include <GLEXT/GLCameraFrustum.h>
46 #include <GLSL/GLSLShaderSetup.h>
47 #include <common/OptionsTransient.h>
48 #include <common/Defines.h>
49 #include <graph/OptionsDisplay.h>
50 #include <graph/MainCamera.h>
51 #include <sound/Sound.h>
52 #include <client/ScorchedClient.h>
53 #include <dialogs/CameraDialog.h>
54 #include <engine/ActionController.h>
55 #include <tankgraph/RenderTargets.h>
56 #include <time.h>
58 Landscape *Landscape::instance_ = 0;
60 Landscape *Landscape::instance()
62 if (!instance_)
64 instance_ = new Landscape;
66 return instance_;
69 Landscape::Landscape() :
70 resetLandscape_(false), resetLandscapeTimer_(0.0f),
71 textureType_(eDefault),
72 changeCount_(1),
73 landShader_(0)
75 water_ = new Water();
76 points_ = new LandscapePoints();
77 sky_ = new Sky();
78 smoke_ = new Smoke();
79 wall_ = new Wall();
81 new ConsoleRuleMethodIAdapter<Landscape>(
82 this, &Landscape::savePlan, "SavePlan");
85 Landscape::~Landscape()
89 void Landscape::simulate(float frameTime)
91 if (resetLandscape_)
93 resetLandscapeTimer_ -= frameTime;
94 if (resetLandscapeTimer_ < 0.0f)
96 // Update the plan texture
97 updatePlanATexture();
98 updatePlanTexture();
100 // Update the landscape
101 GraphicalLandscapeMap *landscapeMap = (GraphicalLandscapeMap *)
102 ScorchedClient::instance()->getLandscapeMaps().
103 getGroundMaps().getHeightMap().getGraphicalMap();
104 landscapeMap->updateWholeBuffer();
106 // Re-calculate the landsacpe on the wind indicator
107 changeCount_++;
108 resetLandscape_ = false;
112 float speedMult = ScorchedClient::instance()->
113 getActionController().getFast().asFloat();
114 water_->simulate(frameTime * speedMult);
115 sky_->simulate(frameTime * speedMult);
116 wall_->simulate(frameTime * speedMult);
117 LandscapeSoundManager::instance()->simulate(frameTime * speedMult);
120 void Landscape::recalculate()
122 if (!resetLandscape_)
124 resetLandscape_ = true;
125 resetLandscapeTimer_ = 1.0f; // Recalculate the water in x seconds
129 void Landscape::reset(ProgressCounter *counter)
131 changeCount_++;
133 // Recalculate all landscape objects
134 // Ensure all objects use any new landscape
135 ScorchedClient::instance()->
136 getParticleEngine().killAll();
137 MainCamera::instance()->getTarget().
138 getPrecipitationEngine().killAll();
139 CameraDialog::instance()->getCamera().
140 getPrecipitationEngine().killAll();
143 void Landscape::drawShadows()
145 if (!GLStateExtension::hasHardwareShadows()) return;
147 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SHADOWS_PRE");
149 // Turn off texturing
150 GLState glstate(GLState::TEXTURE_OFF | GLState::DEPTH_ON);
152 float landWidth = ScorchedClient::instance()->getLandscapeMaps().
153 getGroundMaps().getLandscapeWidth() / 2.0f;
154 float landHeight = ScorchedClient::instance()->getLandscapeMaps().
155 getGroundMaps().getLandscapeHeight() / 2.0f;
156 float maxWidth = MAX(landWidth, landHeight);
158 // Get the sun's position and landscape dimensions
159 Vector sunPosition = Landscape::instance()->getSky().getSun().getPosition();
160 sunPosition *= 0.5f + (maxWidth - 128.0f) / 256.0f;
162 Vector relativePosition = sunPosition;
163 relativePosition[0] -= landWidth;
164 relativePosition[1] -= landHeight;
165 float magnitude = relativePosition.Magnitude();
167 // Bind the frame buffer so we can render into it
168 shadowFrameBuffer_.bind();
169 glViewport(0, 0, shadowFrameBuffer_.getWidth(), shadowFrameBuffer_.getHeight());
171 // Setup the view from the sun
172 glMatrixMode(GL_PROJECTION);
173 glLoadIdentity();
174 gluPerspective(60.0f, 1.0f, magnitude - (maxWidth * 1.5f), magnitude + (maxWidth * 1.5f));
175 glMatrixMode(GL_MODELVIEW);
176 glLoadIdentity();
177 gluLookAt(
178 sunPosition[0], sunPosition[1], sunPosition[2],
179 landWidth, landHeight, 0.0f ,
180 0.0f, 0.0f, 1.0f);
182 GLCameraFrustum::instance()->draw(0);
184 // Save the matrixs used for the sun
185 glGetFloatv(GL_MODELVIEW_MATRIX, lightModelMatrix_);
186 glGetFloatv(GL_PROJECTION_MATRIX, lightProjMatrix_);
188 // Clear and setup the offset
189 glClear(GL_DEPTH_BUFFER_BIT);
191 // Set poly offset so that the shadows dont get precision artifacts
192 glPolygonOffset(10.0f, 10.0f);
193 glEnable(GL_POLYGON_OFFSET_FILL);
195 //Disable color writes, and use flat shading for speed
196 glColorMask(0, 0, 0, 0);
198 // Draw items that cast shadows
199 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SHADOWS_PRE");
201 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SHADOWS_DRAW_LAND");
202 VisibilityPatchGrid::instance()->drawLand(0, true);
203 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SHADOWS_DRAW_LAND");
205 if (!OptionsDisplay::instance()->getNoGLObjectShadows())
207 RenderTargets::instance()->shadowDraw();
210 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SHADOWS_POST");
212 static bool createdMap = false;
213 if (OptionsDisplay::instance()->getDrawGraphicalShadowMap())
215 if (!createdMap)
217 createdMap = true;
219 static float *depthResult =
220 new float[shadowFrameBuffer_.getWidth() * shadowFrameBuffer_.getHeight()];
221 static ImageHandle depthImage =
222 ImageFactory::createBlank(shadowFrameBuffer_.getWidth(),
223 shadowFrameBuffer_.getHeight());
225 glReadPixels(0, 0,
226 shadowFrameBuffer_.getWidth(), shadowFrameBuffer_.getHeight(),
227 GL_DEPTH_COMPONENT, GL_FLOAT, depthResult);
229 float min = 1.0, max = 0.0;
230 float *src = depthResult;
231 unsigned char *dest = depthImage.getBits();
232 for (int i=0; i<shadowFrameBuffer_.getWidth() * shadowFrameBuffer_.getHeight(); i++, src++, dest+=3)
234 if (*src != 1.0f)
236 if (*src != 0.0f)
238 min = MIN(min, *src);
239 max = MAX(max, *src);
242 //*src = 0.0f; // Black and white
243 dest[0] = (unsigned char) (*src * 255.0f);
244 dest[1] = (unsigned char) (*src * 255.0f);
245 dest[2] = (unsigned char) (*src * 255.0f);
249 colorDepthMap_.replace(depthImage);
252 else
254 createdMap = false;
257 //restore states
258 glColorMask(1, 1, 1, 1);
260 // Reset offset
261 glDisable(GL_POLYGON_OFFSET_FILL);
263 // Stop drawing to frame buffer
264 shadowFrameBuffer_.unBind();
266 // Reset camera
267 MainCamera::instance()->getCamera().draw();
268 GLCameraFrustum::instance()->draw(0);
270 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SHADOWS_POST");
273 void Landscape::drawSetup()
275 if (OptionsDisplay::instance()->getDrawLines()) glPolygonMode(GL_FRONT, GL_LINE);
277 // NOTE: The following code is drawn with fog on
278 // Be carefull as this we "dull" bilboard textures
279 if (!OptionsDisplay::instance()->getNoFog())
281 glEnable(GL_FOG); // NOTE: Fog on
285 void Landscape::drawTearDown()
287 glDisable(GL_FOG); // NOTE: Fog off
288 if (OptionsDisplay::instance()->getDrawLines()) glPolygonMode(GL_FRONT, GL_FILL);
291 void Landscape::drawLand()
293 drawSetup();
295 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_LOD");
296 VisibilityPatchGrid::instance()->calculateVisibility();
297 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_LOD");
299 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SKY");
300 sky_->drawBackdrop();
301 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SKY");
303 if (OptionsDisplay::instance()->getDrawLandscape())
305 if (GLStateExtension::hasHardwareShadows() &&
306 OptionsDisplay::instance()->getUseLandscapeTexture())
308 actualDrawLandShader();
310 else
312 actualDrawLandTextured();
316 if (OptionsDisplay::instance()->getDrawGraphicalShadowMap())
318 drawGraphicalShadowMap();
320 if (OptionsDisplay::instance()->getDrawGraphicalReflectionMap())
322 drawGraphicalReflectionMap();
325 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_POINTS");
326 points_->draw();
327 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_POINTS");
329 if (OptionsDisplay::instance()->getDrawMovement())
331 ScorchedClient::instance()->getTargetMovement().draw();
334 drawTearDown();
337 void Landscape::drawWater()
339 if (!water_->getWaterOn()) return;
341 if (GLStateExtension::hasFBO() &&
342 GLStateExtension::hasShaders() &&
343 !OptionsDisplay::instance()->getNoWaterReflections() &&
344 OptionsDisplay::instance()->getDrawWater() &&
345 water_->getWaterOn())
347 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "WATER_REFLECTIONS");
349 water_->bindWaterReflection();
351 glClearColor(0, 1.0f/16.0f, 1.0f/8.0f, 0);
352 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
354 glPushMatrix();
356 glTranslatef(0.0f, 0.0f, water_->getWaterHeight() * 2.0f);
358 // flip geometry at z=0 plane
359 glScalef(1.0f, 1.0f, -1.0f);
360 glCullFace(GL_FRONT);
362 drawSetup();
363 sky_->drawBackdrop();
364 sky_->drawLayers();
365 actualDrawLandReflection();
366 drawTearDown();
368 //water_->drawPoints(); // Bad reflections in large wind
370 glCullFace(GL_BACK);
371 glPopMatrix();
373 water_->unBindWaterReflection();
375 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_REFLECTIONS");
378 drawSetup();
380 water_->draw();
382 drawTearDown();
385 void Landscape::drawObjects()
387 drawSetup();
389 wall_->draw();
390 sky_->drawLayers();
392 drawTearDown();
395 int Landscape::getPlanTexSize()
397 switch (OptionsDisplay::instance()->getTexSize())
399 case 0:
400 return 64;
401 break;
402 case 2:
403 return 256;
404 break;
405 default:
406 return 128;
407 break;
409 return 128;
412 int Landscape::getMapTexSize()
414 switch (OptionsDisplay::instance()->getTexSize())
416 case 0:
417 return 256;
418 break;
419 case 2:
420 return 2048;
421 break;
422 default:
423 return 1024;
424 break;
426 return 1024;
429 void Landscape::generate(ProgressCounter *counter)
431 GraphicalLandscapeMap *landscapeMap = (GraphicalLandscapeMap *)
432 ScorchedClient::instance()->getLandscapeMaps().
433 getGroundMaps().getHeightMap().getGraphicalMap();
434 landscapeMap->updateWholeBuffer();
436 textureType_ = eDefault;
437 InfoMap::instance()->addAdapters();
439 // Choose the correct sizes for the current LOD
440 int mapTexSize = getMapTexSize();
441 int planTexSize = getPlanTexSize();
443 // Generate the texture used to map onto the landscape
444 if (!mainMap_.getBits())
446 mainMap_ = ImageFactory::createBlank(mapTexSize, mapTexSize);
447 bitmapPlanAlpha_ = ImageFactory::createBlank(planTexSize, planTexSize, true);
448 bitmapPlan_ = ImageFactory::createBlank(planTexSize, planTexSize);
449 bitmapPlanAlphaAlpha_ = ImageFactory::createBlank(planTexSize, planTexSize, false, 0);
450 splatMap_ = ImageFactory::createBlank(1024, 1024);
453 ImageHandle splatMask1 = ImageFactory::createBlank(mapTexSize, mapTexSize, true, 0);
454 ImageHandle splatMask2 = ImageFactory::createBlank(mapTexSize, mapTexSize, true, 0);
455 ImageHandle splatMaskBorder1 = ImageFactory::createBlank(64, 64, true, 0);
456 ImageHandle splatMaskBorder2 = ImageFactory::createBlank(64, 64, true, 0);
457 ImageModifier::redBitmap(splatMaskBorder1);
459 if (GLStateExtension::hasHardwareShadows())
461 if (!shadowFrameBuffer_.bufferValid())
463 // Create the frame buffer
464 if (!shadowFrameBuffer_.create(2048, 2048))
466 S3D::dialogExit("Scorched3D", "Failed to create shadow frame buffer");
471 // Removed for now as plan is square
472 // If (when) re-instated need to scale alpha map by playable arena, not full map size
473 /*ImageHandle plana = ImageFactory::loadImageHandle(S3D::getDataFile("data/windows/planaa.bmp"));
474 ImageModifier::scalePlanBitmap(bitmapPlanAlphaAlpha_, plana,
475 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeWidth(),
476 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeHeight());*/
478 // Load the texture bitmaps from resources
479 LandscapeDefn *defn =
480 ScorchedClient::instance()->getLandscapeMaps().getDefinitions().getDefn();
481 LandscapeTex *tex =
482 ScorchedClient::instance()->getLandscapeMaps().getDefinitions().getTex();
483 if (tex->texture->getType() == LandscapeTexType::eTextureGenerate)
485 LandscapeTexTextureGenerate *generate =
486 (LandscapeTexTextureGenerate *) tex->texture;
488 ImageHandle texture0 =
489 ImageFactory::loadImageHandle(S3D::getDataFile(generate->texture0.c_str()));
490 ImageHandle texture1 =
491 ImageFactory::loadImageHandle(S3D::getDataFile(generate->texture1.c_str()));
492 ImageHandle texture2 =
493 ImageFactory::loadImageHandle(S3D::getDataFile(generate->texture2.c_str()));
494 ImageHandle texture3 =
495 ImageFactory::loadImageHandle(S3D::getDataFile(generate->texture3.c_str()));
496 ImageHandle bitmapShore =
497 ImageFactory::loadImageHandle(S3D::getDataFile(generate->shore.c_str()));
498 ImageHandle bitmapRock =
499 ImageFactory::loadImageHandle(S3D::getDataFile(generate->rockside.c_str()));
500 ImageHandle bitmapRoof =
501 ImageFactory::loadImageHandle(S3D::getDataFile(generate->roof.c_str()));
502 Image *bitmaps[4];
503 bitmaps[0] = &texture0;
504 bitmaps[1] = &texture1;
505 bitmaps[2] = &texture2;
506 bitmaps[3] = &texture3;
508 // Generate the new landscape
509 if (counter) counter->setNewOp(LANG_RESOURCE("LANDSCAPE_MAP", "Landscape Map"));
510 ImageModifier::addHeightToBitmap(
511 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getHeightMap(),
512 mainMap_, splatMask1, splatMask2,
513 bitmapRock, bitmapShore, bitmaps, 4, 1024, counter);
515 #ifdef SPLAT_MAP
516 // Generate splat texture maps
517 ImageModifier::addTexturesToBitmap(
518 splatMap_,
519 bitmapRock, bitmapShore, bitmaps, 4);
520 splatTextures_.create(splatMap_, false);
522 // Set up the splat textures
523 splatMaskTexture1_.replace(splatMask1, false);
524 splatMaskTexture2_.replace(splatMask2, false);
525 splatMaskTextureBorder1_.replace(splatMaskBorder1, false);
526 splatMaskTextureBorder2_.replace(splatMaskBorder2, false);
527 #endif
529 // Set the general surround and roof texture
530 groundTexture_.replace(texture0, false);
531 roofTexture_.replace(bitmapRoof, true);
533 else
535 S3D::dialogExit("Landscape", S3D::formatStringBuffer(
536 "Failed to find heightmap type %i",
537 tex->texture->getType()));
540 points_->generate();
542 // Add lighting to the landscape texture
543 sky_->getSun().setPosition(tex->skysunxy, tex->skysunyz);
544 if (!GLStateExtension::hasHardwareShadows())
546 Vector sunPos = sky_->getSun().getPosition();
547 ImageModifier::addLightMapToBitmap(mainMap_,
548 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getHeightMap(),
549 sunPos, // Match with shadows
550 tex->skyambience, tex->skydiffuse, counter);
552 else
554 // Load shader
555 if (!landShader_)
557 landShader_ = new GLSLShaderSetup(
558 S3D::getDataFile("data/shaders/land.vshader"),
559 S3D::getDataFile("data/shaders/land.fshader"));
563 // Add shadows to the mainmap
564 std::list<PlacementShadowDefinition::Entry> &shadows =
565 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().
566 getGroups().getShadows();
567 std::list<PlacementShadowDefinition::Entry>::iterator itor;
568 for (itor = shadows.begin();
569 itor != shadows.end();
570 itor++)
572 PlacementShadowDefinition::Entry &entry = (*itor);
574 entry.definition_->updateLandscapeTexture(
575 !GLStateExtension::hasHardwareShadows() ||
576 OptionsDisplay::instance()->getNoGLObjectShadows(),
577 ScorchedClient::instance()->getContext(),
578 entry.position_, entry.size_);
581 // Create the main landscape texture
582 DIALOG_ASSERT(texture_.replace(mainMap_, false));
584 // Create the landscape texture used for the small plan window
585 gluScaleImage(
586 GL_RGB,
587 mainMap_.getWidth(), mainMap_.getHeight(),
588 GL_UNSIGNED_BYTE, mainMap_.getBits(),
589 bitmapPlan_.getWidth(), bitmapPlan_.getHeight(),
590 GL_UNSIGNED_BYTE, bitmapPlan_.getBits());
592 // Generate the scorch map for the landscape
593 std::string sprayMaskFile = S3D::getDataFile("data/textures/smoke01.bmp");
594 ImageHandle sprayMaskBitmap =
595 ImageFactory::loadImageHandle(sprayMaskFile.c_str(), sprayMaskFile.c_str(), false);
596 scorchMap_ =
597 ImageFactory::loadImageHandle(S3D::getDataFile(tex->scorch.c_str()));
598 ImageHandle scorchMap = scorchMap_.createResize(
599 sprayMaskBitmap.getWidth(), sprayMaskBitmap.getHeight());
600 ImageHandle texture1New = ImageFactory::createBlank(sprayMaskBitmap.getWidth(), sprayMaskBitmap.getHeight(), true);
601 ImageModifier::makeBitmapTransparent(texture1New, scorchMap, sprayMaskBitmap);
602 landTex1_.replace(texture1New);
604 // Magma
605 ImageHandle bitmapMagma =
606 ImageFactory::loadImageHandle(S3D::getDataFile(tex->magmasmall.c_str()));
607 DIALOG_ASSERT(magTexture_.replace(bitmapMagma));
609 // Detail
610 ImageHandle bitmapDetail =
611 ImageFactory::loadImageHandle(S3D::getDataFile(tex->detail.c_str()));
612 DIALOG_ASSERT(detailTexture_.replace(bitmapDetail, true));
614 // Set the fog color
615 GLfloat fogColorF[4];
616 fogColorF[0] = tex->fog[0];
617 fogColorF[1] = tex->fog[1];
618 fogColorF[2] = tex->fog[2];
619 fogColorF[3] = 1.0f;
620 glFogfv(GL_FOG_COLOR, fogColorF);
621 GLfloat fogDensity = tex->fogdensity;
622 glFogf(GL_FOG_DENSITY, fogDensity);
624 // Load the sky
625 sky_->generate();
627 // Load water
628 water_->generate(counter);
630 // Create the plan textures (for the plan and wind dialogs)
631 updatePlanTexture();
632 updatePlanATexture();
634 // Add any ambientsounds
635 LandscapeSoundManager::instance()->addSounds();
636 LandscapeMusicManager::instance()->addMusics();
639 void Landscape::updatePlanTexture()
641 if (water_->getWaterOn())
643 ImageModifier::addWaterToBitmap(
644 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getHeightMap(),
645 bitmapPlan_, water_->getWaterBitmap(), water_->getWaterHeight());
647 if (ScorchedClient::instance()->getOptionsTransient().getWallType() !=
648 OptionsTransient::wallNone)
650 ImageModifier::addBorderToBitmap(bitmapPlan_, 3,
651 ScorchedClient::instance()->getOptionsTransient().getWallColor());
654 DIALOG_ASSERT(planTexture_.replace(bitmapPlan_, false));
657 void Landscape::actualDrawLandTextured()
659 unsigned int state = 0;
660 if (!OptionsDisplay::instance()->getUseLandscapeTexture()) state |= GLState::TEXTURE_OFF;
662 GLState glState(state);
664 bool useDetail =
665 GLStateExtension::getTextureUnits() > 2 &&
666 OptionsDisplay::instance()->getDetailTexture() &&
667 GLStateExtension::hasEnvCombine();
669 if (OptionsDisplay::instance()->getUseLandscapeTexture())
671 if (GLStateExtension::hasMultiTex())
673 if (useDetail)
675 glActiveTextureARB(GL_TEXTURE2_ARB);
676 glEnable(GL_TEXTURE_2D);
677 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
678 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2);
680 detailTexture_.draw(true);
683 glActiveTextureARB(GL_TEXTURE1_ARB);
684 glEnable(GL_TEXTURE_2D);
685 getShadowMap().setTexture();
687 glActiveTextureARB(GL_TEXTURE0_ARB);
690 texture_.draw(true);
693 glColor3f(1.0f, 1.0f, 1.0f);
694 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_LAND");
695 VisibilityPatchGrid::instance()->drawLand();
696 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_LAND");
697 if (OptionsDisplay::instance()->getDrawLandLOD())
699 VisibilityPatchGrid::instance()->drawLandLODLevels();
702 if (OptionsDisplay::instance()->getDrawSurround())
704 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SURROUND");
705 groundTexture_.draw(true);
706 VisibilityPatchGrid::instance()->drawSurround();
707 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SURROUND");
710 if (OptionsDisplay::instance()->getUseLandscapeTexture())
712 if (GLStateExtension::hasMultiTex())
714 if (GLStateExtension::getTextureUnits() > 2 &&
715 OptionsDisplay::instance()->getDetailTexture() &&
716 GLStateExtension::hasEnvCombine())
718 glActiveTextureARB(GL_TEXTURE2_ARB);
719 glDisable(GL_TEXTURE_2D);
722 glActiveTextureARB(GL_TEXTURE1_ARB);
723 glDisable(GL_TEXTURE_2D);
724 glActiveTextureARB(GL_TEXTURE0_ARB);
729 void Landscape::actualDrawLandReflection()
731 unsigned int state = GLState::BLEND_ON | GLState::LIGHTING_ON | GLState::LIGHT1_ON;
732 if (!OptionsDisplay::instance()->getUseLandscapeTexture()) state |= GLState::TEXTURE_OFF;
733 GLState glState(state);
735 Vector4 ambientColor(1.0f, 1.0f, 1.0f, 1.0f);
736 Vector4 diffuseColor(0.0f, 0.0f, 0.0f, 1.0f);
737 Vector4 specularColor(1.0f, 1.0f, 1.0f, 1.0f);
738 Vector4 emissiveColor(0.0f, 0.0f, 0.0f, 1.0f);
739 float shininess = 1.0f;
740 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientColor);
741 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuseColor);
742 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor);
743 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emissiveColor);
744 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
746 Landscape::instance()->getSky().getSun().setLightPosition();
748 if (OptionsDisplay::instance()->getUseLandscapeTexture())
750 planAlphaTexture_.draw(true);
753 glColor3f(1.0f, 1.0f, 1.0f);
754 VisibilityPatchGrid::instance()->drawLand(2);
757 void Landscape::createShadowMatrix()
759 if (!GLStateExtension::hasHardwareShadows()) return;
761 // Create texture matrix
762 static const float mNormalizeMatrix[] =
764 0.5f, 0.0f, 0.0f, 0.0f,
765 0.0f, 0.5f, 0.0f, 0.0f,
766 0.0f, 0.0f, 0.5f, 0.0f,
767 0.5f, 0.5f, 0.5f, 1.0f
769 static GLfloat modelMatrix[16], modelMatrixI[16];
770 glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
772 // Copy and transpose
773 modelMatrixI[ 0] = modelMatrix[ 0];
774 modelMatrixI[ 4] = modelMatrix[ 1];
775 modelMatrixI[ 8] = modelMatrix[ 2];
776 modelMatrixI[ 1] = modelMatrix[ 4];
777 modelMatrixI[ 5] = modelMatrix[ 5];
778 modelMatrixI[ 9] = modelMatrix[ 6];
779 modelMatrixI[ 2] = modelMatrix[ 8];
780 modelMatrixI[ 6] = modelMatrix[ 9];
781 modelMatrixI[10] = modelMatrix[10];
782 modelMatrixI[ 3] = 0;
783 modelMatrixI[ 7] = 0;
784 modelMatrixI[11] = 0;
785 modelMatrixI[15] = modelMatrix[15];
787 // Apply the inverse transformation
788 modelMatrixI[12] = modelMatrixI[0] * -modelMatrix[12] + modelMatrixI[4] * -modelMatrix[13] + modelMatrixI[ 8] * -modelMatrix[14];
789 modelMatrixI[13] = modelMatrixI[1] * -modelMatrix[12] + modelMatrixI[5] * -modelMatrix[13] + modelMatrixI[ 9] * -modelMatrix[14];
790 modelMatrixI[14] = modelMatrixI[2] * -modelMatrix[12] + modelMatrixI[6] * -modelMatrix[13] + modelMatrixI[10] * -modelMatrix[14];
792 // Create and save texture matrix
793 glMatrixMode(GL_TEXTURE);
794 glLoadMatrixf(mNormalizeMatrix);
795 glMultMatrixf(lightProjMatrix_);
796 glMultMatrixf(lightModelMatrix_);
797 glMultMatrixf(modelMatrixI);
798 glGetFloatv(GL_TEXTURE_MATRIX, shadowTextureMatrix_);
799 glMatrixMode(GL_MODELVIEW);
802 void Landscape::actualDrawLandShader()
804 GLState glState(GLState::TEXTURE_ON | GLState::DEPTH_ON);
806 getSky().getSun().setLightPosition(false);
808 #ifdef SPLAT_MAP
809 landShader_->use();
810 landShader_->set_gl_texture(splatMaskTexture1_, "splat1map", 0);
811 landShader_->set_gl_texture(splatMaskTexture2_, "splat2map", 1);
812 landShader_->set_gl_texture(splatTextures_, "splattex", 2);
813 landShader_->set_gl_texture(shadowFrameBuffer_, "shadow", 3);
814 #else
815 landShader_->use();
816 landShader_->set_gl_texture(texture_, "mainmap", 0);
817 landShader_->set_gl_texture(detailTexture_, "detailmap", 1);
819 glActiveTextureARB(GL_TEXTURE2_ARB);
820 glEnable(GL_TEXTURE_2D);
821 landShader_->set_gl_texture(shadowFrameBuffer_, "shadow", 2);
822 glMatrixMode(GL_TEXTURE);
823 createShadowMatrix();
824 glMatrixMode(GL_MODELVIEW);
825 glActiveTextureARB(GL_TEXTURE0_ARB);
826 #endif
828 glColor3f(1.0f, 1.0f, 1.0f);
830 // Draw Land
831 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_LAND");
832 VisibilityPatchGrid::instance()->drawLand();
833 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_LAND");
835 // Draw Surround
836 if (OptionsDisplay::instance()->getDrawSurround())
838 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SURROUND");
839 #ifdef SPLAT_MAP
840 landShader_->set_gl_texture(splatMaskTextureBorder1_, "splat1map", 0);
841 landShader_->set_gl_texture(splatMaskTextureBorder2_, "splat2map", 1);
842 #else
843 if (OptionsDisplay::instance()->getDrawWater())
845 // Disable Tex
846 glActiveTextureARB(GL_TEXTURE2_ARB);
847 glMatrixMode(GL_TEXTURE);
848 glLoadIdentity();
849 glMatrixMode(GL_MODELVIEW);
850 glActiveTextureARB(GL_TEXTURE0_ARB);
852 landShader_->use_fixed();
854 groundTexture_.draw(true);
856 else
858 landShader_->set_gl_texture(groundTexture_, "mainmap", 0);
860 #endif
861 VisibilityPatchGrid::instance()->drawSurround();
862 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SURROUND");
865 // Disable Tex
866 glActiveTextureARB(GL_TEXTURE2_ARB);
867 glMatrixMode(GL_TEXTURE);
868 glLoadIdentity();
869 glMatrixMode(GL_MODELVIEW);
870 glActiveTextureARB(GL_TEXTURE0_ARB);
872 landShader_->use_fixed();
875 void Landscape::drawGraphicalShadowMap()
877 GLState state(GLState::TEXTURE_ON);
879 glColor3f( 1.f, 1.f, 1.f );
880 glMatrixMode(GL_PROJECTION);
881 glPushMatrix();
882 glLoadIdentity();
883 gluOrtho2D(0, 800, 0, 600);
884 glMatrixMode(GL_TEXTURE);
885 glPushMatrix();
886 glLoadIdentity();
887 glMatrixMode(GL_MODELVIEW);
888 glPushMatrix();
889 glLoadIdentity();
890 colorDepthMap_.draw(true);
891 glBegin(GL_QUADS);
892 glTexCoord2f(0.f, 0.f);
893 glVertex2i (0, 0);
894 glTexCoord2f(1.f, 0.f);
895 glVertex2i (300, 0);
896 glTexCoord2f(1.f, 1.f);
897 glVertex2i (300, 300);
898 glTexCoord2f(0.f, 1.f);
899 glVertex2i (0, 300);
900 glEnd();
901 glMatrixMode(GL_PROJECTION);
902 glPopMatrix();
903 glMatrixMode( GL_TEXTURE );
904 glPopMatrix();
905 glMatrixMode( GL_MODELVIEW );
906 glPopMatrix();
909 void Landscape::drawGraphicalReflectionMap()
911 GLState state(GLState::TEXTURE_ON);
913 glColor3f( 1.f, 1.f, 1.f );
914 glMatrixMode(GL_PROJECTION);
915 glPushMatrix();
916 glLoadIdentity();
917 gluOrtho2D(0, 800, 0, 600);
918 glMatrixMode(GL_TEXTURE);
919 glPushMatrix();
920 glLoadIdentity();
921 glMatrixMode(GL_MODELVIEW);
922 glPushMatrix();
923 glLoadIdentity();
924 water_->getReflectionTexture().draw(true);
925 glBegin(GL_QUADS);
926 glTexCoord2f(0.f, 0.f);
927 glVertex2i (0, 0);
928 glTexCoord2f(1.f, 0.f);
929 glVertex2i (300, 0);
930 glTexCoord2f(1.f, 1.f);
931 glVertex2i (300, 300);
932 glTexCoord2f(0.f, 1.f);
933 glVertex2i (0, 300);
934 glEnd();
935 glMatrixMode(GL_PROJECTION);
936 glPopMatrix();
937 glMatrixMode( GL_TEXTURE );
938 glPopMatrix();
939 glMatrixMode( GL_MODELVIEW );
940 glPopMatrix();
943 void Landscape::updatePlanATexture()
945 ImageModifier::removeWaterFromBitmap(
946 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getHeightMap(),
947 bitmapPlan_, bitmapPlanAlpha_, bitmapPlanAlphaAlpha_,
948 (water_->getWaterOn()?water_->getWaterHeight():-50.0f));
949 DIALOG_ASSERT(planAlphaTexture_.replace(bitmapPlanAlpha_, false));
950 planAlphaTexture_.draw();
951 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
952 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
955 void Landscape::restoreLandscapeTexture()
957 if (textureType_ == eDefault) return;
959 DIALOG_ASSERT(texture_.replace(mainMap_, false));
960 textureType_ = eDefault;
963 void Landscape::savePlan()
965 static unsigned counter = 0;
966 time_t currentTime = time(0);
967 bitmapPlan_.writeToFile(
968 S3D::getHomeFile(
969 S3D::formatStringBuffer("PlanShot-%i-%i.bmp", currentTime, counter++)));
972 Landscape::CameraContext::CameraContext()
974 shadowMap_ = new ShadowMap();
977 ShadowMap &Landscape::getShadowMap()
979 if (GLCamera::getCurrentCamera() ==
980 &MainCamera::instance()->getCamera())
982 return *cameraContexts_[0].shadowMap_;
984 else
986 return *cameraContexts_[1].shadowMap_;