3 Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "drawscene.h"
23 #include "clientmap.h"
24 #include "util/timetaker.h"
25 #include "fontengine.h"
26 #include "guiscalingfilter.h"
34 void draw_anaglyph_3d_mode(Camera& camera, bool show_hud, Hud& hud,
35 video::IVideoDriver* driver, scene::ISceneManager* smgr,
36 bool draw_wield_tool, Client& client,
37 gui::IGUIEnvironment* guienv )
40 /* preserve old setup*/
41 irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
42 irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
44 irr::core::matrix4 startMatrix =
45 camera.getCameraNode()->getAbsoluteTransformation();
46 irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
47 - camera.getCameraNode()->getAbsolutePosition()).setLength(1)
48 + camera.getCameraNode()->getAbsolutePosition();
52 irr::core::vector3df leftEye;
53 irr::core::matrix4 leftMove;
54 leftMove.setTranslation(
55 irr::core::vector3df(-g_settings->getFloat("3d_paralax_strength"),
57 leftEye = (startMatrix * leftMove).getTranslation();
59 //clear the depth buffer, and color
60 driver->beginScene( true, true, irr::video::SColor(0, 200, 200, 255));
61 driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_RED;
62 driver->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
63 driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX
64 + irr::scene::ESNRP_SOLID + irr::scene::ESNRP_TRANSPARENT
65 + irr::scene::ESNRP_TRANSPARENT_EFFECT + irr::scene::ESNRP_SHADOW;
66 camera.getCameraNode()->setPosition(leftEye);
67 camera.getCameraNode()->setTarget(focusPoint);
69 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
71 hud.drawSelectionMesh();
73 camera.drawWieldedTool(&leftMove);
79 irr::core::vector3df rightEye;
80 irr::core::matrix4 rightMove;
81 rightMove.setTranslation(
82 irr::core::vector3df(g_settings->getFloat("3d_paralax_strength"),
84 rightEye = (startMatrix * rightMove).getTranslation();
86 //clear the depth buffer
87 driver->clearZBuffer();
88 driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_GREEN
89 + irr::video::ECP_BLUE;
90 driver->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
91 driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX
92 + irr::scene::ESNRP_SOLID + irr::scene::ESNRP_TRANSPARENT
93 + irr::scene::ESNRP_TRANSPARENT_EFFECT + irr::scene::ESNRP_SHADOW;
94 camera.getCameraNode()->setPosition(rightEye);
95 camera.getCameraNode()->setTarget(focusPoint);
97 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
99 hud.drawSelectionMesh();
101 camera.drawWieldedTool(&rightMove);
106 driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_ALL;
107 driver->getOverrideMaterial().EnableFlags = 0;
108 driver->getOverrideMaterial().EnablePasses = 0;
109 camera.getCameraNode()->setPosition(oldPosition);
110 camera.getCameraNode()->setTarget(oldTarget);
113 void init_texture(video::IVideoDriver* driver, const v2u32& screensize,
114 video::ITexture** texture, const char* name)
116 if (*texture != NULL)
118 driver->removeTexture(*texture);
120 *texture = driver->addRenderTargetTexture(
121 core::dimension2d<u32>(screensize.X, screensize.Y), name,
122 irr::video::ECF_A8R8G8B8);
125 video::ITexture* draw_image(const v2u32 &screensize,
126 paralax_sign psign, const irr::core::matrix4 &startMatrix,
127 const irr::core::vector3df &focusPoint, bool show_hud,
128 video::IVideoDriver *driver, Camera &camera, scene::ISceneManager *smgr,
129 Hud &hud, bool draw_wield_tool, Client &client,
130 gui::IGUIEnvironment *guienv, const video::SColor &skycolor)
132 static video::ITexture* images[2] = { NULL, NULL };
133 static v2u32 last_screensize = v2u32(0, 0);
135 video::ITexture* image = NULL;
137 if (screensize != last_screensize) {
138 init_texture(driver, screensize, &images[1], "mt_drawimage_img1");
139 init_texture(driver, screensize, &images[0], "mt_drawimage_img2");
140 last_screensize = screensize;
148 driver->setRenderTarget(image, true, true,
149 irr::video::SColor(255,
150 skycolor.getRed(), skycolor.getGreen(), skycolor.getBlue()));
152 irr::core::vector3df eye_pos;
153 irr::core::matrix4 movement;
154 movement.setTranslation(
155 irr::core::vector3df((int) psign *
156 g_settings->getFloat("3d_paralax_strength"), 0.0f, 0.0f));
157 eye_pos = (startMatrix * movement).getTranslation();
159 //clear the depth buffer
160 driver->clearZBuffer();
161 camera.getCameraNode()->setPosition(eye_pos);
162 camera.getCameraNode()->setTarget(focusPoint);
165 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
168 hud.drawSelectionMesh();
170 camera.drawWieldedTool(&movement);
175 /* switch back to real renderer */
176 driver->setRenderTarget(0, true, true,
177 irr::video::SColor(0,
178 skycolor.getRed(), skycolor.getGreen(), skycolor.getBlue()));
183 video::ITexture* draw_hud(video::IVideoDriver* driver, const v2u32& screensize,
184 bool show_hud, Hud& hud, Client& client, bool draw_crosshair,
185 video::SColor skycolor, gui::IGUIEnvironment* guienv, Camera& camera )
187 static video::ITexture* image = NULL;
188 init_texture(driver, screensize, &image, "mt_drawimage_hud");
189 driver->setRenderTarget(image, true, true,
190 irr::video::SColor(255,0,0,0));
196 hud.drawHotbar(client.getPlayerItem());
197 hud.drawLuaElements(camera.getOffset());
198 camera.drawNametags();
202 driver->setRenderTarget(0, true, true,
203 irr::video::SColor(0,
204 skycolor.getRed(), skycolor.getGreen(), skycolor.getBlue()));
209 void draw_interlaced_3d_mode(Camera& camera, bool show_hud,
210 Hud& hud, video::IVideoDriver* driver,
211 scene::ISceneManager* smgr, const v2u32& screensize,
212 bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
213 video::SColor skycolor )
215 /* save current info */
216 irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
217 irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
218 irr::core::matrix4 startMatrix =
219 camera.getCameraNode()->getAbsoluteTransformation();
220 irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
221 - camera.getCameraNode()->getAbsolutePosition()).setLength(1)
222 + camera.getCameraNode()->getAbsolutePosition();
224 /* create left view */
225 video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
226 focusPoint, show_hud, driver, camera, smgr, hud,
227 draw_wield_tool, client, guienv, skycolor);
230 irr::core::vector3df rightEye;
231 irr::core::matrix4 rightMove;
232 rightMove.setTranslation(
233 irr::core::vector3df(g_settings->getFloat("3d_paralax_strength"),
235 rightEye = (startMatrix * rightMove).getTranslation();
237 //clear the depth buffer
238 driver->clearZBuffer();
239 camera.getCameraNode()->setPosition(rightEye);
240 camera.getCameraNode()->setTarget(focusPoint);
243 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
246 hud.drawSelectionMesh();
248 camera.drawWieldedTool(&rightMove);
252 for (unsigned int i = 0; i < screensize.Y; i+=2 ) {
253 #if (IRRLICHT_VERSION_MAJOR >= 1) && (IRRLICHT_VERSION_MINOR >= 8)
254 driver->draw2DImage(left_image, irr::core::position2d<s32>(0, i),
256 driver->draw2DImage(left_image, irr::core::position2d<s32>(0, screensize.Y-i),
258 irr::core::rect<s32>(0, i,screensize.X, i+1), 0,
259 irr::video::SColor(255, 255, 255, 255),
264 camera.getCameraNode()->setPosition(oldPosition);
265 camera.getCameraNode()->setTarget(oldTarget);
268 void draw_sidebyside_3d_mode(Camera& camera, bool show_hud,
269 Hud& hud, video::IVideoDriver* driver,
270 scene::ISceneManager* smgr, const v2u32& screensize,
271 bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
272 video::SColor skycolor )
274 /* save current info */
275 irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
276 irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
277 irr::core::matrix4 startMatrix =
278 camera.getCameraNode()->getAbsoluteTransformation();
279 irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
280 - camera.getCameraNode()->getAbsolutePosition()).setLength(1)
281 + camera.getCameraNode()->getAbsolutePosition();
283 /* create left view */
284 video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
285 focusPoint, show_hud, driver, camera, smgr, hud,
286 draw_wield_tool, client, guienv, skycolor);
288 /* create right view */
289 video::ITexture* right_image = draw_image(screensize, RIGHT, startMatrix,
290 focusPoint, show_hud, driver, camera, smgr, hud,
291 draw_wield_tool, client, guienv, skycolor);
293 /* create hud overlay */
294 video::ITexture* hudtexture = draw_hud(driver, screensize, show_hud, hud, client,
295 false, skycolor, guienv, camera );
296 driver->makeColorKeyTexture(hudtexture, irr::video::SColor(255, 0, 0, 0));
297 //makeColorKeyTexture mirrors texture so we do it twice to get it right again
298 driver->makeColorKeyTexture(hudtexture, irr::video::SColor(255, 0, 0, 0));
300 draw2DImageFilterScaled(driver, left_image,
301 irr::core::rect<s32>(0, 0, screensize.X/2, screensize.Y),
302 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, false);
304 draw2DImageFilterScaled(driver, hudtexture,
305 irr::core::rect<s32>(0, 0, screensize.X/2, screensize.Y),
306 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, true);
308 draw2DImageFilterScaled(driver, right_image,
309 irr::core::rect<s32>(screensize.X/2, 0, screensize.X, screensize.Y),
310 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, false);
312 draw2DImageFilterScaled(driver, hudtexture,
313 irr::core::rect<s32>(screensize.X/2, 0, screensize.X, screensize.Y),
314 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, true);
320 camera.getCameraNode()->setPosition(oldPosition);
321 camera.getCameraNode()->setTarget(oldTarget);
324 void draw_top_bottom_3d_mode(Camera& camera, bool show_hud,
325 Hud& hud, video::IVideoDriver* driver,
326 scene::ISceneManager* smgr, const v2u32& screensize,
327 bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
328 video::SColor skycolor )
330 /* save current info */
331 irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
332 irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
333 irr::core::matrix4 startMatrix =
334 camera.getCameraNode()->getAbsoluteTransformation();
335 irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
336 - camera.getCameraNode()->getAbsolutePosition()).setLength(1)
337 + camera.getCameraNode()->getAbsolutePosition();
339 /* create left view */
340 video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
341 focusPoint, show_hud, driver, camera, smgr, hud,
342 draw_wield_tool, client, guienv, skycolor);
344 /* create right view */
345 video::ITexture* right_image = draw_image(screensize, RIGHT, startMatrix,
346 focusPoint, show_hud, driver, camera, smgr, hud,
347 draw_wield_tool, client, guienv, skycolor);
349 /* create hud overlay */
350 video::ITexture* hudtexture = draw_hud(driver, screensize, show_hud, hud, client,
351 false, skycolor, guienv, camera );
352 driver->makeColorKeyTexture(hudtexture, irr::video::SColor(255, 0, 0, 0));
353 //makeColorKeyTexture mirrors texture so we do it twice to get it right again
354 driver->makeColorKeyTexture(hudtexture, irr::video::SColor(255, 0, 0, 0));
356 draw2DImageFilterScaled(driver, left_image,
357 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y/2),
358 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, false);
360 draw2DImageFilterScaled(driver, hudtexture,
361 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y/2),
362 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, true);
364 draw2DImageFilterScaled(driver, right_image,
365 irr::core::rect<s32>(0, screensize.Y/2, screensize.X, screensize.Y),
366 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, false);
368 draw2DImageFilterScaled(driver, hudtexture,
369 irr::core::rect<s32>(0, screensize.Y/2, screensize.X, screensize.Y),
370 irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, true);
376 camera.getCameraNode()->setPosition(oldPosition);
377 camera.getCameraNode()->setTarget(oldTarget);
380 void draw_pageflip_3d_mode(Camera& camera, bool show_hud,
381 Hud& hud, video::IVideoDriver* driver,
382 scene::ISceneManager* smgr, const v2u32& screensize,
383 bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
384 video::SColor skycolor)
386 #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8
387 errorstream << "Pageflip 3D mode is not supported"
388 << " with your Irrlicht version!" << std::endl;
390 /* preserve old setup*/
391 irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
392 irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
394 irr::core::matrix4 startMatrix =
395 camera.getCameraNode()->getAbsoluteTransformation();
396 irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
397 - camera.getCameraNode()->getAbsolutePosition()).setLength(1)
398 + camera.getCameraNode()->getAbsolutePosition();
401 driver->setRenderTarget(irr::video::ERT_STEREO_LEFT_BUFFER);
403 irr::core::vector3df leftEye;
404 irr::core::matrix4 leftMove;
405 leftMove.setTranslation(
406 irr::core::vector3df(-g_settings->getFloat("3d_paralax_strength"),
408 leftEye = (startMatrix * leftMove).getTranslation();
410 //clear the depth buffer, and color
411 driver->beginScene(true, true, irr::video::SColor(200, 200, 200, 255));
412 camera.getCameraNode()->setPosition(leftEye);
413 camera.getCameraNode()->setTarget(focusPoint);
415 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
418 hud.drawSelectionMesh();
420 camera.drawWieldedTool(&leftMove);
421 hud.drawHotbar(client.getPlayerItem());
422 hud.drawLuaElements(camera.getOffset());
423 camera.drawNametags();
429 driver->setRenderTarget(irr::video::ERT_STEREO_RIGHT_BUFFER);
431 irr::core::vector3df rightEye;
432 irr::core::matrix4 rightMove;
433 rightMove.setTranslation(
434 irr::core::vector3df(g_settings->getFloat("3d_paralax_strength"),
436 rightEye = (startMatrix * rightMove).getTranslation();
438 //clear the depth buffer, and color
439 driver->beginScene(true, true, irr::video::SColor(200, 200, 200, 255));
440 camera.getCameraNode()->setPosition(rightEye);
441 camera.getCameraNode()->setTarget(focusPoint);
443 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
446 hud.drawSelectionMesh();
448 camera.drawWieldedTool(&rightMove);
449 hud.drawHotbar(client.getPlayerItem());
450 hud.drawLuaElements(camera.getOffset());
451 camera.drawNametags();
456 camera.getCameraNode()->setPosition(oldPosition);
457 camera.getCameraNode()->setTarget(oldTarget);
461 void draw_plain(Camera &camera, bool show_hud, Hud &hud,
462 video::IVideoDriver *driver, bool draw_wield_tool,
463 Client &client, gui::IGUIEnvironment *guienv)
465 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
467 hud.drawSelectionMesh();
468 if (draw_wield_tool) {
469 camera.drawWieldedTool();
474 void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr,
475 Camera &camera, Client& client, LocalPlayer *player, Hud &hud,
476 Mapper &mapper, gui::IGUIEnvironment *guienv,
477 const v2u32 &screensize, const video::SColor &skycolor,
478 bool show_hud, bool show_minimap)
480 TimeTaker timer("smgr");
482 bool draw_wield_tool = (show_hud &&
483 (player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE) &&
484 camera.getCameraMode() < CAMERA_MODE_THIRD );
486 bool draw_crosshair = ((player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
487 (camera.getCameraMode() != CAMERA_MODE_THIRD_FRONT));
489 #ifdef HAVE_TOUCHSCREENGUI
491 draw_crosshair = !g_settings->getBool("touchtarget");
493 catch(SettingNotFoundException) {}
496 std::string draw_mode = g_settings->get("3d_mode");
500 if (draw_mode == "anaglyph")
502 draw_anaglyph_3d_mode(camera, show_hud, hud, driver,
503 smgr, draw_wield_tool, client, guienv);
504 draw_crosshair = false;
506 else if (draw_mode == "interlaced")
508 draw_interlaced_3d_mode(camera, show_hud, hud, driver,
509 smgr, screensize, draw_wield_tool, client, guienv, skycolor);
510 draw_crosshair = false;
512 else if (draw_mode == "sidebyside")
514 draw_sidebyside_3d_mode(camera, show_hud, hud, driver,
515 smgr, screensize, draw_wield_tool, client, guienv, skycolor);
518 else if (draw_mode == "topbottom")
520 draw_top_bottom_3d_mode(camera, show_hud, hud, driver,
521 smgr, screensize, draw_wield_tool, client, guienv, skycolor);
524 else if (draw_mode == "pageflip")
526 draw_pageflip_3d_mode(camera, show_hud, hud, driver,
527 smgr, screensize, draw_wield_tool, client, guienv, skycolor);
528 draw_crosshair = false;
532 draw_plain(camera, show_hud, hud, driver,
533 draw_wield_tool, client, guienv);
540 client.getEnv().getClientMap().renderPostFx(camera.getCameraMode());
543 //TODO how to make those 3d too
549 hud.drawHotbar(client.getPlayerItem());
550 hud.drawLuaElements(camera.getOffset());
551 camera.drawNametags();
554 mapper.drawMinimap();
563 Draws a screen with a single text on it.
564 Text will be removed when the screen is drawn the next time.
565 Additionally, a progressbar can be drawn when percent is set between 0 and 100.
567 void draw_load_screen(const std::wstring &text, IrrlichtDevice* device,
568 gui::IGUIEnvironment* guienv, float dtime, int percent, bool clouds )
570 video::IVideoDriver* driver = device->getVideoDriver();
571 v2u32 screensize = porting::getWindowSize();
573 v2s32 textsize(g_fontengine->getTextWidth(text), g_fontengine->getLineHeight());
574 v2s32 center(screensize.X / 2, screensize.Y / 2);
575 core::rect<s32> textrect(center - textsize / 2, center + textsize / 2);
577 gui::IGUIStaticText *guitext = guienv->addStaticText(
578 text.c_str(), textrect, false, false);
579 guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
581 bool cloud_menu_background = clouds && g_settings->getBool("menu_clouds");
582 if (cloud_menu_background)
584 g_menuclouds->step(dtime*3);
585 g_menuclouds->render();
586 driver->beginScene(true, true, video::SColor(255, 140, 186, 250));
587 g_menucloudsmgr->drawAll();
590 driver->beginScene(true, true, video::SColor(255, 0, 0, 0));
593 if ((percent >= 0) && (percent <= 100))
596 // 342 is (approximately) 256/0.75 to keep bar on same size as
597 // before with default settings
598 342 * porting::getDisplayDensity() *
599 g_settings->getFloat("gui_scaling"),
600 g_fontengine->getTextHeight() * 2);
602 core::rect<s32> barrect(center - barsize / 2, center + barsize / 2);
603 driver->draw2DRectangle(video::SColor(255, 255, 255, 255),barrect, NULL); // border
604 driver->draw2DRectangle(video::SColor(255, 64, 64, 64), core::rect<s32> (
605 barrect.UpperLeftCorner + 1,
606 barrect.LowerRightCorner-1), NULL); // black inside the bar
607 driver->draw2DRectangle(video::SColor(255, 128, 128, 128), core::rect<s32> (
608 barrect.UpperLeftCorner + 1,
610 barrect.LowerRightCorner.X -
611 (barsize.X - 1) + percent * (barsize.X - 2) / 100,
612 barrect.LowerRightCorner.Y - 1)), NULL); // the actual progress