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