1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
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>
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>
58 Landscape
*Landscape::instance_
= 0;
60 Landscape
*Landscape::instance()
64 instance_
= new Landscape
;
69 Landscape::Landscape() :
70 resetLandscape_(false), resetLandscapeTimer_(0.0f
),
71 textureType_(eDefault
),
76 points_
= new LandscapePoints();
81 new ConsoleRuleMethodIAdapter
<Landscape
>(
82 this, &Landscape::savePlan
, "SavePlan");
85 Landscape::~Landscape()
89 void Landscape::simulate(float frameTime
)
93 resetLandscapeTimer_
-= frameTime
;
94 if (resetLandscapeTimer_
< 0.0f
)
96 // Update the plan texture
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
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
)
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
);
174 gluPerspective(60.0f
, 1.0f
, magnitude
- (maxWidth
* 1.5f
), magnitude
+ (maxWidth
* 1.5f
));
175 glMatrixMode(GL_MODELVIEW
);
178 sunPosition
[0], sunPosition
[1], sunPosition
[2],
179 landWidth
, landHeight
, 0.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())
219 static float *depthResult
=
220 new float[shadowFrameBuffer_
.getWidth() * shadowFrameBuffer_
.getHeight()];
221 static ImageHandle depthImage
=
222 ImageFactory::createBlank(shadowFrameBuffer_
.getWidth(),
223 shadowFrameBuffer_
.getHeight());
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)
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
);
258 glColorMask(1, 1, 1, 1);
261 glDisable(GL_POLYGON_OFFSET_FILL
);
263 // Stop drawing to frame buffer
264 shadowFrameBuffer_
.unBind();
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()
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();
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");
327 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_POINTS");
329 if (OptionsDisplay::instance()->getDrawMovement())
331 ScorchedClient::instance()->getTargetMovement().draw();
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
);
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
);
363 sky_
->drawBackdrop();
365 actualDrawLandReflection();
368 //water_->drawPoints(); // Bad reflections in large wind
373 water_
->unBindWaterReflection();
375 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_REFLECTIONS");
385 void Landscape::drawObjects()
395 int Landscape::getPlanTexSize()
397 switch (OptionsDisplay::instance()->getTexSize())
412 int Landscape::getMapTexSize()
414 switch (OptionsDisplay::instance()->getTexSize())
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();
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()));
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
);
516 // Generate splat texture maps
517 ImageModifier::addTexturesToBitmap(
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);
529 // Set the general surround and roof texture
530 groundTexture_
.replace(texture0
, false);
531 roofTexture_
.replace(bitmapRoof
, true);
535 S3D::dialogExit("Landscape", S3D::formatStringBuffer(
536 "Failed to find heightmap type %i",
537 tex
->texture
->getType()));
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
);
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();
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
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);
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
);
605 ImageHandle bitmapMagma
=
606 ImageFactory::loadImageHandle(S3D::getDataFile(tex
->magmasmall
.c_str()));
607 DIALOG_ASSERT(magTexture_
.replace(bitmapMagma
));
610 ImageHandle bitmapDetail
=
611 ImageFactory::loadImageHandle(S3D::getDataFile(tex
->detail
.c_str()));
612 DIALOG_ASSERT(detailTexture_
.replace(bitmapDetail
, true));
615 GLfloat fogColorF
[4];
616 fogColorF
[0] = tex
->fog
[0];
617 fogColorF
[1] = tex
->fog
[1];
618 fogColorF
[2] = tex
->fog
[2];
620 glFogfv(GL_FOG_COLOR
, fogColorF
);
621 GLfloat fogDensity
= tex
->fogdensity
;
622 glFogf(GL_FOG_DENSITY
, fogDensity
);
628 water_
->generate(counter
);
630 // Create the plan textures (for the plan and wind dialogs)
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
);
665 GLStateExtension::getTextureUnits() > 2 &&
666 OptionsDisplay::instance()->getDetailTexture() &&
667 GLStateExtension::hasEnvCombine();
669 if (OptionsDisplay::instance()->getUseLandscapeTexture())
671 if (GLStateExtension::hasMultiTex())
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
);
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);
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);
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
);
828 glColor3f(1.0f
, 1.0f
, 1.0f
);
831 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_LAND");
832 VisibilityPatchGrid::instance()->drawLand();
833 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_LAND");
836 if (OptionsDisplay::instance()->getDrawSurround())
838 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SURROUND");
840 landShader_
->set_gl_texture(splatMaskTextureBorder1_
, "splat1map", 0);
841 landShader_
->set_gl_texture(splatMaskTextureBorder2_
, "splat2map", 1);
843 if (OptionsDisplay::instance()->getDrawWater())
846 glActiveTextureARB(GL_TEXTURE2_ARB
);
847 glMatrixMode(GL_TEXTURE
);
849 glMatrixMode(GL_MODELVIEW
);
850 glActiveTextureARB(GL_TEXTURE0_ARB
);
852 landShader_
->use_fixed();
854 groundTexture_
.draw(true);
858 landShader_
->set_gl_texture(groundTexture_
, "mainmap", 0);
861 VisibilityPatchGrid::instance()->drawSurround();
862 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "LANDSCAPE_SURROUND");
866 glActiveTextureARB(GL_TEXTURE2_ARB
);
867 glMatrixMode(GL_TEXTURE
);
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
);
883 gluOrtho2D(0, 800, 0, 600);
884 glMatrixMode(GL_TEXTURE
);
887 glMatrixMode(GL_MODELVIEW
);
890 colorDepthMap_
.draw(true);
892 glTexCoord2f(0.f
, 0.f
);
894 glTexCoord2f(1.f
, 0.f
);
896 glTexCoord2f(1.f
, 1.f
);
897 glVertex2i (300, 300);
898 glTexCoord2f(0.f
, 1.f
);
901 glMatrixMode(GL_PROJECTION
);
903 glMatrixMode( GL_TEXTURE
);
905 glMatrixMode( GL_MODELVIEW
);
909 void Landscape::drawGraphicalReflectionMap()
911 GLState
state(GLState::TEXTURE_ON
);
913 glColor3f( 1.f
, 1.f
, 1.f
);
914 glMatrixMode(GL_PROJECTION
);
917 gluOrtho2D(0, 800, 0, 600);
918 glMatrixMode(GL_TEXTURE
);
921 glMatrixMode(GL_MODELVIEW
);
924 water_
->getReflectionTexture().draw(true);
926 glTexCoord2f(0.f
, 0.f
);
928 glTexCoord2f(1.f
, 0.f
);
930 glTexCoord2f(1.f
, 1.f
);
931 glVertex2i (300, 300);
932 glTexCoord2f(0.f
, 1.f
);
935 glMatrixMode(GL_PROJECTION
);
937 glMatrixMode( GL_TEXTURE
);
939 glMatrixMode( GL_MODELVIEW
);
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(
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_
;
986 return *cameraContexts_
[1].shadowMap_
;