1 #pragma once
2 
3 #include "object.h"
4 #include "lc_math.h"
5 #include "lc_array.h"
6 
7 #define LC_CAMERA_HIDDEN            0x0001
8 #define LC_CAMERA_SIMPLE            0x0002
9 #define LC_CAMERA_ORTHO             0x0004
10 #define LC_CAMERA_POSITION_SELECTED 0x0010
11 #define LC_CAMERA_POSITION_FOCUSED  0x0020
12 #define LC_CAMERA_TARGET_SELECTED   0x0040
13 #define LC_CAMERA_TARGET_FOCUSED    0x0080
14 #define LC_CAMERA_UPVECTOR_SELECTED 0x0100
15 #define LC_CAMERA_UPVECTOR_FOCUSED  0x0200
16 
17 #define LC_CAMERA_SELECTION_MASK    (LC_CAMERA_POSITION_SELECTED | LC_CAMERA_TARGET_SELECTED | LC_CAMERA_UPVECTOR_SELECTED)
18 #define LC_CAMERA_FOCUS_MASK        (LC_CAMERA_POSITION_FOCUSED | LC_CAMERA_TARGET_FOCUSED | LC_CAMERA_UPVECTOR_FOCUSED)
19 
20 enum class lcViewpoint
21 {
22 	Front,
23 	Back,
24 	Top,
25 	Bottom,
26 	Left,
27 	Right,
28 	Home,
29 	Count
30 };
31 
32 enum lcCameraSection
33 {
34 	LC_CAMERA_SECTION_POSITION,
35 	LC_CAMERA_SECTION_TARGET,
36 	LC_CAMERA_SECTION_UPVECTOR
37 };
38 
39 class lcCamera : public lcObject
40 {
41 public:
42 	lcCamera(bool Simple);
43 	lcCamera(float ex, float ey, float ez, float tx, float ty, float tz);
44 	~lcCamera();
45 
46 	lcCamera(const lcCamera&) = delete;
47 	lcCamera& operator=(const lcCamera&) = delete;
48 
49 	static lcViewpoint GetViewpoint(const QString& ViewpointName);
50 
GetName()51 	QString GetName() const override
52 	{
53 		return mName;
54 	}
55 
56 	void SetName(const QString& Name);
57 	void CreateName(const lcArray<lcCamera*>& Cameras);
58 
IsSimple()59 	bool IsSimple() const
60 	{
61 		return (mState & LC_CAMERA_SIMPLE) != 0;
62 	}
63 
IsOrtho()64 	bool IsOrtho() const
65 	{
66 		return (mState & LC_CAMERA_ORTHO) != 0;
67 	}
68 
SetOrtho(bool Ortho)69 	void SetOrtho(bool Ortho)
70 	{
71 		if (Ortho)
72 			mState |= LC_CAMERA_ORTHO;
73 		else
74 			mState &= ~LC_CAMERA_ORTHO;
75 	}
76 
IsSelected()77 	bool IsSelected() const override
78 	{
79 		return (mState & LC_CAMERA_SELECTION_MASK) != 0;
80 	}
81 
IsSelected(quint32 Section)82 	bool IsSelected(quint32 Section) const override
83 	{
84 		switch (Section)
85 		{
86 		case LC_CAMERA_SECTION_POSITION:
87 			return (mState & LC_CAMERA_POSITION_SELECTED) != 0;
88 			break;
89 
90 		case LC_CAMERA_SECTION_TARGET:
91 			return (mState & LC_CAMERA_TARGET_SELECTED) != 0;
92 			break;
93 
94 		case LC_CAMERA_SECTION_UPVECTOR:
95 			return (mState & LC_CAMERA_UPVECTOR_SELECTED) != 0;
96 			break;
97 		}
98 		return false;
99 	}
100 
SetSelected(bool Selected)101 	void SetSelected(bool Selected) override
102 	{
103 		if (Selected)
104 			mState |= LC_CAMERA_SELECTION_MASK;
105 		else
106 			mState &= ~(LC_CAMERA_SELECTION_MASK | LC_CAMERA_FOCUS_MASK);
107 	}
108 
SetSelected(quint32 Section,bool Selected)109 	void SetSelected(quint32 Section, bool Selected) override
110 	{
111 		switch (Section)
112 		{
113 		case LC_CAMERA_SECTION_POSITION:
114 			if (Selected)
115 				mState |= LC_CAMERA_POSITION_SELECTED;
116 			else
117 				mState &= ~(LC_CAMERA_POSITION_SELECTED | LC_CAMERA_POSITION_FOCUSED);
118 			break;
119 
120 		case LC_CAMERA_SECTION_TARGET:
121 			if (Selected)
122 				mState |= LC_CAMERA_TARGET_SELECTED;
123 			else
124 				mState &= ~(LC_CAMERA_TARGET_SELECTED | LC_CAMERA_TARGET_FOCUSED);
125 			break;
126 
127 		case LC_CAMERA_SECTION_UPVECTOR:
128 			if (Selected)
129 				mState |= LC_CAMERA_UPVECTOR_SELECTED;
130 			else
131 				mState &= ~(LC_CAMERA_UPVECTOR_SELECTED | LC_CAMERA_UPVECTOR_FOCUSED);
132 			break;
133 		}
134 	}
135 
IsFocused()136 	bool IsFocused() const override
137 	{
138 		return (mState & LC_CAMERA_FOCUS_MASK) != 0;
139 	}
140 
IsFocused(quint32 Section)141 	bool IsFocused(quint32 Section) const override
142 	{
143 		switch (Section)
144 		{
145 		case LC_CAMERA_SECTION_POSITION:
146 			return (mState & LC_CAMERA_POSITION_FOCUSED) != 0;
147 			break;
148 
149 		case LC_CAMERA_SECTION_TARGET:
150 			return (mState & LC_CAMERA_TARGET_FOCUSED) != 0;
151 			break;
152 
153 		case LC_CAMERA_SECTION_UPVECTOR:
154 			return (mState & LC_CAMERA_UPVECTOR_FOCUSED) != 0;
155 			break;
156 		}
157 		return false;
158 	}
159 
SetFocused(quint32 Section,bool Focus)160 	void SetFocused(quint32 Section, bool Focus) override
161 	{
162 		switch (Section)
163 		{
164 		case LC_CAMERA_SECTION_POSITION:
165 			if (Focus)
166 				mState |= LC_CAMERA_POSITION_SELECTED | LC_CAMERA_POSITION_FOCUSED;
167 			else
168 				mState &= ~(LC_CAMERA_POSITION_SELECTED | LC_CAMERA_POSITION_FOCUSED);
169 			break;
170 
171 		case LC_CAMERA_SECTION_TARGET:
172 			if (Focus)
173 				mState |= LC_CAMERA_TARGET_SELECTED | LC_CAMERA_TARGET_FOCUSED;
174 			else
175 				mState &= ~(LC_CAMERA_TARGET_SELECTED | LC_CAMERA_TARGET_FOCUSED);
176 			break;
177 
178 		case LC_CAMERA_SECTION_UPVECTOR:
179 			if (Focus)
180 				mState |= LC_CAMERA_UPVECTOR_SELECTED | LC_CAMERA_UPVECTOR_FOCUSED;
181 			else
182 				mState &= ~(LC_CAMERA_UPVECTOR_SELECTED | LC_CAMERA_UPVECTOR_FOCUSED);
183 			break;
184 		}
185 	}
186 
GetFocusSection()187 	quint32 GetFocusSection() const override
188 	{
189 		if (mState & LC_CAMERA_POSITION_FOCUSED)
190 			return LC_CAMERA_SECTION_POSITION;
191 
192 		if (mState & LC_CAMERA_TARGET_FOCUSED)
193 			return LC_CAMERA_SECTION_TARGET;
194 
195 		if (mState & LC_CAMERA_UPVECTOR_FOCUSED)
196 			return LC_CAMERA_SECTION_UPVECTOR;
197 
198 		return ~0U;
199 	}
200 
GetAllowedTransforms()201 	quint32 GetAllowedTransforms() const override
202 	{
203 		return LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z;
204 	}
205 
GetSectionPosition(quint32 Section)206 	lcVector3 GetSectionPosition(quint32 Section) const override
207 	{
208 		switch (Section)
209 		{
210 		case LC_CAMERA_SECTION_POSITION:
211 			return mPosition;
212 
213 		case LC_CAMERA_SECTION_TARGET:
214 			return mTargetPosition;
215 
216 		case LC_CAMERA_SECTION_UPVECTOR:
217 			return lcMul31(lcVector3(0, 25, 0), lcMatrix44AffineInverse(mWorldView));
218 		}
219 
220 		return lcVector3(0.0f, 0.0f, 0.0f);
221 	}
222 
223 	void SaveLDraw(QTextStream& Stream) const;
224 	bool ParseLDrawLine(QTextStream& Stream);
225 
226 public:
IsVisible()227 	bool IsVisible() const
228 		{ return (mState & LC_CAMERA_HIDDEN) == 0; }
229 
IsHidden()230 	bool IsHidden() const
231 	{
232 		return (mState & LC_CAMERA_HIDDEN) != 0;
233 	}
234 
SetHidden(bool Hidden)235 	void SetHidden(bool Hidden)
236 	{
237 		if (Hidden)
238 			mState |= LC_CAMERA_HIDDEN;
239 		else
240 			mState &= ~LC_CAMERA_HIDDEN;
241 	}
242 
SetPosition(const lcVector3 & Position,lcStep Step,bool AddKey)243 	void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
244 	{
245 		mPositionKeys.ChangeKey(Position, Step, AddKey);
246 	}
247 
SetTargetPosition(const lcVector3 & TargetPosition,lcStep Step,bool AddKey)248 	void SetTargetPosition(const lcVector3& TargetPosition, lcStep Step, bool AddKey)
249 	{
250 		mTargetPositionKeys.ChangeKey(TargetPosition, Step, AddKey);
251 	}
252 
SetUpVector(const lcVector3 & UpVector,lcStep Step,bool AddKey)253 	void SetUpVector(const lcVector3& UpVector, lcStep Step, bool AddKey)
254 	{
255 		mPositionKeys.ChangeKey(UpVector, Step, AddKey);
256 	}
257 
GetOrthoHeight()258 	float GetOrthoHeight() const
259 	{
260 		// Compute the FOV/plane intersection radius.
261 		//                d               d
262 		//   a = 2 atan(------) => ~ a = --- => d = af
263 		//                2f              f
264 		float f = (mPosition - mTargetPosition).Length();
265 		return (m_fovy * f) * (LC_PI / 180.0f);
266 	}
267 
268 public:
269 	void RayTest(lcObjectRayTest& ObjectRayTest) const override;
270 	void BoxTest(lcObjectBoxTest& ObjectBoxTest) const override;
271 	void DrawInterface(lcContext* Context, const lcScene& Scene) const override;
272 	void RemoveKeyFrames() override;
273 
274 	void InsertTime(lcStep Start, lcStep Time);
275 	void RemoveTime(lcStep Start, lcStep Time);
276 
277 	static bool FileLoad(lcFile& file);
278 
279 	void CompareBoundingBox(lcVector3& Min, lcVector3& Max);
280 	void UpdatePosition(lcStep Step);
281 	void CopyPosition(const lcCamera* Camera);
282 	void CopySettings(const lcCamera* Camera);
283 
284 	void ZoomExtents(float AspectRatio, const lcVector3& Center, const std::vector<lcVector3>& Points, lcStep Step, bool AddKey);
285 	void ZoomRegion(float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners, lcStep Step, bool AddKey);
286 	void Zoom(float Distance, lcStep Step, bool AddKey);
287 	void Pan(const lcVector3& Distance, lcStep Step, bool AddKey);
288 	void Orbit(float DistanceX, float DistanceY, const lcVector3& CenterPosition, lcStep Step, bool AddKey);
289 	void Roll(float Distance, lcStep Step, bool AddKey);
290 	void Center(const lcVector3& NewCenter, lcStep Step, bool AddKey);
291 	void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance);
292 	void MoveRelative(const lcVector3& Distance, lcStep Step, bool AddKey);
293 	void SetViewpoint(lcViewpoint Viewpoint);
294 	void SetViewpoint(const lcVector3& Position);
295 	void SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up);
296 	void GetAngles(float& Latitude, float& Longitude, float& Distance) const;
297 	void SetAngles(float Latitude, float Longitude, float Distance);
298 
299 	float m_fovy;
300 	float m_zNear;
301 	float m_zFar;
302 
303 	lcMatrix44 mWorldView;
304 	lcVector3 mPosition;
305 	lcVector3 mTargetPosition;
306 	lcVector3 mUpVector;
307 
308 protected:
309 	lcObjectKeyArray<lcVector3> mPositionKeys;
310 	lcObjectKeyArray<lcVector3> mTargetPositionKeys;
311 	lcObjectKeyArray<lcVector3> mUpVectorKeys;
312 
313 	void Initialize();
314 
315 	QString mName;
316 	quint32 mState;
317 };
318