1 // Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #ifndef _FRAME_H
5 #define _FRAME_H
6 
7 #include "FrameId.h"
8 
9 #include "IterationProxy.h"
10 #include "JsonFwd.h"
11 #include "matrix3x3.h"
12 #include "matrix4x4.h"
13 #include "vector3.h"
14 #include <list>
15 #include <string>
16 
17 class Body;
18 class CollisionSpace;
19 class Geom;
20 class SystemBody;
21 class SfxManager;
22 class Space;
23 
24 struct CollisionContact;
25 
26 // Frame of reference.
27 
28 class Frame {
29 	// Used to avoid direct instantiation of Frames: use factory methods instead.
30 	// TODO: Find a better way, as checking it at compile time
31 	struct Dummy;
32 
33 public:
34 	Frame() = delete;
35 	Frame(const Dummy &d, FrameId parent, const char *label, unsigned int flags = FLAG_DEFAULT, double radius = 0.0);
36 	// Used *only* for Camera frame:
37 	// it doesn't set up CollisionSpace, and use default values for label, flags and radius
38 	Frame(const Dummy &d, FrameId parent);
39 
40 	Frame(const Frame &) = delete;
41 	Frame(Frame &&) noexcept;
42 	Frame &operator=(Frame &&);
43 
44 	~Frame();
45 
46 	enum { FLAG_DEFAULT = (0),
47 		FLAG_ROTATING = (1 << 1),
48 		FLAG_HAS_ROT = (1 << 2) };
49 
50 	static FrameId CreateFrame(FrameId parent, const char *label, unsigned int flags = FLAG_DEFAULT, double radius = 0.0);
51 	static FrameId FromJson(const Json &jsonObj, Space *space, FrameId parent, double at_time);
52 
53 	// Used to speed up creation/deletion of Frame for camera
54 	static FrameId CreateCameraFrame(FrameId parent);
55 	static void DeleteCameraFrame(FrameId camera);
56 
57 	static void ToJson(Json &jsonObj, FrameId fId, Space *space);
58 	static void PostUnserializeFixup(FrameId fId, Space *space);
59 
60 	static void DeleteFrames();
61 
62 	static Frame *GetFrame(FrameId FId);
63 
GetId()64 	FrameId GetId() const { return m_thisId; }
65 
GetLabel()66 	const std::string &GetLabel() const { return m_label; }
SetLabel(const char * label)67 	void SetLabel(const char *label) { m_label = label; }
68 
SetPosition(const vector3d & pos)69 	void SetPosition(const vector3d &pos) { m_pos = pos; }
GetPosition()70 	vector3d GetPosition() const { return m_pos; }
71 	void SetInitialOrient(const matrix3x3d &m, double time);
72 	void SetOrient(const matrix3x3d &m, double time);
GetOrient()73 	const matrix3x3d &GetOrient() const { return m_orient; }
GetInterpOrient()74 	const matrix3x3d &GetInterpOrient() const { return m_interpOrient; }
SetVelocity(const vector3d & vel)75 	void SetVelocity(const vector3d &vel) { m_vel = vel; }
GetVelocity()76 	vector3d GetVelocity() const { return m_vel; }
SetAngSpeed(const double angspeed)77 	void SetAngSpeed(const double angspeed) { m_angSpeed = angspeed; }
GetAngSpeed()78 	double GetAngSpeed() const { return m_angSpeed; }
SetRadius(double radius)79 	void SetRadius(double radius) { m_radius = radius; }
GetRadius()80 	double GetRadius() const { return m_radius; }
IsRotFrame()81 	bool IsRotFrame() const { return m_flags & FLAG_ROTATING; }
HasRotFrame()82 	bool HasRotFrame() const { return m_flags & FLAG_HAS_ROT; }
83 
GetParent()84 	FrameId GetParent() const { return m_parent; }
GetNonRotFrame()85 	FrameId GetNonRotFrame() const { return IsRotFrame() ? m_parent : m_thisId; }
GetRotFrame()86 	FrameId GetRotFrame() const { return HasRotFrame() ? m_children.front() : m_thisId; }
87 
SetBodies(SystemBody * s,Body * b)88 	void SetBodies(SystemBody *s, Body *b)
89 	{
90 		m_sbody = s;
91 		m_astroBody = b;
92 	}
GetSystemBody()93 	SystemBody *GetSystemBody() const { return m_sbody; }
GetBody()94 	Body *GetBody() const { return m_astroBody; }
95 
AddChild(FrameId fId)96 	void AddChild(FrameId fId) { m_children.push_back(fId); }
97 	void RemoveChild(FrameId fId);
HasChildren()98 	bool HasChildren() const { return !m_children.empty(); }
GetNumChildren()99 	unsigned GetNumChildren() const { return static_cast<Uint32>(m_children.size()); }
GetChildren()100 	IterationProxy<std::vector<FrameId>> GetChildren() { return MakeIterationProxy(m_children); }
GetChildren()101 	const IterationProxy<const std::vector<FrameId>> GetChildren() const { return MakeIterationProxy(m_children); }
102 
103 	void AddGeom(Geom *);
104 	void RemoveGeom(Geom *);
105 	void AddStaticGeom(Geom *);
106 	void RemoveStaticGeom(Geom *);
107 	// TODO: Should be a Planet or there's a needs for a Body?
108 	void SetPlanetGeom(double radius, Body *);
109 	CollisionSpace *GetCollisionSpace() const;
110 
111 	static void UpdateOrbitRails(double time, double timestep);
112 	static void CollideFrames(void (*callback)(CollisionContact *));
113 	void UpdateInterpTransform(double alpha);
114 	void ClearMovement();
115 
116 	// For an object in a rotating frame, relative to non-rotating frames it
117 	// must attain this velocity within rotating frame to be stationary.
GetStasisVelocity(const vector3d & pos)118 	vector3d GetStasisVelocity(const vector3d &pos) const { return -vector3d(0, m_angSpeed, 0).Cross(pos); }
119 
120 	vector3d GetPositionRelTo(FrameId relTo) const;
121 	vector3d GetVelocityRelTo(FrameId relTo) const;
122 	matrix3x3d GetOrientRelTo(FrameId relTo) const;
123 	matrix4x4d GetTransformRelTo(FrameId relTo) const;
124 
125 	// Same as above except it does interpolation between
126 	// physics ticks so rendering is smooth above physics hz
127 	vector3d GetInterpPositionRelTo(FrameId relTo) const;
128 	matrix3x3d GetInterpOrientRelTo(FrameId relTo) const;
129 	matrix4x4d GetInterpTransformRelTo(FrameId relTo) const;
130 
131 	static void GetFrameTransform(FrameId fFrom, FrameId fTo, matrix4x4d &m);
132 
133 	std::unique_ptr<SfxManager> m_sfx; // the last survivor. actually m_children is pretty grim too.
134 
135 private:
136 	FrameId m_thisId;
137 
138 	void UpdateRootRelativeVars();
139 
140 	FrameId m_parent;				 // if parent is null then frame position is absolute
141 	std::vector<FrameId> m_children; // child frames, first may be rotating
142 	SystemBody *m_sbody;			 // points to SBodies in Pi::current_system
143 	Body *m_astroBody;				 // if frame contains a star or planet or something
144 
145 	vector3d m_pos;
146 	vector3d m_oldPos;
147 	vector3d m_interpPos;
148 	matrix3x3d m_initialOrient;
149 	matrix3x3d m_orient;
150 	matrix3x3d m_interpOrient;
151 	vector3d m_vel;	   // note we don't use this to move frame. rather,
152 					   // orbital rails determine velocity.
153 	double m_angSpeed; // this however *is* directly applied (for rotating frames)
154 	double m_oldAngDisplacement;
155 	std::string m_label;
156 	double m_radius;
157 	int m_flags;
158 	int m_collisionSpace;
159 
160 	vector3d m_rootVel; // velocity, position and orient relative to root frame
161 	vector3d m_rootPos; // updated by UpdateOrbitRails
162 	matrix3x3d m_rootOrient;
163 	vector3d m_rootInterpPos;	   // interp position and orient relative to root frame
164 	matrix3x3d m_rootInterpOrient; // updated by UpdateInterpTransform
165 
166 	int m_astroBodyIndex; // deserialisation
167 
168 	static std::vector<Frame> s_frames;
169 	static std::vector<CollisionSpace> s_collisionSpaces;
170 
171 	// A trick in order to avoid a direct call of ctor or dtor: use factory methods instead
172 	struct Dummy {
DummyDummy173 		Dummy() :
174 			madeWithFactory(false)
175 		{}
176 		bool madeWithFactory;
177 	};
178 
179 	Dummy d;
180 };
181 
182 #endif /* _FRAME_H */
183