File: Camera.h

package info (click to toggle)
spring 106.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 55,260 kB
  • sloc: cpp: 543,946; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (269 lines) | stat: -rw-r--r-- 8,644 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef _CAMERA_H
#define _CAMERA_H

#include "System/AABB.hpp"
#include "System/float3.h"
#include "System/Matrix44f.h"


class CCamera {
public:
	enum {
		CAMTYPE_PLAYER = 0, // main camera
		CAMTYPE_UWREFL = 1, // used for underwater reflections
		CAMTYPE_SHADOW = 2, // used for shadowmap generation
		CAMTYPE_ENVMAP = 3, // used for cubemap generation
		CAMTYPE_VISCUL = 4, // used for frustum culling
		CAMTYPE_ACTIVE = 5, // pointer to currently active camera
		CAMTYPE_COUNT  = 6,
	};

	enum {
		PROJTYPE_PERSP = 0,
		PROJTYPE_ORTHO = 1,
		PROJTYPE_COUNT = 2,
	};

	enum {
		FRUSTUM_PLANE_LFT = 0,
		FRUSTUM_PLANE_RGT = 1,
		FRUSTUM_PLANE_TOP = 2,
		FRUSTUM_PLANE_BOT = 3,
		FRUSTUM_PLANE_FRN = 4, // near
		FRUSTUM_PLANE_BCK = 5, // far
		FRUSTUM_PLANE_CNT = 6,
	};
	enum {
		FRUSTUM_SIDE_POS = 0,
		FRUSTUM_SIDE_NEG = 1,
	};

	enum {
		MOVE_STATE_FWD = 0, // forward
		MOVE_STATE_BCK = 1, // back
		MOVE_STATE_LFT = 2, // left
		MOVE_STATE_RGT = 3, // right
		MOVE_STATE_UP  = 4, // up
		MOVE_STATE_DWN = 5, // down
		MOVE_STATE_FST = 6, // fast
		MOVE_STATE_SLW = 7, // slow
	};

	struct Frustum {
	public:
		bool IntersectSphere(const float3& cp, const float4& sp) const;
		bool IntersectAABB(const AABB& b) const;

	public:
		// corners
		float3 verts[8];
		// normals
		float3 planes[FRUSTUM_PLANE_CNT];
		// ntr - ntl, ntl - nbl, ftl - ntl, ftr - ntr, fbr - nbr, fbl - nbl
		float3 edges[6];

		// xy-scales (for orthographic cameras only), .z := znear, .w := zfar
		float4 scales;
	};
	struct FrustumLine {
		int sign = 0;

		float base = 0.0f;
		float dir = 0.0f;

		float minz = 0.0f;
		float maxz = 0.0f;
	};

	struct UpdateParams {
		bool updateDirs;
		bool updateMats;
		bool updateFrustum;
		bool updateViewPort;
		bool updateViewRange;
	};

public:
	CCamera(unsigned int cameraType = CAMTYPE_PLAYER, unsigned int projectionType = PROJTYPE_PERSP);

	void CopyState(const CCamera*);
	void CopyStateReflect(const CCamera*);

	void Update(const UpdateParams& p);
	void Update(bool updateDirs = true, bool updateMats = true, bool updateViewPort = true, bool updateViewRange = true) {
		Update({updateDirs, updateMats, true, updateViewPort, updateViewRange});
	}

	/// @param fov in degree
	void SetPos(const float3& p) { pos = p; }
	void SetDir(const float3& dir);

	const float3& GetPos() const { return pos; }
	const float3& GetDir() const { return forward; }

	const float3& GetForward() const { return forward; }
	const float3& GetRight() const   { return right; }
	const float3& GetUp() const      { return up; }
	const float3& GetRot() const     { return rot; }

	void SetRot(const float3& r) { UpdateDirsFromRot(rot = r); }
	void SetRotX(const float x) { SetRot(float3(    x, rot.y, rot.z)); }
	void SetRotY(const float y) { SetRot(float3(rot.x,     y, rot.z)); }
	void SetRotZ(const float z) { SetRot(float3(rot.x, rot.y,     z)); }

	float3 CalcPixelDir(int x, int y) const;
	float3 CalcWindowCoordinates(const float3& objPos) const;

	bool InView(const float3& point, float radius = 0.0f) const { return (frustum.IntersectSphere(pos, {point, radius})); }
	bool InView(const float3& mins, const float3& maxs) const { return (InView(AABB{mins, maxs})); }
	bool InView(const AABB& aabb) const { return (InView(aabb.CalcCenter(), aabb.CalcRadius()) && frustum.IntersectAABB(aabb)); }

	void CalcFrustumLines(float miny, float maxy, float scale, bool neg = false);
	void CalcFrustumLine(
		const float3& normal,
		const float3& offset,
		const float3& params,
		unsigned int side
	);

	void ClipFrustumLines(const float zmin, const float zmax, bool neg);
	void SetFrustumScales(const float4 scales) { frustum.scales = scales; }

	const FrustumLine* GetPosFrustumLines() const { return &frustumLines[FRUSTUM_SIDE_POS][0]; }
	const FrustumLine* GetNegFrustumLines() const { return &frustumLines[FRUSTUM_SIDE_NEG][0]; }

