]> git.lizzy.rs Git - minetest.git/blob - src/client/camera.h
Add setting to mirror hands
[minetest.git] / src / client / camera.h
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #pragma once
21
22 #include "irrlichttypes_extrabloated.h"
23 #include "inventory.h"
24 #include "client/tile.h"
25 #include <ICameraSceneNode.h>
26 #include <ISceneNode.h>
27 #include <plane3d.h>
28 #include <array>
29 #include <list>
30 #include "util/Optional.h"
31
32 class LocalPlayer;
33 struct MapDrawControl;
34 class Client;
35 class RenderingEngine;
36 class WieldMeshSceneNode;
37
38 struct Nametag
39 {
40         scene::ISceneNode *parent_node;
41         std::string text;
42         video::SColor textcolor;
43         Optional<video::SColor> bgcolor;
44         v3f pos;
45
46         Nametag(scene::ISceneNode *a_parent_node,
47                         const std::string &text,
48                         const video::SColor &textcolor,
49                         const Optional<video::SColor> &bgcolor,
50                         const v3f &pos):
51                 parent_node(a_parent_node),
52                 text(text),
53                 textcolor(textcolor),
54                 bgcolor(bgcolor),
55                 pos(pos)
56         {
57         }
58
59         video::SColor getBgColor(bool use_fallback) const
60         {
61                 if (bgcolor)
62                         return bgcolor.value();
63                 else if (!use_fallback)
64                         return video::SColor(0, 0, 0, 0);
65                 else if (textcolor.getLuminance() > 186)
66                         // Dark background for light text
67                         return video::SColor(50, 50, 50, 50);
68                 else
69                         // Light background for dark text
70                         return video::SColor(50, 255, 255, 255);
71         }
72 };
73
74 enum HandIndex { MAINHAND = 0, OFFHAND = 1 };
75
76 class WieldNode
77 {
78 public:
79         WieldNode(HandIndex index, Client *client, scene::ISceneManager *mgr);
80         int getDirection();
81         void step(f32 dtime);
82         void addArmInertia(f32 player_yaw, v3f camera_direction);
83         void update(video::SColor player_light_color, f32 view_bobbing_anim, f32 tool_reload_ratio);
84         void setDigging(s32 button);
85         void wield(const ItemStack &item);
86
87 private:
88         HandIndex m_index;
89         int m_direction;
90
91         Client *m_client;
92         WieldMeshSceneNode *m_meshnode = nullptr;
93
94         // Digging animation frame (0 <= m_digging_anim < 1)
95         f32 m_digging_anim = 0.0f;
96
97         // If -1, no digging animation
98         // If 0, left-click digging animation
99         // If 1, right-click digging animation
100         s32 m_digging_button = -1;
101
102         // Animation when changing wielded item
103         f32 m_change_timer = 0.125f;
104         ItemStack m_item_next;
105         bool m_item_old = false;
106
107         // Last known light color of the player
108         video::SColor m_player_light_color;
109
110         // Arm inertia
111         v2f m_offset = v2f(55.0f, -35.0f);
112         v2f m_arm_dir;
113         v2f m_cam_vel;
114         v2f m_cam_vel_old;
115         v2f m_last_cam_pos;
116 };
117
118 enum CameraMode {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT};
119
120 /*
121         Client camera class, manages the player and camera scene nodes, the viewing distance
122         and performs view bobbing etc. It also displays the wielded tool in front of the
123         first-person camera.
124 */
125 class Camera
126 {
127 public:
128         Camera(MapDrawControl &draw_control, Client *client, RenderingEngine *rendering_engine);
129         ~Camera();
130
131         // Get camera scene node.
132         // It has the eye transformation, pitch and view bobbing applied.
133         inline scene::ICameraSceneNode* getCameraNode() const
134         {
135                 return m_cameranode;
136         }
137
138         // Get the camera position (in absolute scene coordinates).
139         // This has view bobbing applied.
140         inline v3f getPosition() const
141         {
142                 return m_camera_position;
143         }
144
145         // Returns the absolute position of the head SceneNode in the world
146         inline v3f getHeadPosition() const
147         {
148                 return m_headnode->getAbsolutePosition();
149         }
150
151         // Get the camera direction (in absolute camera coordinates).
152         // This has view bobbing applied.
153         inline v3f getDirection() const
154         {
155                 return m_camera_direction;
156         }
157
158         // Get the camera offset
159         inline v3s16 getOffset() const
160         {
161                 return m_camera_offset;
162         }
163
164         // Horizontal field of view
165         inline f32 getFovX() const
166         {
167                 return m_fov_x;
168         }
169
170         // Vertical field of view
171         inline f32 getFovY() const
172         {
173                 return m_fov_y;
174         }
175
176         // Get maximum of getFovX() and getFovY()
177         inline f32 getFovMax() const
178         {
179                 return MYMAX(m_fov_x, m_fov_y);
180         }
181
182         // Returns a lambda that when called with an object's position and bounding-sphere
183         // radius (both in BS space) returns true if, and only if the object should be
184         // frustum-culled.
185         auto getFrustumCuller() const
186         {
187                 return [planes = getFrustumCullPlanes(),
188                                 camera_offset = intToFloat(m_camera_offset, BS)
189                                 ](v3f position, f32 radius) {
190                         v3f pos_camspace = position - camera_offset;
191                         for (auto &plane : planes) {
192                                 if (plane.getDistanceTo(pos_camspace) > radius)
193                                         return true;
194                         }
195                         return false;
196                 };
197         }
198
199         // Notify about new server-sent FOV and initialize smooth FOV transition
200         void notifyFovChange();
201
202         // Step the camera: updates the viewing range and view bobbing.
203         void step(f32 dtime);
204
205         // Update the camera from the local player's position.
206         void update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio);
207
208         // Update render distance
209         void updateViewingRange();
210
211         // Start digging animation
212         // button: Pass 0 for left click, 1 for right click
213         void setDigging(s32 button, HandIndex hand);
214
215         // Replace the wielded item mesh
216         void wield(const ItemStack &item, HandIndex hand);
217
218         // Draw the wielded tool.
219         // This has to happen *after* the main scene is drawn.
220         // Warning: This clears the Z buffer.
221         void drawWieldedTool(irr::core::matrix4* translation=NULL);
222
223         // Toggle the current camera mode
224         void toggleCameraMode() {
225                 if (m_camera_mode == CAMERA_MODE_FIRST)
226                         m_camera_mode = CAMERA_MODE_THIRD;
227                 else if (m_camera_mode == CAMERA_MODE_THIRD)
228                         m_camera_mode = CAMERA_MODE_THIRD_FRONT;
229                 else
230                         m_camera_mode = CAMERA_MODE_FIRST;
231         }
232
233         // Set the current camera mode
234         inline void setCameraMode(CameraMode mode)
235         {
236                 m_camera_mode = mode;
237         }
238
239         //read the current camera mode
240         inline CameraMode getCameraMode()
241         {
242                 return m_camera_mode;
243         }
244
245         Nametag *addNametag(scene::ISceneNode *parent_node,
246                 const std::string &text, video::SColor textcolor,
247                 Optional<video::SColor> bgcolor, const v3f &pos);
248
249         void removeNametag(Nametag *nametag);
250
251         void drawNametags();
252
253         inline void addArmInertia(f32 player_yaw);
254
255 private:
256         // Use getFrustumCuller().
257         // This helper just exists to decrease the header's number of includes.
258         std::array<core::plane3d<f32>, 4> getFrustumCullPlanes() const;
259
260         // Nodes
261         scene::ISceneNode *m_playernode = nullptr;
262         scene::ISceneNode *m_headnode = nullptr;
263         scene::ICameraSceneNode *m_cameranode = nullptr;
264
265         WieldNode *m_wieldnodes[2];
266
267         scene::ISceneManager *m_wieldmgr = nullptr;
268
269         // draw control
270         MapDrawControl& m_draw_control;
271
272         Client *m_client;
273
274         // Default Client FOV (as defined by the "fov" setting)
275         f32 m_cache_fov;
276
277         // Absolute camera position
278         v3f m_camera_position;
279         // Absolute camera direction
280         v3f m_camera_direction;
281         // Camera offset
282         v3s16 m_camera_offset;
283
284         bool m_stepheight_smooth_active = false;
285
286         // Server-sent FOV variables
287         bool m_server_sent_fov = false;
288         f32 m_curr_fov_degrees, m_old_fov_degrees, m_target_fov_degrees;
289
290         // FOV transition variables
291         bool m_fov_transition_active = false;
292         f32 m_fov_diff, m_transition_time;
293
294         // Field of view and aspect ratio stuff
295         f32 m_aspect = 1.0f;
296         f32 m_fov_x = 1.0f;
297         f32 m_fov_y = 1.0f;
298
299         // View bobbing animation frame (0 <= m_view_bobbing_anim < 1)
300         f32 m_view_bobbing_anim = 0.0f;
301         // If 0, view bobbing is off (e.g. player is standing).
302         // If 1, view bobbing is on (player is walking).
303         // If 2, view bobbing is getting switched off.
304         s32 m_view_bobbing_state = 0;
305         // Speed of view bobbing animation
306         f32 m_view_bobbing_speed = 0.0f;
307         // Fall view bobbing
308         f32 m_view_bobbing_fall = 0.0f;
309
310         CameraMode m_camera_mode = CAMERA_MODE_FIRST;
311
312         f32 m_cache_fall_bobbing_amount;
313         f32 m_cache_view_bobbing_amount;
314         bool m_arm_inertia;
315
316         std::list<Nametag *> m_nametags;
317         bool m_show_nametag_backgrounds;
318
319         // Last known light color of the player
320         video::SColor m_player_light_color;
321 };