1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #include "Rendering/GL/myGL.h"
4 
5 
6 #include "WorldDrawer.h"
7 #include "Rendering/Env/CubeMapHandler.h"
8 #include "Rendering/Env/GrassDrawer.h"
9 #include "Rendering/Env/IGroundDecalDrawer.h"
10 #include "Rendering/Env/ISky.h"
11 #include "Rendering/Env/ITreeDrawer.h"
12 #include "Rendering/Env/IWater.h"
13 #include "Rendering/DebugColVolDrawer.h"
14 #include "Rendering/FarTextureHandler.h"
15 #include "Rendering/LineDrawer.h"
16 #include "Rendering/FeatureDrawer.h"
17 #include "Rendering/ProjectileDrawer.h"
18 #include "Rendering/UnitDrawer.h"
19 #include "Rendering/IPathDrawer.h"
20 #include "Rendering/SmoothHeightMeshDrawer.h"
21 #include "Rendering/InMapDrawView.h"
22 #include "Rendering/ShadowHandler.h"
23 #include "Rendering/Models/ModelDrawer.h"
24 #include "Lua/LuaUnsyncedCtrl.h"
25 #include "Map/BaseGroundDrawer.h"
26 #include "Map/HeightMapTexture.h"
27 #include "Map/MapInfo.h"
28 #include "Map/ReadMap.h"
29 #include "Game/Camera.h"
30 #include "Game/SelectedUnitsHandler.h"
31 #include "Game/Game.h"
32 #include "Game/LoadScreen.h"
33 #include "Game/UI/UnitTracker.h"
34 #include "Game/UI/CommandColors.h"
35 #include "Game/UI/GuiHandler.h"
36 #include "System/EventHandler.h"
37 #include "System/TimeProfiler.h"
38 #include "System/Util.h"
39 
40 
CWorldDrawer()41 CWorldDrawer::CWorldDrawer()
42 {
43 	// rendering components
44 	loadscreen->SetLoadMessage("Creating ShadowHandler & DecalHandler");
45 	cubeMapHandler = new CubeMapHandler();
46 	shadowHandler = new CShadowHandler();
47 
48 	loadscreen->SetLoadMessage("Creating GroundDrawer");
49 	readMap->NewGroundDrawer();
50 
51 	loadscreen->SetLoadMessage("Creating TreeDrawer");
52 	treeDrawer = ITreeDrawer::GetTreeDrawer();
53 	grassDrawer = new CGrassDrawer();
54 
55 	inMapDrawerView = new CInMapDrawView();
56 	pathDrawer = IPathDrawer::GetInstance();
57 
58 	farTextureHandler = new CFarTextureHandler();
59 	heightMapTexture = new HeightMapTexture();
60 
61 	loadscreen->SetLoadMessage("Creating ProjectileDrawer & UnitDrawer");
62 	projectileDrawer = new CProjectileDrawer();
63 	projectileDrawer->LoadWeaponTextures();
64 	unitDrawer = new CUnitDrawer();
65 	// FIXME: see CGame::LoadSimulation (we only delete it)
66 	// featureDrawer = new CFeatureDrawer();
67 	modelDrawer = IModelDrawer::GetInstance();
68 
69 	loadscreen->SetLoadMessage("Creating Water");
70 	water = IWater::GetWater(NULL, -1);
71 }
72 
73 
~CWorldDrawer()74 CWorldDrawer::~CWorldDrawer()
75 {
76 	SafeDelete(water);
77 	SafeDelete(sky);
78 	SafeDelete(treeDrawer);
79 	SafeDelete(grassDrawer);
80 	SafeDelete(pathDrawer);
81 	SafeDelete(modelDrawer);
82 	SafeDelete(shadowHandler);
83 	SafeDelete(inMapDrawerView);
84 
85 	SafeDelete(featureDrawer);
86 	SafeDelete(unitDrawer); // depends on unitHandler, cubeMapHandler
87 	SafeDelete(projectileDrawer);
88 
89 	SafeDelete(farTextureHandler);
90 	SafeDelete(heightMapTexture);
91 
92 	SafeDelete(cubeMapHandler);
93 	IGroundDecalDrawer::FreeInstance();
94 }
95 
96 
Update()97 void CWorldDrawer::Update()
98 {
99 	readMap->UpdateDraw();
100 	if (globalRendering->drawGround) {
101 		SCOPED_TIMER("GroundDrawer::Update");
102 		CBaseGroundDrawer* gd = readMap->GetGroundDrawer();
103 		gd->Update();
104 	}
105 	//XXX: do in CGame, cause it needs to get updated even when doDrawWorld==false, cause it updates unitdrawpos which is used for maximized minimap too
106 	//unitDrawer->Update();
107 	//lineDrawer.UpdateLineStipple();
108 	treeDrawer->Update();
109 	featureDrawer->Update();
110 	IWater::ApplyPushedChanges(game);
111 }
112 
113 
Draw()114 void CWorldDrawer::Draw()
115 {
116 	SCOPED_TIMER("WorldDrawer::Total");
117 
118 	CBaseGroundDrawer* gd = readMap->GetGroundDrawer();
119 
120 	if (globalRendering->drawSky) {
121 		sky->Draw();
122 	}
123 
124 	if (globalRendering->drawGround) {
125 		{
126 			SCOPED_TIMER("WorldDrawer::Terrain");
127 			gd->Draw(DrawPass::Normal);
128 		}
129 		{
130 			SCOPED_TIMER("WorldDrawer::GroundDecals");
131 			groundDecals->Draw();
132 			projectileDrawer->DrawGroundFlashes();
133 		}
134 		{
135 			SCOPED_TIMER("WorldDrawer::Foliage");
136 			grassDrawer->Draw();
137 			gd->DrawTrees();
138 		}
139 		smoothHeightMeshDrawer->Draw(1.0f);
140 	}
141 
142 	if (globalRendering->drawWater && !mapInfo->map.voidWater) {
143 		SCOPED_TIMER("WorldDrawer::Water");
144 
145 		water->OcclusionQuery();
146 		if (water->DrawSolid()) {
147 			water->UpdateWater(game);
148 			water->Draw();
149 		}
150 	}
151 
152 	selectedUnitsHandler.Draw();
153 	eventHandler.DrawWorldPreUnit();
154 
155 	{
156 		SCOPED_TIMER("WorldDrawer::Models");
157 		unitDrawer->Draw(false);
158 		modelDrawer->Draw();
159 		featureDrawer->Draw();
160 		DebugColVolDrawer::Draw();
161 
162 		pathDrawer->DrawAll();
163 	}
164 
165 	//! transparent stuff
166 	glEnable(GL_BLEND);
167 	glDepthFunc(GL_LEQUAL);
168 
169 	static const double plane_below[4] = {0.0f, -1.0f, 0.0f, 0.0f};
170 	static const double plane_above[4] = {0.0f,  1.0f, 0.0f, 0.0f};
171 
172 	{
173 		glClipPlane(GL_CLIP_PLANE3, plane_below);
174 		glEnable(GL_CLIP_PLANE3);
175 
176 		//! draw cloaked objects below water surface
177 		unitDrawer->DrawCloakedUnits(shadowHandler->shadowsLoaded);
178 		featureDrawer->DrawFadeFeatures(shadowHandler->shadowsLoaded);
179 
180 		glDisable(GL_CLIP_PLANE3);
181 	}
182 
183 	//! draw water
184 	if (globalRendering->drawWater && !mapInfo->map.voidWater) {
185 		SCOPED_TIMER("WorldDrawer::Water");
186 
187 		if (!water->DrawSolid()) {
188 			//! Water rendering will overwrite features, so save them
189 			featureDrawer->SwapFeatures();
190 			water->UpdateWater(game);
191 			water->Draw();
192 			featureDrawer->SwapFeatures();
193 		}
194 	}
195 
196 	{
197 		glClipPlane(GL_CLIP_PLANE3, plane_above);
198 		glEnable(GL_CLIP_PLANE3);
199 
200 		//! draw cloaked objects above water surface
201 		unitDrawer->DrawCloakedUnits(shadowHandler->shadowsLoaded);
202 		featureDrawer->DrawFadeFeatures(shadowHandler->shadowsLoaded);
203 
204 		glDisable(GL_CLIP_PLANE3);
205 	}
206 
207 	{
208 		SCOPED_TIMER("WorldDrawer::Projectiles");
209 		projectileDrawer->Draw(false);
210 	}
211 
212 	if (globalRendering->drawSky) {
213 		sky->DrawSun();
214 	}
215 
216 	eventHandler.DrawWorld();
217 
218 	LuaUnsyncedCtrl::DrawUnitCommandQueues();
219 	if (cmdColors.AlwaysDrawQueue() || guihandler->GetQueueKeystate()) {
220 		selectedUnitsHandler.DrawCommands();
221 	}
222 
223 	lineDrawer.DrawAll();
224 	cursorIcons.Draw();
225 	cursorIcons.Clear();
226 
227 	mouse->DrawSelectionBox();
228 
229 	guihandler->DrawMapStuff(false);
230 
231 	if (globalRendering->drawMapMarks && !game->hideInterface) {
232 		inMapDrawerView->Draw();
233 	}
234 
235 
236 	//! underwater overlay
237 	if (camera->GetPos().y < 0.0f && globalRendering->drawWater && !mapInfo->map.voidWater) {
238 		glEnableClientState(GL_VERTEX_ARRAY);
239 		const float3& cpos = camera->GetPos();
240 		const float vr = globalRendering->viewRange * 0.5f;
241 		glDepthMask(GL_FALSE);
242 		glDisable(GL_TEXTURE_2D);
243 		glColor4f(0.0f, 0.5f, 0.3f, 0.50f);
244 		{
245 			float3 verts[] = {
246 				float3(cpos.x - vr, 0.0f, cpos.z - vr),
247 				float3(cpos.x - vr, 0.0f, cpos.z + vr),
248 				float3(cpos.x + vr, 0.0f, cpos.z + vr),
249 				float3(cpos.x + vr, 0.0f, cpos.z - vr)
250 			};
251 			glVertexPointer(3, GL_FLOAT, 0, verts);
252 			glDrawArrays(GL_QUADS, 0, 4);
253 		}
254 
255 		{
256 			float3 verts[] = {
257 				float3(cpos.x - vr, 0.0f, cpos.z - vr),
258 				float3(cpos.x - vr,  -vr, cpos.z - vr),
259 				float3(cpos.x - vr, 0.0f, cpos.z + vr),
260 				float3(cpos.x - vr,  -vr, cpos.z + vr),
261 				float3(cpos.x + vr, 0.0f, cpos.z + vr),
262 				float3(cpos.x + vr,  -vr, cpos.z + vr),
263 				float3(cpos.x + vr, 0.0f, cpos.z - vr),
264 				float3(cpos.x + vr,  -vr, cpos.z - vr),
265 				float3(cpos.x - vr, 0.0f, cpos.z - vr),
266 				float3(cpos.x - vr,  -vr, cpos.z - vr),
267 			};
268 			glVertexPointer(3, GL_FLOAT, 0, verts);
269 			glDrawArrays(GL_QUAD_STRIP, 0, 10);
270 		}
271 
272 		glDepthMask(GL_TRUE);
273 		glDisableClientState(GL_VERTEX_ARRAY);
274 	}
275 
276 	//reset fov
277 	glMatrixMode(GL_PROJECTION);
278 	glLoadIdentity();
279 	gluOrtho2D(0,1,0,1);
280 	glMatrixMode(GL_MODELVIEW);
281 	glLoadIdentity();
282 
283 	glEnable(GL_BLEND);
284 	glDisable(GL_DEPTH_TEST);
285 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
286 
287 	// underwater overlay, part 2
288 	if (camera->GetPos().y < 0.0f && globalRendering->drawWater && !mapInfo->map.voidWater) {
289 		glEnableClientState(GL_VERTEX_ARRAY);
290 		glDisable(GL_TEXTURE_2D);
291 		glColor4f(0.0f, 0.2f, 0.8f, 0.333f);
292 		float3 verts[] = {
293 			float3 (0.f, 0.f, -1.f),
294 			float3 (1.f, 0.f, -1.f),
295 			float3 (1.f, 1.f, -1.f),
296 			float3 (0.f, 1.f, -1.f),
297 		};
298 		glVertexPointer(3, GL_FLOAT, 0, verts);
299 		glDrawArrays(GL_QUADS, 0, 4);
300 		glDisableClientState(GL_VERTEX_ARRAY);
301 	}
302 }
303