	void SetClipCtrlMatrix(const CMatrix44f& mat) { clipControlMatrix = mat; }
	void SetProjMatrix(const CMatrix44f& mat) { projectionMatrix = mat; }
	void SetViewMatrix(const CMatrix44f& mat) {
		viewMatrix = mat;

		// FIXME: roll-angle might not be 0
		pos = viewMatrix.GetPos();
		rot = GetRotFromDir(viewMatrix.GetZ());

		forward = viewMatrix.GetZ();
		right   = viewMatrix.GetX();
		up      = viewMatrix.GetY();
	}

	const CMatrix44f& GetViewMatrix() const { return viewMatrix; }
	const CMatrix44f& GetViewMatrixInverse() const { return viewMatrixInverse; }
	const CMatrix44f& GetProjectionMatrix() const { return projectionMatrix; }
	const CMatrix44f& GetProjectionMatrixInverse() const { return projectionMatrixInverse; }
	const CMatrix44f& GetViewProjectionMatrix() const { return viewProjectionMatrix; }
	const CMatrix44f& GetViewProjectionMatrixInverse() const { return viewProjectionMatrixInverse; }
	const CMatrix44f& GetBillBoardMatrix() const { return billboardMatrix; }
	const CMatrix44f& GetClipControlMatrix() const { return clipControlMatrix; }

	const float3& GetFrustumVert (unsigned int i) const { return frustum.verts [i]; }
	const float3& GetFrustumPlane(unsigned int i) const { return frustum.planes[i]; }
	const float3& GetFrustumEdge (unsigned int i) const { return frustum.edges [i]; }

	void LoadViewPort() const;
	void UpdateLoadViewPort(int px, int py, int sx, int sy);

	void SetVFOV(float angle);
	void SetAspectRatio(float ar) { aspectRatio = ar; }

	float GetVFOV() const { return fov; }
	float GetHFOV() const;
	float GetHalfFov() const { return halfFov; }
	float GetTanHalfFov() const { return tanHalfFov; }
	float GetLPPScale() const { return lppScale; }
	float GetNearPlaneDist() const { return frustum.scales.z; }
	float GetFarPlaneDist() const { return frustum.scales.w; }
	float GetAspectRatio() const { return aspectRatio; }

	float3 GetMoveVectorFromState(bool fromKeyState) const;

	void SetMovState(int idx, bool b) { movState[idx] = b; }
	void SetRotState(int idx, bool b) { rotState[idx] = b; }
	const bool* GetMovState() const { return movState; }
	const bool* GetRotState() const { return rotState; }

	static CCamera* GetActive();

	static float3 GetRotFromDir(float3 fwd);
	static float3 GetFwdFromRot(const float3& r);
	static float3 GetRgtFromRot(const float3& r);


	float ProjectedDistance(const float3& objPos) const {
		return (forward.dot(objPos - pos));
	}

	/*
	float ProjectedDistanceShadow(const float3& objPos, const float3& sunDir) const {
		// FIXME: fix it, cap it for shallow shadows?
		const float3 diff = pos - objPos;
		const float  dot  = diff.dot(sunDir);
		const float3 gap  = diff - (sunDir * dot);
		return (gap.Length());
	}
	*/

	unsigned int GetCamType() const { return camType; }
	unsigned int GetProjType() const { return projType; }
	unsigned int SetCamType(unsigned int ct) { return (camType = ct); }
	unsigned int SetProjType(unsigned int pt) { return (projType = pt); }

public:
	void UpdateViewRange();
	void UpdateFrustum();
	void UpdateMatrices(unsigned int vsx, unsigned int vsy, float var);
	void UpdateViewPort(int px, int py, int sx, int sy);

private:
	void gluPerspectiveSpring(const float aspect, const float zn, const float zf);
	void glOrthoScaledSpring(const float sx, const float sy, const float zn, const float zf);
	void gluLookAtSpring(const float3&, const float3&, const float3&);

	void UpdateDirsFromRot(const float3& r);

public:
	float3 pos;
	float3 rot;                   ///< x = inclination, y = azimuth (to the -z axis!), z = roll
	float3 forward = FwdVector;   ///< local z-axis
	float3 right   = RgtVector;   ///< local x-axis
	float3 up      =  UpVector;   ///< local y-axis

	// Lua-controlled parameters, player-camera only
	float3 posOffset;
	float3 tiltOffset;

	float fov         = 0.0f;  ///< vertical viewing angle, in degrees
	float halfFov     = 0.0f;  ///< half the fov in radians
	float tanHalfFov  = 0.0f;  ///< math::tan(halfFov)
	float lppScale    = 0.0f;  ///< length-per-pixel scale
	float aspectRatio = 1.0f;  ///< horizontal

	int viewport[4];

private:
	CMatrix44f projectionMatrix;
	CMatrix44f projectionMatrixInverse;
	CMatrix44f viewMatrix;
	CMatrix44f viewMatrixInverse;
	CMatrix44f viewProjectionMatrix;
	CMatrix44f viewProjectionMatrixInverse;
	CMatrix44f billboardMatrix;
	CMatrix44f clipControlMatrix;

	Frustum frustum;
	// positive (right-to-left) lines [0], negative (left-to-right) lines [1]
	FrustumLine frustumLines[2][4 + 1];

	// CAMTYPE_*
	unsigned int camType = -1u;
	// PROJTYPE_*
	unsigned int projType = -1u;

	bool movState[8]; // fwd, back, left, right, up, down, fast, slow
	bool rotState[4]; // unused
};

#define camera (CCamera::GetActive())
#endif // _CAMERA_H