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 _BODY_H 5 #define _BODY_H 6 7 #include "DeleteEmitter.h" 8 #include "FrameId.h" 9 #include "lua/PropertiedObject.h" 10 #include "matrix3x3.h" 11 #include "vector3.h" 12 #include <string> 13 14 class Space; 15 class Camera; 16 class Frame; 17 class SystemBody; 18 19 namespace Graphics { 20 class Renderer; 21 } 22 struct CollisionContact; 23 24 // ObjectType is used as a form of RTTI for Body and its children. 25 // Think carefully before adding more entries; we'd like to switch 26 // to a composition-based system instead. 27 enum class ObjectType { // <enum name=PhysicsObjectType scope='ObjectType' public> 28 // only creating enum strings for types that are exposed to Lua 29 BODY, 30 MODELBODY, 31 DYNAMICBODY, // <enum skip> 32 SHIP, 33 PLAYER, 34 SPACESTATION, 35 TERRAINBODY, // <enum skip> 36 PLANET, 37 STAR, 38 CARGOBODY, 39 PROJECTILE, // <enum skip> 40 MISSILE, 41 HYPERSPACECLOUD // <enum skip> 42 }; 43 44 #define OBJDEF(__thisClass, __parentClass, __TYPE) \ 45 virtual ObjectType GetType() const override { return ObjectType::__TYPE; } \ 46 virtual bool IsType(ObjectType c) const override \ 47 { \ 48 if (__thisClass::GetType() == (c)) \ 49 return true; \ 50 else \ 51 return __parentClass::IsType(c); \ 52 } 53 54 class Body : public DeleteEmitter, public PropertiedObject { 55 public: GetType()56 virtual ObjectType GetType() const { return ObjectType::BODY; } IsType(ObjectType c)57 virtual bool IsType(ObjectType c) const { return GetType() == c; } 58 59 Body(); 60 Body(const Json &jsonObj, Space *space); 61 virtual ~Body(); 62 void ToJson(Json &jsonObj, Space *space); 63 static Body *FromJson(const Json &jsonObj, Space *space); PostLoadFixup(Space * space)64 virtual void PostLoadFixup(Space *space){}; 65 SetPosition(const vector3d & p)66 virtual void SetPosition(const vector3d &p) { m_pos = p; } GetPosition()67 vector3d GetPosition() const { return m_pos; } SetOrient(const matrix3x3d & r)68 virtual void SetOrient(const matrix3x3d &r) { m_orient = r; } GetOrient()69 const matrix3x3d &GetOrient() const { return m_orient; } SetVelocity(const vector3d & v)70 virtual void SetVelocity(const vector3d &v) { assert(0); } GetVelocity()71 virtual vector3d GetVelocity() const { return vector3d(0.0); } 72 SetPhysRadius(double r)73 void SetPhysRadius(double r) { m_physRadius = r; } GetPhysRadius()74 double GetPhysRadius() const { return m_physRadius; } SetClipRadius(double r)75 void SetClipRadius(double r) { m_clipRadius = r; } GetClipRadius()76 double GetClipRadius() const { return m_clipRadius; } GetMass()77 virtual double GetMass() const 78 { 79 assert(0); 80 return 0; 81 } 82 83 // return true if to do collision response and apply damage OnCollision(Body * o,Uint32 flags,double relVel)84 virtual bool OnCollision(Body *o, Uint32 flags, double relVel) { return false; } 85 // Attacker may be null OnDamage(Body * attacker,float kgDamage,const CollisionContact & contactData)86 virtual bool OnDamage(Body *attacker, float kgDamage, const CollisionContact &contactData) { return false; } 87 // Override to clear any pointers you hold to the body NotifyRemoved(const Body * const removedBody)88 virtual void NotifyRemoved(const Body *const removedBody) {} 89 90 // before all bodies have had TimeStepUpdate (their moving step), 91 // StaticUpdate() is called. Good for special collision testing (Projectiles) 92 // as you can't test for collisions if different objects are on different 'steps' StaticUpdate(const float timeStep)93 virtual void StaticUpdate(const float timeStep) {} TimeStepUpdate(const float timeStep)94 virtual void TimeStepUpdate(const float timeStep) {} 95 virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) = 0; 96 SetFrame(FrameId f)97 virtual void SetFrame(FrameId f) { m_frame = f; } GetFrame()98 FrameId GetFrame() const { return m_frame; } 99 void SwitchToFrame(FrameId newFrame); 100 void UpdateFrame(); // check for frame switching 101 102 vector3d GetVelocityRelTo(const Body *) const; 103 vector3d GetVelocityRelTo(FrameId) const; 104 vector3d GetPositionRelTo(FrameId) const; 105 vector3d GetPositionRelTo(const Body *) const; 106 matrix3x3d GetOrientRelTo(FrameId) const; 107 108 // Should return pointer in Pi::currentSystem GetSystemBody()109 virtual const SystemBody *GetSystemBody() const { return nullptr; } 110 // for putting on planet surface, oriented +y up 111 void OrientOnSurface(double radius, double latitude, double longitude); 112 113 virtual void SetLabel(const std::string &label); GetLabel()114 const std::string &GetLabel() const { return m_label; } 115 GetFlags()116 unsigned int GetFlags() const { return m_flags; } 117 // TODO(sturnclaw) use this sparingly, the flags interface is rather fragile and needs work SetFlag(unsigned int flag,bool enable)118 void SetFlag(unsigned int flag, bool enable) 119 { 120 if (enable) 121 m_flags |= flag; 122 else 123 m_flags &= ~flag; 124 } 125 126 // Only Space::KillBody() should call this method. MarkDead()127 void MarkDead() { m_dead = true; } IsDead()128 bool IsDead() const { return m_dead; } 129 130 // all Bodies are in space... except where they're not (Ships hidden in hyperspace clouds) IsInSpace()131 virtual bool IsInSpace() const { return true; } 132 133 // Interpolated between physics ticks. GetInterpOrient()134 const matrix3x3d &GetInterpOrient() const { return m_interpOrient; } GetInterpPosition()135 vector3d GetInterpPosition() const { return m_interpPos; } 136 vector3d GetInterpPositionRelTo(FrameId relToId) const; 137 vector3d GetInterpPositionRelTo(const Body *relTo) const; 138 matrix3x3d GetInterpOrientRelTo(FrameId relToId) const; 139 140 // should set m_interpolatedTransform to the smoothly interpolated value 141 // (interpolated by 0 <= alpha <=1) between the previous and current physics tick UpdateInterpTransform(double alpha)142 virtual void UpdateInterpTransform(double alpha) 143 { 144 m_interpOrient = GetOrient(); 145 m_interpPos = GetPosition(); 146 } 147 148 // TODO: abstract this functionality into a component of some fashion 149 // Return the position in body-local coordinates where the target indicator should be displayed. 150 // Usually equal to the center of the body == vector3d(0, 0, 0) 151 virtual vector3d GetTargetIndicatorPosition() const; 152 153 enum { 154 FLAG_CAN_MOVE_FRAME = (1 << 0), 155 FLAG_LABEL_HIDDEN = (1 << 1), 156 FLAG_DRAW_LAST = (1 << 2), // causes the body drawn after other bodies in the z-sort 157 FLAG_DRAW_EXCLUDE = (1 << 3) // do not draw this body, intended for e.g. when camera is inside 158 }; 159 160 protected: 161 virtual void SaveToJson(Json &jsonObj, Space *space); 162 unsigned int m_flags; 163 164 // Interpolated draw orientation-position 165 vector3d m_interpPos; 166 matrix3x3d m_interpOrient; 167 168 private: 169 vector3d m_pos; 170 matrix3x3d m_orient; 171 FrameId m_frame; // frame of reference 172 std::string m_label; 173 bool m_dead; // Checked in destructor to make sure body has been marked dead. 174 double m_clipRadius; 175 double m_physRadius; 176 }; 177 178 #endif /* _BODY_H */ 179