diff --git a/src/Beam.cpp b/src/Beam.cpp index 7ca47aee8..c24510fb8 100644 --- a/src/Beam.cpp +++ b/src/Beam.cpp @@ -216,7 +216,7 @@ double Beam::GetRadius() const return sqrt(m_length * m_length); } -static void MiningLaserSpawnTastyStuff(Frame *f, const SystemBody *asteroid, const vector3d &pos) +static void MiningLaserSpawnTastyStuff(FrameId fId, const SystemBody *asteroid, const vector3d &pos) { lua_State *l = Lua::manager->GetLuaState(); @@ -240,7 +240,7 @@ static void MiningLaserSpawnTastyStuff(Frame *f, const SystemBody *asteroid, con lua_pop(l, 1); LUA_DEBUG_END(l, 0); - cargo->SetFrame(f); + cargo->SetFrame(fId); cargo->SetPosition(pos); const double x = Pi::rng.Double(); vector3d dir = pos.Normalized(); @@ -257,7 +257,9 @@ void Beam::StaticUpdate(const float timeStep) return; CollisionContact c; - GetFrame()->GetCollisionSpace()->TraceRay(GetPosition(), m_dir.Normalized(), m_length, &c, static_cast(m_parent)->GetGeom()); + + Frame *frame = Frame::GetFrame(GetFrame()); + frame->GetCollisionSpace()->TraceRay(GetPosition(), m_dir.Normalized(), m_length, &c, static_cast(m_parent)->GetGeom()); if (c.userData1) { Object *o = static_cast(c.userData1); @@ -277,8 +279,8 @@ void Beam::StaticUpdate(const float timeStep) if (m_mining) { // need to test for terrain hit - if (GetFrame()->GetBody() && GetFrame()->GetBody()->IsType(Object::PLANET)) { - Planet *const planet = static_cast(GetFrame()->GetBody()); + if (frame->GetBody() && frame->GetBody()->IsType(Object::PLANET)) { + Planet *const planet = static_cast(frame->GetBody()); const SystemBody *b = planet->GetSystemBody(); vector3d pos = GetPosition(); double terrainHeight = planet->GetTerrainHeight(pos.Normalized()); diff --git a/src/Body.cpp b/src/Body.cpp index b069ff94a..d3d8375f7 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -24,7 +24,7 @@ Body::Body() : m_interpOrient(matrix3x3d::Identity()), m_pos(0.0), m_orient(matrix3x3d::Identity()), - m_frame(nullptr), + m_frame(noFrameId), m_dead(false), m_clipRadius(0.0), m_physRadius(0.0) @@ -37,13 +37,13 @@ Body::Body(const Json &jsonObj, Space *space) : m_flags(0), m_interpPos(0.0), m_interpOrient(matrix3x3d::Identity()), - m_frame(nullptr) + m_frame(noFrameId) { try { Json bodyObj = jsonObj["body"]; Properties().LoadFromJson(bodyObj); - m_frame = Frame::FindFrame(bodyObj["index_for_frame"]); + m_frame = bodyObj["index_for_frame"]; m_label = bodyObj["label"]; Properties().Set("label", m_label); m_dead = bodyObj["dead"]; @@ -66,7 +66,7 @@ void Body::SaveToJson(Json &jsonObj, Space *space) Json bodyObj = Json::object(); // Create JSON object to contain body data. Properties().SaveToJson(bodyObj); - bodyObj["index_for_frame"] = (m_frame != nullptr ? m_frame->GetId() : noFrameId); + bodyObj["index_for_frame"] = (m_frame >= 0 ? m_frame : noFrameId); bodyObj["label"] = m_label; bodyObj["dead"] = m_dead; @@ -139,17 +139,21 @@ Body *Body::FromJson(const Json &jsonObj, Space *space) return nullptr; } -vector3d Body::GetPositionRelTo(const Frame *relTo) const +vector3d Body::GetPositionRelTo(FrameId relToId) const { - vector3d fpos = m_frame->GetPositionRelTo(relTo); - matrix3x3d forient = m_frame->GetOrientRelTo(relTo); + Frame *frame = Frame::GetFrame(m_frame); + + vector3d fpos = frame->GetPositionRelTo(relToId); + matrix3x3d forient = frame->GetOrientRelTo(relToId); return forient * GetPosition() + fpos; } -vector3d Body::GetInterpPositionRelTo(const Frame *relTo) const +vector3d Body::GetInterpPositionRelTo(FrameId relToId) const { - vector3d fpos = m_frame->GetInterpPositionRelTo(relTo); - matrix3x3d forient = m_frame->GetInterpOrientRelTo(relTo); + Frame *frame = Frame::GetFrame(m_frame); + + vector3d fpos = frame->GetInterpPositionRelTo(relToId); + matrix3x3d forient = frame->GetInterpOrientRelTo(relToId); return forient * GetInterpPosition() + fpos; } @@ -163,24 +167,30 @@ vector3d Body::GetInterpPositionRelTo(const Body *relTo) const return GetInterpPositionRelTo(relTo->m_frame) - relTo->GetInterpPosition(); } -matrix3x3d Body::GetOrientRelTo(const Frame *relTo) const +matrix3x3d Body::GetOrientRelTo(FrameId relToId) const { - matrix3x3d forient = m_frame->GetOrientRelTo(relTo); + Frame *frame = Frame::GetFrame(m_frame); + + matrix3x3d forient = frame->GetOrientRelTo(relToId); return forient * GetOrient(); } -matrix3x3d Body::GetInterpOrientRelTo(const Frame *relTo) const +matrix3x3d Body::GetInterpOrientRelTo(FrameId relToId) const { - matrix3x3d forient = m_frame->GetInterpOrientRelTo(relTo); + Frame *frame = Frame::GetFrame(m_frame); + + matrix3x3d forient = frame->GetInterpOrientRelTo(relToId); return forient * GetInterpOrient(); } -vector3d Body::GetVelocityRelTo(const Frame *relTo) const +vector3d Body::GetVelocityRelTo(FrameId relToId) const { - matrix3x3d forient = m_frame->GetOrientRelTo(relTo); + Frame *frame = Frame::GetFrame(m_frame); + + matrix3x3d forient = frame->GetOrientRelTo(relToId); vector3d vel = GetVelocity(); - if (m_frame != relTo) vel -= m_frame->GetStasisVelocity(GetPosition()); - return forient * vel + m_frame->GetVelocityRelTo(relTo); + if (m_frame != relToId) vel -= frame->GetStasisVelocity(GetPosition()); + return forient * vel + frame->GetVelocityRelTo(relToId); } vector3d Body::GetVelocityRelTo(const Body *relTo) const @@ -197,15 +207,18 @@ void Body::OrientOnSurface(double radius, double latitude, double longitude) SetOrient(matrix3x3d::FromVectors(right, up)); } -void Body::SwitchToFrame(Frame *newFrame) +void Body::SwitchToFrame(FrameId newFrameId) { - const vector3d vel = GetVelocityRelTo(newFrame); // do this first because it uses position - const vector3d fpos = m_frame->GetPositionRelTo(newFrame); - const matrix3x3d forient = m_frame->GetOrientRelTo(newFrame); + const Frame *newFrame = Frame::GetFrame(newFrameId); + const Frame *frame = Frame::GetFrame(m_frame); + + const vector3d vel = GetVelocityRelTo(newFrameId); // do this first because it uses position + const vector3d fpos = frame->GetPositionRelTo(newFrameId); + const matrix3x3d forient = frame->GetOrientRelTo(newFrameId); SetPosition(forient * GetPosition() + fpos); SetOrient(forient * GetOrient()); SetVelocity(vel + newFrame->GetStasisVelocity(GetPosition())); - SetFrame(newFrame); + SetFrame(newFrameId); LuaEvent::Queue("onFrameChanged", this); } @@ -214,29 +227,33 @@ void Body::UpdateFrame() { if (!(m_flags & FLAG_CAN_MOVE_FRAME)) return; + const Frame *frame = Frame::GetFrame(m_frame); + // falling out of frames - if (m_frame->GetRadius() < GetPosition().Length()) { - Frame *newFrame = GetFrame()->GetParent(); + if (frame->GetRadius() < GetPosition().Length()) { + FrameId parent = frame->GetParent(); + Frame *newFrame = Frame::GetFrame(parent); if (newFrame) { // don't fall out of root frame - Output("%s leaves frame %s\n", GetLabel().c_str(), GetFrame()->GetLabel().c_str()); - SwitchToFrame(newFrame); + Output("%s leaves frame %s\n", GetLabel().c_str(), frame->GetLabel().c_str()); + SwitchToFrame(parent); return; } } // entering into frames - for (Frame *kid : m_frame->GetChildren()) { + for (FrameId kid : frame->GetChildren()) { + Frame *kid_frame = Frame::GetFrame(kid); const vector3d pos = GetPositionRelTo(kid); - if (pos.Length() >= kid->GetRadius()) continue; + if (pos.Length() >= kid_frame->GetRadius()) continue; SwitchToFrame(kid); - Output("%s enters frame %s\n", GetLabel().c_str(), kid->GetLabel().c_str()); + Output("%s enters frame %s\n", GetLabel().c_str(), kid_frame->GetLabel().c_str()); break; } } -vector3d Body::GetTargetIndicatorPosition(const Frame *relTo) const +vector3d Body::GetTargetIndicatorPosition(FrameId relToId) const { - return GetInterpPositionRelTo(relTo); + return GetInterpPositionRelTo(relToId); } void Body::SetLabel(const std::string &label) diff --git a/src/Body.h b/src/Body.h index 387d1a03b..a2003e24b 100644 --- a/src/Body.h +++ b/src/Body.h @@ -4,6 +4,7 @@ #ifndef _BODY_H #define _BODY_H +#include "FrameId.h" #include "Object.h" #include "PropertiedObject.h" #include "matrix3x3.h" @@ -61,16 +62,16 @@ public: virtual void TimeStepUpdate(const float timeStep) {} virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) = 0; - virtual void SetFrame(Frame *f) { m_frame = f; } - Frame *GetFrame() const { return m_frame; } - void SwitchToFrame(Frame *newFrame); + virtual void SetFrame(FrameId f) { m_frame = f; } + FrameId GetFrame() const { return m_frame; } + void SwitchToFrame(FrameId newFrame); void UpdateFrame(); // check for frame switching vector3d GetVelocityRelTo(const Body *) const; - vector3d GetVelocityRelTo(const Frame *) const; - vector3d GetPositionRelTo(const Frame *) const; + vector3d GetVelocityRelTo(FrameId) const; + vector3d GetPositionRelTo(FrameId) const; vector3d GetPositionRelTo(const Body *) const; - matrix3x3d GetOrientRelTo(const Frame *) const; + matrix3x3d GetOrientRelTo(FrameId) const; // Should return pointer in Pi::currentSystem virtual const SystemBody *GetSystemBody() const { return nullptr; } @@ -90,9 +91,9 @@ public: // Interpolated between physics ticks. const matrix3x3d &GetInterpOrient() const { return m_interpOrient; } vector3d GetInterpPosition() const { return m_interpPos; } - vector3d GetInterpPositionRelTo(const Frame *relTo) const; + vector3d GetInterpPositionRelTo(FrameId relToId) const; vector3d GetInterpPositionRelTo(const Body *relTo) const; - matrix3x3d GetInterpOrientRelTo(const Frame *relTo) const; + matrix3x3d GetInterpOrientRelTo(FrameId relToId) const; // should set m_interpolatedTransform to the smoothly interpolated value // (interpolated by 0 <= alpha <=1) between the previous and current physics tick @@ -103,7 +104,7 @@ public: } // where to draw targeting indicators - usually equal to GetInterpolatedPositionRelTo - virtual vector3d GetTargetIndicatorPosition(const Frame *relTo) const; + virtual vector3d GetTargetIndicatorPosition(FrameId relToId) const; enum { FLAG_CAN_MOVE_FRAME = (1 << 0), FLAG_LABEL_HIDDEN = (1 << 1), @@ -120,7 +121,7 @@ protected: private: vector3d m_pos; matrix3x3d m_orient; - Frame *m_frame; // frame of reference + FrameId m_frame; // frame of reference std::string m_label; bool m_dead; // Checked in destructor to make sure body has been marked dead. double m_clipRadius; diff --git a/src/Camera.cpp b/src/Camera.cpp index b72a1b78d..77738d3a8 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -29,44 +29,46 @@ CameraContext::CameraContext(float width, float height, float fovAng, float zNea m_zNear(zNear), m_zFar(zFar), m_frustum(m_width, m_height, m_fovAng, m_zNear, m_zFar), - m_frame(nullptr), + m_frame(noFrameId), m_pos(0.0), m_orient(matrix3x3d::Identity()), - m_camFrame(nullptr) + m_camFrame(noFrameId) { } CameraContext::~CameraContext() { - if (m_camFrame) + if (m_camFrame != noFrameId) EndFrame(); } void CameraContext::BeginFrame() { - assert(m_frame); - assert(!m_camFrame); + assert(IsIdValid(m_frame)); + assert(!IsIdValid(m_camFrame)); // make temporary camera frame m_camFrame = Frame::CreateFrame(m_frame, "camera", Frame::FLAG_ROTATING, 0.0); + Frame *camFrame = Frame::GetFrame(m_camFrame); // move and orient it to the camera position - m_camFrame->SetOrient(m_orient, Pi::game ? Pi::game->GetTime() : 0.0); - m_camFrame->SetPosition(m_pos); + camFrame->SetOrient(m_orient, Pi::game ? Pi::game->GetTime() : 0.0); + camFrame->SetPosition(m_pos); // make sure old orient and interpolated orient (rendering orient) are not rubbish - m_camFrame->ClearMovement(); - m_camFrame->UpdateInterpTransform(1.0); // update root-relative pos/orient + camFrame->ClearMovement(); + camFrame->UpdateInterpTransform(1.0); // update root-relative pos/orient } void CameraContext::EndFrame() { - assert(m_frame); - assert(m_camFrame); + assert(IsIdValid(m_frame)); + assert(IsIdValid(m_camFrame)); - m_frame->RemoveChild(m_camFrame); + Frame *frame = Frame::GetFrame(m_frame); + frame->RemoveChild(m_camFrame); Frame::DeleteFrame(m_camFrame); - m_camFrame = nullptr; + m_camFrame = noFrameId; } void CameraContext::ApplyDrawTransforms(Graphics::Renderer *r) @@ -113,7 +115,7 @@ static void position_system_lights(Frame *camFrame, Frame *frame, std::vectorGetSystemBody(); // IsRotFrame check prevents double counting if (body && !frame->IsRotFrame() && (body->GetSuperType() == SystemBody::SUPERTYPE_STAR)) { - vector3d lpos = frame->GetPositionRelTo(camFrame); + vector3d lpos = frame->GetPositionRelTo(camFrame->GetId()); const double dist = lpos.Length() / AU; lpos *= 1.0 / dist; // normalize @@ -125,14 +127,15 @@ static void position_system_lights(Frame *camFrame, Frame *frame, std::vectorGetBody(), light)); } - for (Frame *kid : frame->GetChildren()) { - position_system_lights(camFrame, kid, lights); + for (FrameId kid : frame->GetChildren()) { + Frame *kid_f = Frame::GetFrame(kid); + position_system_lights(camFrame, kid_f, lights); } } void Camera::Update() { - Frame *camFrame = m_context->GetCamFrame(); + FrameId camFrame = m_context->GetCamFrame(); // evaluate each body and determine if/where/how to draw it m_sortedBodies.clear(); @@ -143,8 +146,9 @@ void Camera::Update() // determine position and transform for draw // Frame::GetFrameTransform(b->GetFrame(), camFrame, attrs.viewTransform); // doesn't use interp coords, so breaks in some cases - attrs.viewTransform = b->GetFrame()->GetInterpOrientRelTo(camFrame); - attrs.viewTransform.SetTranslate(b->GetFrame()->GetInterpPositionRelTo(camFrame)); + Frame *f = Frame::GetFrame(b->GetFrame()); + attrs.viewTransform = f->GetInterpOrientRelTo(camFrame); + attrs.viewTransform.SetTranslate(f->GetInterpPositionRelTo(camFrame)); attrs.viewCoords = attrs.viewTransform * b->GetInterpPosition(); // cull off-screen objects @@ -203,18 +207,22 @@ void Camera::Draw(const Body *excludeBody, ShipCockpit *cockpit) { PROFILE_SCOPED() - Frame *camFrame = m_context->GetCamFrame(); + FrameId camFrameId = m_context->GetCamFrame(); + FrameId rootFrameId = Pi::game->GetSpace()->GetRootFrame(); + + Frame *camFrame = Frame::GetFrame(camFrameId); + Frame *rootFrame = Frame::GetFrame(rootFrameId); m_renderer->ClearScreen(); matrix4x4d trans2bg; - Frame::GetFrameTransform(Pi::game->GetSpace()->GetRootFrame(), camFrame, trans2bg); + Frame::GetFrameTransform(rootFrameId, camFrameId, trans2bg); trans2bg.ClearToRotOnly(); // Pick up to four suitable system light sources (stars) m_lightSources.clear(); m_lightSources.reserve(4); - position_system_lights(camFrame, Pi::game->GetSpace()->GetRootFrame(), m_lightSources); + position_system_lights(camFrame, rootFrame, m_lightSources); if (m_lightSources.empty()) { // no lights means we're somewhere weird (eg hyperspace). fake one @@ -224,12 +232,13 @@ void Camera::Draw(const Body *excludeBody, ShipCockpit *cockpit) //fade space background based on atmosphere thickness and light angle float bgIntensity = 1.f; - if (camFrame->GetParent() && camFrame->GetParent()->IsRotFrame()) { + Frame *camParent = Frame::GetFrame(camFrame->GetParent()); + if ( camParent && camParent->IsRotFrame()) { //check if camera is near a planet - Body *camParentBody = camFrame->GetParent()->GetBody(); + Body *camParentBody = camParent->GetBody(); if (camParentBody && camParentBody->IsType(Object::PLANET)) { Planet *planet = static_cast(camParentBody); - const vector3f relpos(planet->GetInterpPositionRelTo(camFrame)); + const vector3f relpos(planet->GetInterpPositionRelTo(camFrameId)); double altitude(relpos.Length()); double pressure, density; planet->GetAtmosphericState(altitude, &pressure, &density); @@ -279,7 +288,7 @@ void Camera::Draw(const Body *excludeBody, ShipCockpit *cockpit) attrs->body->Render(m_renderer, this, attrs->viewCoords, attrs->viewTransform); } - SfxManager::RenderAll(m_renderer, Pi::game->GetSpace()->GetRootFrame(), camFrame); + SfxManager::RenderAll(m_renderer, rootFrameId, camFrameId); // NB: Do any screen space rendering after here: // Things like the cockpit and AR features like hudtrails, space dust etc. @@ -288,7 +297,7 @@ void Camera::Draw(const Body *excludeBody, ShipCockpit *cockpit) // XXX only here because it needs a frame for lighting calc // should really be in WorldView, immediately after camera draw if (cockpit) - cockpit->RenderCockpit(m_renderer, this, camFrame); + cockpit->RenderCockpit(m_renderer, this, camFrameId); } void Camera::CalcShadows(const int lightNum, const Body *b, std::vector &shadowsOut) const diff --git a/src/Camera.h b/src/Camera.h index cab7cc7c1..7ad7d3545 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -5,6 +5,7 @@ #define _CAMERA_H #include "Color.h" +#include "FrameId.h" #include "graphics/Frustum.h" #include "graphics/Light.h" #include "matrix4x4.h" @@ -32,7 +33,7 @@ public: float GetZFar() const { return m_zFar; } // frame to position the camera relative to - void SetCameraFrame(Frame *frame) { m_frame = frame; } + void SetCameraFrame(FrameId frame) { m_frame = frame; } // camera position relative to the frame origin void SetCameraPosition(const vector3d &pos) { m_pos = pos; } @@ -48,7 +49,7 @@ public: void EndFrame(); // valid between BeginFrame and EndFrame - Frame *GetCamFrame() const + FrameId GetCamFrame() const { assert(m_camFrame); return m_camFrame; @@ -66,11 +67,11 @@ private: Graphics::Frustum m_frustum; - Frame *m_frame; + FrameId m_frame; vector3d m_pos; matrix3x3d m_orient; - Frame *m_camFrame; + FrameId m_camFrame; }; class Camera { diff --git a/src/CameraController.cpp b/src/CameraController.cpp index b79bfe148..3f314f1d9 100644 --- a/src/CameraController.cpp +++ b/src/CameraController.cpp @@ -4,6 +4,7 @@ #include "CameraController.h" #include "AnimationCurves.h" +#include "Frame.h" #include "Game.h" #include "GameSaveError.h" #include "MathUtil.h" @@ -374,9 +375,10 @@ void FlyByCameraController::Update() vector3d ship_pos = ship->GetInterpPosition(); vector3d camerap; - if (GetPosition() == vector3d(0, 0, 0) || m_old_frame != ship->GetFrame()) { + Frame *shipFrame = Frame::GetFrame(ship->GetFrame()); + if (GetPosition() == vector3d(0, 0, 0) || m_old_frame != shipFrame) { m_old_pos = ship_pos; - m_old_frame = ship->GetFrame(); + m_old_frame = shipFrame; } m_flybyOrient.Renormalize(); diff --git a/src/CityOnPlanet.cpp b/src/CityOnPlanet.cpp index 9ffc416e4..762f5a7f2 100644 --- a/src/CityOnPlanet.cpp +++ b/src/CityOnPlanet.cpp @@ -64,7 +64,8 @@ void CityOnPlanet::AddStaticGeomsToCollisionSpace() for (unsigned int i = 0; i < m_buildings.size(); i++) { if (i & skipMask) { } else { - m_frame->AddStaticGeom(m_buildings[i].geom); + Frame *f = Frame::GetFrame(m_frame); + f->AddStaticGeom(m_buildings[i].geom); m_enabledBuildings.push_back(m_buildings[i]); // Update building types ++(m_buildingCounts[m_buildings[i].instIndex]); @@ -79,7 +80,8 @@ void CityOnPlanet::RemoveStaticGeomsFromCollisionSpace() { m_enabledBuildings.clear(); for (unsigned int i = 0; i < m_buildings.size(); i++) { - m_frame->RemoveStaticGeom(m_buildings[i].geom); + Frame *f = Frame::GetFrame(m_frame); + f->RemoveStaticGeom(m_buildings[i].geom); } } @@ -190,7 +192,8 @@ CityOnPlanet::~CityOnPlanet() { // frame may be null (already removed from for (unsigned int i = 0; i < m_buildings.size(); i++) { - m_frame->RemoveStaticGeom(m_buildings[i].geom); + Frame *f = Frame::GetFrame(m_frame); + f->RemoveStaticGeom(m_buildings[i].geom); delete m_buildings[i].geom; } } diff --git a/src/CityOnPlanet.h b/src/CityOnPlanet.h index 23489bee8..18e1f1cc2 100644 --- a/src/CityOnPlanet.h +++ b/src/CityOnPlanet.h @@ -5,6 +5,7 @@ #define _CITYONPLANET_H #include "CollMesh.h" +#include "FrameId.h" #include "Object.h" #include "Random.h" @@ -53,7 +54,7 @@ private: }; Planet *m_planet; - Frame *m_frame; + FrameId m_frame; std::vector m_buildings; std::vector m_enabledBuildings; std::vector m_buildingCounts; diff --git a/src/DynamicBody.cpp b/src/DynamicBody.cpp index 7d77ca92a..61f33cb80 100644 --- a/src/DynamicBody.cpp +++ b/src/DynamicBody.cpp @@ -181,17 +181,18 @@ void DynamicBody::SetMass(double mass) m_angInertia = (2 / 5.0) * m_mass * m_massRadius * m_massRadius; } -void DynamicBody::SetFrame(Frame *f) +void DynamicBody::SetFrame(FrameId fId) { - ModelBody::SetFrame(f); + ModelBody::SetFrame(fId); // external forces will be wrong after frame transition m_externalForce = m_gravityForce = m_atmosForce = vector3d(0.0); } double DynamicBody::CalcAtmosphericDrag(double velSqr, double area, double coeff) const { - Body *body = GetFrame()->GetBody(); - if (!body || !GetFrame()->IsRotFrame() || !body->IsType(Object::PLANET)) + Frame *f = Frame::GetFrame(GetFrame()); + Body *body = f->GetBody(); + if (!body || !f->IsRotFrame() || !body->IsType(Object::PLANET)) return 0.0; Planet *planet = static_cast(body); double pressure, density; @@ -213,8 +214,9 @@ vector3d DynamicBody::CalcAtmosphericForce() const void DynamicBody::CalcExternalForce() { // gravity - if (!GetFrame()) return; // no external force if not in a frame - Body *body = GetFrame()->GetBody(); + Frame *f = Frame::GetFrame(GetFrame()); + if (!f) return; // no external force if not in a frame + Body *body = f->GetBody(); if (body && !body->IsType(Object::SPACESTATION)) { // they ought to have mass though... vector3d b1b2 = GetPosition(); double m1m2 = GetMass() * body->GetMass(); @@ -226,7 +228,7 @@ void DynamicBody::CalcExternalForce() m_gravityForce = m_externalForce; // atmospheric drag - if (body && GetFrame()->IsRotFrame() && body->IsType(Object::PLANET)) { + if (body && f->IsRotFrame() && body->IsType(Object::PLANET)) { vector3d fAtmoForce = CalcAtmosphericForce(); // make this a bit less daft at high time accel @@ -243,8 +245,8 @@ void DynamicBody::CalcExternalForce() m_atmosForce = vector3d(0.0); // centrifugal and coriolis forces for rotating frames - if (GetFrame()->IsRotFrame()) { - vector3d angRot(0, GetFrame()->GetAngSpeed(), 0); + if (f->IsRotFrame()) { + vector3d angRot(0, f->GetAngSpeed(), 0); m_externalForce -= m_mass * angRot.Cross(angRot.Cross(GetPosition())); // centrifugal m_externalForce -= 2 * m_mass * angRot.Cross(GetVelocity()); // coriolis } @@ -362,12 +364,13 @@ bool DynamicBody::OnCollision(Object *o, Uint32 flags, double relVel) // return parameters for orbit of any body, gives both elliptic and hyperbolic trajectories Orbit DynamicBody::ComputeOrbit() const { - const Frame *frame = this->GetFrame()->GetNonRotFrame(); - const double mass = frame->GetSystemBody()->GetMass(); + FrameId nrFrameId = Frame::GetFrame(GetFrame())->GetNonRotFrame(); + const Frame *nrFrame = Frame::GetFrame(nrFrameId); + const double mass = nrFrame->GetSystemBody()->GetMass(); // current velocity and position with respect to non-rotating frame - const vector3d vel = this->GetVelocityRelTo(frame); - const vector3d pos = this->GetPositionRelTo(frame); + const vector3d vel = GetVelocityRelTo(nrFrameId); + const vector3d pos = GetPositionRelTo(nrFrameId); return Orbit::FromBodyState(pos, vel, mass); } diff --git a/src/DynamicBody.h b/src/DynamicBody.h index 806756d70..1240949bd 100644 --- a/src/DynamicBody.h +++ b/src/DynamicBody.h @@ -25,7 +25,7 @@ public: virtual vector3d GetVelocity() const override; virtual void SetVelocity(const vector3d &v) override; - virtual void SetFrame(Frame *f) override; + virtual void SetFrame(FrameId fId) override; vector3d GetAngVelocity() const; void SetAngVelocity(const vector3d &v); virtual bool OnCollision(Object *o, Uint32 flags, double relVel) override; diff --git a/src/Frame.cpp b/src/Frame.cpp index 35a3d1c85..c96a94e79 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -12,7 +12,7 @@ std::list Frame::s_frames; -Frame::Frame(const Dummy &d, Frame *parent, const char *label, unsigned int flags, double radius): +Frame::Frame(const Dummy &d, FrameId parent, const char *label, unsigned int flags, double radius): m_sbody(nullptr), m_astroBody(nullptr), m_parent(parent), @@ -31,12 +31,16 @@ Frame::Frame(const Dummy &d, Frame *parent, const char *label, unsigned int flag ClearMovement(); m_collisionSpace = new CollisionSpace(); - if (m_parent) m_parent->AddChild(this); + if (IsIdValid(m_parent)) Frame::GetFrame(m_parent)->AddChild(m_thisId); if (label) m_label = label; } -void Frame::ToJson(Json &frameObj, Frame *f, Space *space) +void Frame::ToJson(Json &frameObj, FrameId fId, Space *space) { + Frame *f = Frame::GetFrame(fId); + + assert(f != nullptr); + frameObj["frameId"] = f->m_thisId; frameObj["flags"] = f->m_flags; frameObj["radius"] = f->m_radius; @@ -48,7 +52,7 @@ void Frame::ToJson(Json &frameObj, Frame *f, Space *space) frameObj["index_for_astro_body"] = space->GetIndexForBody(f->m_astroBody); Json childFrameArray = Json::array(); // Create JSON array to contain child frame data. - for (Frame *kid : f->GetChildren()) { + for (FrameId kid : f->GetChildren()) { Json childFrameArrayEl = Json::object(); // Create JSON object to contain child frame. Frame::ToJson(childFrameArrayEl, kid, space); childFrameArray.push_back(childFrameArrayEl); // Append child frame object to array. @@ -57,30 +61,46 @@ void Frame::ToJson(Json &frameObj, Frame *f, Space *space) frameObj["child_frames"] = childFrameArray; // Add child frame array to frame object. // Add sfx array to supplied object. - SfxManager::ToJson(frameObj, f); + SfxManager::ToJson(frameObj, f->m_thisId); } -Frame *Frame::CreateFrame(Frame *parent, const char *label, unsigned int flags, double radius) +Frame::~Frame() +{ + if (!d.madeWithFactory) { + Error("Frame instance deletion outside 'DeleteFrame'\n"); + } + // Delete this Frame and recurse deleting children + delete m_collisionSpace; + for (FrameId kid : m_children) { + DeleteFrame(kid); + } +} + +FrameId Frame::CreateFrame(FrameId parent, const char *label, unsigned int flags, double radius) { Dummy dummy; dummy.madeWithFactory = true; s_frames.emplace_back(dummy, parent, label, flags, radius); - return &s_frames.back(); + return (s_frames.size() - 1); } -Frame *Frame::FromJson(const Json &frameObj, Space *space, Frame *parent, double at_time) +FrameId Frame::FromJson(const Json &frameObj, Space *space, FrameId parent, double at_time) { Dummy dummy; dummy.madeWithFactory = true; // Set parent to nullptr here in order to avoid this frame // being a child twice (due to ctor calling AddChild) - s_frames.emplace_back(dummy, nullptr, nullptr); + s_frames.emplace_back(dummy, noFrameId, nullptr); Frame *f = &s_frames.back(); - f->m_parent = parent; + if (parent != noFrameId) + f->m_parent = Frame::GetFrame(parent)->GetId(); + else + f->m_parent = noFrameId; + f->d.madeWithFactory = false; try { @@ -104,7 +124,8 @@ Frame *Frame::FromJson(const Json &frameObj, Space *space, Frame *parent, double Json childFrameArray = frameObj["child_frames"]; f->m_children.reserve(childFrameArray.size()); for (unsigned int i = 0; i < childFrameArray.size(); ++i) { - f->m_children.push_back(FromJson(childFrameArray[i], space, f, at_time)); + FrameId kidId = FromJson(childFrameArray[i], space, f->m_thisId, at_time); + f->m_children.push_back(kidId); } } else { f->m_children.clear(); @@ -115,26 +136,26 @@ Frame *Frame::FromJson(const Json &frameObj, Space *space, Frame *parent, double throw SavedGameCorruptException(); } - SfxManager::FromJson(frameObj, f); + SfxManager::FromJson(frameObj, f->m_thisId); f->ClearMovement(); - return f; + return f->GetId(); } -void Frame::DeleteFrame(Frame *tobedeleted) +void Frame::DeleteFrame(FrameId tobedeleted) { - tobedeleted->d.madeWithFactory = true; + Frame *f = GetFrame(tobedeleted); + f->d.madeWithFactory = true; // Find Frame and delete it, let dtor delete its children for (std::list::const_iterator it = s_frames.begin(); it != s_frames.end(); it++) { - if (tobedeleted == &(*it)) { + if (f == &(*it)) { s_frames.erase(it); break; } } - tobedeleted->d.madeWithFactory = false; } -Frame *Frame::FindFrame(FrameId FId) +Frame *Frame::GetFrame(FrameId FId) { for (Frame &elem : s_frames) { if (elem.m_thisId == FId) return &elem; @@ -142,30 +163,22 @@ Frame *Frame::FindFrame(FrameId FId) return nullptr; } -void Frame::PostUnserializeFixup(Frame *f, Space *space) +void Frame::PostUnserializeFixup(FrameId fId, Space *space) { + Frame *f = Frame::GetFrame(fId); f->UpdateRootRelativeVars(); f->m_astroBody = space->GetBodyByIndex(f->m_astroBodyIndex); - for (Frame *kid : f->GetChildren()) + for (FrameId kid : f->GetChildren()) PostUnserializeFixup(kid, space); } -Frame::~Frame() -{ - if (!d.madeWithFactory) { - Error("Frame instance deletion outside 'DeleteFrame'\n"); - } - // Delete this Frame and recurse deleting children - delete m_collisionSpace; - for (Frame *kid : m_children) { - DeleteFrame(kid); - } -} - -void Frame::RemoveChild(Frame *f) +void Frame::RemoveChild(FrameId fId) { PROFILE_SCOPED() - const std::vector::iterator it = std::find(m_children.begin(), m_children.end(), f); + if (fId == noFrameId) return; + Frame *f = Frame::GetFrame(fId); + if (f == nullptr) return; + const std::vector::iterator it = std::find(m_children.begin(), m_children.end(), fId); if (it != m_children.end()) m_children.erase(it); } @@ -180,9 +193,11 @@ void Frame::SetPlanetGeom(double radius, Body *obj) } // doesn't consider stasis velocity -vector3d Frame::GetVelocityRelTo(const Frame *relTo) const +vector3d Frame::GetVelocityRelTo(FrameId relToId) const { - if (this == relTo) return vector3d(0, 0, 0); // early-out to avoid unnecessary computation + if (m_thisId == relToId) return vector3d(0, 0, 0); // early-out to avoid unnecessary computation + + const Frame *relTo = Frame::GetFrame(relToId); vector3d diff = m_rootVel - relTo->m_rootVel; if (relTo->IsRotFrame()) return diff * relTo->m_rootOrient; @@ -190,12 +205,15 @@ vector3d Frame::GetVelocityRelTo(const Frame *relTo) const return diff; } -vector3d Frame::GetPositionRelTo(const Frame *relTo) const +vector3d Frame::GetPositionRelTo(FrameId relToId) const { // early-outs for simple cases, required for accuracy in large systems - if (this == relTo) return vector3d(0, 0, 0); - if (GetParent() == relTo) return m_pos; // relative to parent - if (relTo->GetParent() == this) { // relative to child + if (m_thisId == relToId) return vector3d(0, 0, 0); + + const Frame *relTo = Frame::GetFrame(relToId); + + if (GetParent() == relToId) return m_pos; // relative to parent + if (relTo->GetParent() == m_thisId) { // relative to child if (!relTo->IsRotFrame()) return -relTo->m_pos; else @@ -216,12 +234,14 @@ vector3d Frame::GetPositionRelTo(const Frame *relTo) const return diff; } -vector3d Frame::GetInterpPositionRelTo(const Frame *relTo) const +vector3d Frame::GetInterpPositionRelTo(FrameId relToId) const { + const Frame *relTo = Frame::GetFrame(relToId); + // early-outs for simple cases, required for accuracy in large systems - if (this == relTo) return vector3d(0, 0, 0); - if (GetParent() == relTo) return m_interpPos; // relative to parent - if (relTo->GetParent() == this) { // relative to child + if (m_thisId == relToId) return vector3d(0, 0, 0); + if (GetParent() == relTo->GetId()) return m_interpPos; // relative to parent + if (relTo->GetParent() == m_thisId) { // relative to child if (!relTo->IsRotFrame()) return -relTo->m_interpPos; else @@ -241,16 +261,16 @@ vector3d Frame::GetInterpPositionRelTo(const Frame *relTo) const return diff; } -matrix3x3d Frame::GetOrientRelTo(const Frame *relTo) const +matrix3x3d Frame::GetOrientRelTo(FrameId relToId) const { - if (this == relTo) return matrix3x3d::Identity(); - return relTo->m_rootOrient.Transpose() * m_rootOrient; + if (m_thisId == relToId) return matrix3x3d::Identity(); + return Frame::GetFrame(relToId)->m_rootOrient.Transpose() * m_rootOrient; } -matrix3x3d Frame::GetInterpOrientRelTo(const Frame *relTo) const +matrix3x3d Frame::GetInterpOrientRelTo(FrameId relToId) const { - if (this == relTo) return matrix3x3d::Identity(); - return relTo->m_rootInterpOrient.Transpose() * m_rootInterpOrient; + if (m_thisId == relToId) return matrix3x3d::Identity(); + return Frame::GetFrame(relToId)->m_rootInterpOrient.Transpose() * m_rootInterpOrient; /* if (IsRotFrame()) { if (relTo->IsRotFrame()) return m_interpOrient * relTo->m_interpOrient.Transpose(); else return m_interpOrient; @@ -272,21 +292,24 @@ void Frame::UpdateInterpTransform(double alpha) } else m_interpOrient = m_orient; - if (!m_parent) + Frame *parent = Frame::GetFrame(m_parent); + if (!parent) ClearMovement(); else { - m_rootInterpPos = m_parent->m_rootInterpOrient * m_interpPos + m_parent->m_rootInterpPos; - m_rootInterpOrient = m_parent->m_rootInterpOrient * m_interpOrient; + m_rootInterpPos = parent->m_rootInterpOrient * m_interpPos + parent->m_rootInterpPos; + m_rootInterpOrient = parent->m_rootInterpOrient * m_interpOrient; } - for (Frame *kid : m_children) - kid->UpdateInterpTransform(alpha); + for (FrameId kid : m_children) { + Frame *kidFrame = Frame::GetFrame(kid); + kidFrame->UpdateInterpTransform(alpha); + } } -void Frame::GetFrameTransform(const Frame *fFrom, const Frame *fTo, matrix4x4d &m) +void Frame::GetFrameTransform(const FrameId fFromId, const FrameId fToId, matrix4x4d &m) { - matrix3x3d forient = fFrom->GetOrientRelTo(fTo); - vector3d fpos = fFrom->GetPositionRelTo(fTo); + matrix3x3d forient = Frame::GetFrame(fFromId)->GetOrientRelTo(fToId); + vector3d fpos = Frame::GetFrame(fFromId)->GetPositionRelTo(fToId); m = forient; m.SetTranslate(fpos); } @@ -307,7 +330,7 @@ void Frame::UpdateOrbitRails(double time, double timestep) m_oldAngDisplacement = m_angSpeed * timestep; // update frame position and velocity - if (m_parent && m_sbody && !IsRotFrame()) { + if (IsIdValid(m_parent) && m_sbody && !IsRotFrame()) { m_pos = m_sbody->GetOrbit().OrbitalPosAtTime(time); vector3d pos2 = m_sbody->GetOrbit().OrbitalPosAtTime(time + timestep); m_vel = (pos2 - m_pos) / timestep; @@ -324,8 +347,10 @@ void Frame::UpdateOrbitRails(double time, double timestep) } UpdateRootRelativeVars(); // update root-relative pos/vel/orient - for (Frame *kid : m_children) - kid->UpdateOrbitRails(time, timestep); + for (FrameId kid : m_children) { + Frame *kidFrame = Frame::GetFrame(kid); + kidFrame->UpdateOrbitRails(time, timestep); + } } void Frame::SetInitialOrient(const matrix3x3d &m, double time) @@ -355,12 +380,13 @@ void Frame::SetOrient(const matrix3x3d &m, double time) void Frame::UpdateRootRelativeVars() { // update pos & vel relative to parent frame - if (!m_parent) { + Frame *parent = Frame::GetFrame(m_parent); + if (!parent) { m_rootPos = m_rootVel = vector3d(0, 0, 0); m_rootOrient = matrix3x3d::Identity(); } else { - m_rootPos = m_parent->m_rootOrient * m_pos + m_parent->m_rootPos; - m_rootVel = m_parent->m_rootOrient * m_vel + m_parent->m_rootVel; - m_rootOrient = m_parent->m_rootOrient * m_orient; + m_rootPos = parent->m_rootOrient * m_pos + parent->m_rootPos; + m_rootVel = parent->m_rootOrient * m_vel + parent->m_rootVel; + m_rootOrient = parent->m_rootOrient * m_orient; } } diff --git a/src/Frame.h b/src/Frame.h index 6b88d9560..c6a427fa2 100644 --- a/src/Frame.h +++ b/src/Frame.h @@ -30,22 +30,22 @@ class Frame { public: Frame() = delete; - Frame(const Dummy &d, Frame *parent, const char *label, unsigned int flags = FLAG_DEFAULT, double radius = 0.0); + Frame(const Dummy &d, FrameId parent, const char *label, unsigned int flags = FLAG_DEFAULT, double radius = 0.0); ~Frame(); enum { FLAG_DEFAULT = (0), FLAG_ROTATING = (1 << 1), FLAG_HAS_ROT = (1 << 2) }; - static Frame *CreateFrame(Frame *parent, const char *label, unsigned int flags = FLAG_DEFAULT, double radius = 0.0); - static Frame *FromJson(const Json &jsonObj, Space *space, Frame *parent, double at_time); + static FrameId CreateFrame(FrameId parent, const char *label, unsigned int flags = FLAG_DEFAULT, double radius = 0.0); + static FrameId FromJson(const Json &jsonObj, Space *space, FrameId parent, double at_time); - static void ToJson(Json &jsonObj, Frame *f, Space *space); - static void PostUnserializeFixup(Frame *f, Space *space); + static void ToJson(Json &jsonObj, FrameId fId, Space *space); + static void PostUnserializeFixup(FrameId fId, Space *space); - static void DeleteFrame(Frame *tobedeleted); + static void DeleteFrame(FrameId tobedeleted); - static Frame *FindFrame(FrameId FId); + static Frame *GetFrame(FrameId FId); FrameId GetId() const {return m_thisId; } @@ -67,11 +67,9 @@ public: bool IsRotFrame() const { return m_flags & FLAG_ROTATING; } bool HasRotFrame() const { return m_flags & FLAG_HAS_ROT; } - Frame *GetParent() const { return m_parent; } - const Frame *GetNonRotFrame() const { return IsRotFrame() ? m_parent : this; } - Frame *GetNonRotFrame() { return IsRotFrame() ? m_parent : this; } - const Frame *GetRotFrame() const { return HasRotFrame() ? m_children.front() : this; } - Frame *GetRotFrame() { return HasRotFrame() ? m_children.front() : this; } + FrameId GetParent() const { return m_parent; } + FrameId GetNonRotFrame() { return IsRotFrame() ? m_parent : m_thisId; } + FrameId GetRotFrame() { return HasRotFrame() ? m_children.front() : m_thisId; } void SetBodies(SystemBody *s, Body *b) { @@ -81,12 +79,12 @@ public: SystemBody *GetSystemBody() const { return m_sbody; } Body *GetBody() const { return m_astroBody; } - void AddChild(Frame *f) { m_children.push_back(f); } - void RemoveChild(Frame *f); + void AddChild(FrameId fId) { m_children.push_back(fId); } + void RemoveChild(FrameId fId); bool HasChildren() const { return !m_children.empty(); } unsigned GetNumChildren() const { return static_cast(m_children.size()); } - IterationProxy> GetChildren() { return MakeIterationProxy(m_children); } - const IterationProxy> GetChildren() const { return MakeIterationProxy(m_children); } + IterationProxy> GetChildren() { return MakeIterationProxy(m_children); } + const IterationProxy> GetChildren() const { return MakeIterationProxy(m_children); } void AddGeom(Geom *); void RemoveGeom(Geom *); @@ -104,16 +102,16 @@ public: // must attain this velocity within rotating frame to be stationary. vector3d GetStasisVelocity(const vector3d &pos) const { return -vector3d(0, m_angSpeed, 0).Cross(pos); } - vector3d GetPositionRelTo(const Frame *relTo) const; - vector3d GetVelocityRelTo(const Frame *relTo) const; - matrix3x3d GetOrientRelTo(const Frame *relTo) const; + vector3d GetPositionRelTo(FrameId relTo) const; + vector3d GetVelocityRelTo(FrameId relTo) const; + matrix3x3d GetOrientRelTo(FrameId relTo) const; // Same as above except it does interpolation between // physics ticks so rendering is smooth above physics hz - vector3d GetInterpPositionRelTo(const Frame *relTo) const; - matrix3x3d GetInterpOrientRelTo(const Frame *relTo) const; + vector3d GetInterpPositionRelTo(FrameId relTo) const; + matrix3x3d GetInterpOrientRelTo(FrameId relTo) const; - static void GetFrameTransform(const Frame *fFrom, const Frame *fTo, matrix4x4d &m); + static void GetFrameTransform(FrameId fFrom, FrameId fTo, matrix4x4d &m); std::unique_ptr m_sfx; // the last survivor. actually m_children is pretty grim too. @@ -122,8 +120,8 @@ private: void UpdateRootRelativeVars(); - Frame *m_parent; // if parent is null then frame position is absolute - std::vector m_children; // child frames, first may be rotating + FrameId m_parent; // if parent is null then frame position is absolute + std::vector m_children; // child frames, first may be rotating SystemBody *m_sbody; // points to SBodies in Pi::current_system Body *m_astroBody; // if frame contains a star or planet or something diff --git a/src/FrameId.cpp b/src/FrameId.cpp new file mode 100644 index 000000000..315e55c9b --- /dev/null +++ b/src/FrameId.cpp @@ -0,0 +1,3 @@ +#include "FrameId.h" + +bool IsIdValid(FrameId fId) { return fId >= 0; } diff --git a/src/FrameId.h b/src/FrameId.h index 852a0a8be..0f86d92fa 100644 --- a/src/FrameId.h +++ b/src/FrameId.h @@ -5,4 +5,6 @@ typedef int FrameId; constexpr FrameId noFrameId = -1; +extern bool IsIdValid(FrameId fId); + #endif // FRAMEID_H_INCLUDED diff --git a/src/HudTrail.cpp b/src/HudTrail.cpp index e20edb466..05fb476fd 100644 --- a/src/HudTrail.cpp +++ b/src/HudTrail.cpp @@ -4,6 +4,7 @@ #include "HudTrail.h" #include "Body.h" +#include "Frame.h" #include "Pi.h" #include "graphics/Renderer.h" #include "graphics/RenderState.h" @@ -31,14 +32,15 @@ void HudTrail::Update(float time) m_updateTime += time; if (m_updateTime > UPDATE_INTERVAL) { m_updateTime = 0.f; - const Frame *bodyFrame = m_body->GetFrame(); + FrameId bodyFrameId = m_body->GetFrame(); + const Frame *bodyFrame = Frame::GetFrame(bodyFrameId); - if (!m_currentFrame) { - m_currentFrame = bodyFrame; + if (m_currentFrame < 0) { + m_currentFrame = bodyFrameId; m_trailPoints.clear(); } - if (bodyFrame == m_currentFrame) + if (bodyFrameId == m_currentFrame) m_trailPoints.push_back(m_body->GetInterpPosition()); } @@ -82,7 +84,7 @@ void HudTrail::Render(Graphics::Renderer *r) } } -void HudTrail::Reset(const Frame *newFrame) +void HudTrail::Reset(FrameId newFrame) { m_currentFrame = newFrame; m_trailPoints.clear(); diff --git a/src/HudTrail.h b/src/HudTrail.h index a469d257e..83e03b7c7 100644 --- a/src/HudTrail.h +++ b/src/HudTrail.h @@ -5,6 +5,7 @@ #define _HUDTRAIL_H #include "Color.h" +#include "FrameId.h" #include "matrix4x4.h" #include "graphics/Drawables.h" @@ -24,14 +25,14 @@ public: HudTrail(Body *b, const Color &); void Update(float time); void Render(Graphics::Renderer *r); - void Reset(const Frame *newFrame); + void Reset(const FrameId newFrame); void SetColor(const Color &c) { m_color = c; } void SetTransform(const matrix4x4d &t) { m_transform = t; } private: Body *m_body; - const Frame *m_currentFrame; + FrameId m_currentFrame; float m_updateTime; Color m_color; matrix4x4d m_transform; diff --git a/src/LuaBody.cpp b/src/LuaBody.cpp index e33ab4f11..6d3a3f707 100644 --- a/src/LuaBody.cpp +++ b/src/LuaBody.cpp @@ -405,7 +405,7 @@ static int l_body_attr_frame_body(lua_State *l) return 1; } - Frame *f = b->GetFrame(); + Frame *f = Frame::GetFrame(b->GetFrame()); LuaObject::PushToLua(f->GetBody()); return 1; } @@ -434,7 +434,7 @@ static int l_body_attr_frame_rotating(lua_State *l) return 1; } - Frame *f = b->GetFrame(); + Frame *f = Frame::GetFrame(b->GetFrame()); lua_pushboolean(l, f->IsRotFrame()); return 1; } @@ -548,7 +548,7 @@ static int l_body_get_ground_position(lua_State *l) return 1; } - Frame *f = b->GetFrame(); + Frame *f = Frame::GetFrame(b->GetFrame()); if (!f->IsRotFrame()) return 0; diff --git a/src/LuaPlayer.cpp b/src/LuaPlayer.cpp index 09db2baeb..43a90d508 100644 --- a/src/LuaPlayer.cpp +++ b/src/LuaPlayer.cpp @@ -515,13 +515,14 @@ static int l_get_gps(lua_State *l) Player *player = LuaObject::CheckFromLua(1); vector3d pos = Pi::player->GetPosition(); double center_dist = pos.Length(); - auto frame = player->GetFrame(); - if (frame) { - Body *astro = frame->GetBody(); + FrameId playerFrameId = player->GetFrame(); + Frame *playerFrame = Frame::GetFrame(playerFrameId); + if (IsIdValid(playerFrameId)) { + Body *astro = Frame::GetFrame(playerFrameId)->GetBody(); if (astro && astro->IsType(Object::TERRAINBODY)) { TerrainBody *terrain = static_cast(astro); - if (!frame->IsRotFrame()) - frame = frame->GetRotFrame(); + if (!playerFrame->IsRotFrame()) + playerFrame = Frame::GetFrame(playerFrame->GetRotFrame()); vector3d surface_pos = pos.Normalized(); double radius = 0.0; if (center_dist <= 3.0 * terrain->GetMaxFeatureRadius()) { diff --git a/src/LuaShip.cpp b/src/LuaShip.cpp index 1b7c5cf9d..4f17b52dc 100644 --- a/src/LuaShip.cpp +++ b/src/LuaShip.cpp @@ -938,7 +938,8 @@ static int l_ship_get_set_speed_target(lua_State *l) Ship *s = LuaObject::CheckFromLua(1); Body *t = s->GetController()->GetSetSpeedTarget(); if (s->GetType() == Object::Type::PLAYER && t == nullptr) { - Frame *f = s->GetFrame(); + FrameId fId = s->GetFrame(); + Frame *f = Frame::GetFrame(fId); if (f) t = f->GetBody(); } diff --git a/src/LuaSpace.cpp b/src/LuaSpace.cpp index e6efbe17d..931f68faa 100644 --- a/src/LuaSpace.cpp +++ b/src/LuaSpace.cpp @@ -225,7 +225,9 @@ static int l_space_spawn_ship_near(lua_State *l) Body *thing = _maybe_wrap_ship_with_cloud(ship, path, due); // XXX protect against spawning inside the body - Frame *newframe = nearbody->GetFrame(); + FrameId newframeId = nearbody->GetFrame(); + Frame *newframe = Frame::GetFrame(newframeId); + const vector3d newPosition = (MathUtil::RandomPointOnSphere(min_dist, max_dist) * 1000.0) + nearbody->GetPosition(); // If the frame is rotating and the chosen position is too far, use non-rotating parent. @@ -233,10 +235,10 @@ static int l_space_spawn_ship_near(lua_State *l) // rotating frame in the next update if (newframe->IsRotFrame() && newframe->GetRadius() < newPosition.Length()) { assert(newframe->GetParent()); - newframe = newframe->GetParent(); + newframe = Frame::GetFrame(newframe->GetParent()); } - thing->SetFrame(newframe); + thing->SetFrame(newframe->GetId()); ; thing->SetPosition(newPosition); thing->SetVelocity(newVelocity); @@ -505,7 +507,7 @@ static int l_space_spawn_ship_landed_near(lua_State *l) assert(ship); // XXX protect against spawning inside the body - Frame *newframe = nearbody->GetFrame()->GetRotFrame(); + Frame *newframe = Frame::GetFrame(Frame::GetFrame(nearbody->GetFrame())->GetRotFrame()); if (!newframe->IsRotFrame()) luaL_error(l, "Body must be in rotating frame"); SystemBody *sbody = newframe->GetSystemBody(); @@ -696,7 +698,9 @@ static int l_space_attr_root_system_body(lua_State *l) LUA_DEBUG_START(l); - LuaObject::PushToLua(Pi::game->GetSpace()->GetRootFrame()->GetSystemBody()); + FrameId rootId = Pi::game->GetSpace()->GetRootFrame(); + Frame *root = Frame::GetFrame(rootId); + LuaObject::PushToLua(root->GetSystemBody()); LUA_DEBUG_END(l, 1); diff --git a/src/ModelBody.cpp b/src/ModelBody.cpp index b1be7b5a6..d119aa2ab 100644 --- a/src/ModelBody.cpp +++ b/src/ModelBody.cpp @@ -92,7 +92,7 @@ ModelBody::ModelBody(const Json &jsonObj, Space *space) : ModelBody::~ModelBody() { - SetFrame(0); // Will remove geom from frame if necessary. + SetFrame(noFrameId); // Will remove geom from frame if necessary. DeleteGeoms(); //delete instanced model @@ -120,12 +120,13 @@ void ModelBody::SetStatic(bool isStatic) m_isStatic = isStatic; if (!m_geom) return; + Frame *f = Frame::GetFrame(GetFrame()); if (m_isStatic) { - GetFrame()->RemoveGeom(m_geom); - GetFrame()->AddStaticGeom(m_geom); + f->RemoveGeom(m_geom); + f->AddStaticGeom(m_geom); } else { - GetFrame()->RemoveStaticGeom(m_geom); - GetFrame()->AddGeom(m_geom); + f->RemoveStaticGeom(m_geom); + f->AddGeom(m_geom); } } @@ -140,8 +141,9 @@ void ModelBody::SetColliding(bool colliding) void ModelBody::RebuildCollisionMesh() { + Frame *f = Frame::GetFrame(GetFrame()); if (m_geom) { - if (GetFrame()) RemoveGeomsFromFrame(GetFrame()); + if (f) RemoveGeomsFromFrame(f); DeleteGeoms(); } @@ -167,7 +169,7 @@ void ModelBody::RebuildCollisionMesh() m_dynGeoms.push_back(dynG); } - if (GetFrame()) AddGeomsToFrame(GetFrame()); + if (f) AddGeomsToFrame(f); } void ModelBody::SetModel(const char *modelName) @@ -193,9 +195,6 @@ void ModelBody::SetPosition(const vector3d &p) { Body::SetPosition(p); MoveGeoms(GetOrient(), p); - - // for rebuild of static objects in collision space - if (m_isStatic) SetFrame(GetFrame()); } void ModelBody::SetOrient(const matrix3x3d &m) @@ -205,16 +204,18 @@ void ModelBody::SetOrient(const matrix3x3d &m) MoveGeoms(m2, GetPosition()); } -void ModelBody::SetFrame(Frame *f) +void ModelBody::SetFrame(FrameId fId) { - if (f == GetFrame()) return; + if (fId == GetFrame()) return; //remove collision geoms from old frame - if (GetFrame()) RemoveGeomsFromFrame(GetFrame()); + Frame *f = Frame::GetFrame(GetFrame()); + if (f) RemoveGeomsFromFrame(f); - Body::SetFrame(f); + Body::SetFrame(fId); //add collision geoms to new frame + f = Frame::GetFrame(GetFrame()); if (f) AddGeomsToFrame(f); } @@ -247,14 +248,16 @@ void ModelBody::AddGeomsToFrame(Frame *f) void ModelBody::RemoveGeomsFromFrame(Frame *f) { + if (f == nullptr) return; + if (m_isStatic) { - GetFrame()->RemoveStaticGeom(m_geom); + f->RemoveStaticGeom(m_geom); } else { - GetFrame()->RemoveGeom(m_geom); + f->RemoveGeom(m_geom); } for (auto it = m_dynGeoms.begin(); it != m_dynGeoms.end(); ++it) - GetFrame()->RemoveGeom(*it); + f->RemoveGeom(*it); } void ModelBody::MoveGeoms(const matrix4x4d &m, const vector3d &p) @@ -296,7 +299,7 @@ void ModelBody::CalcLighting(double &ambient, double &direct, const Camera *came const double minAmbient = 0.05; ambient = minAmbient; direct = 1.0; - Body *astro = GetFrame()->GetBody(); + Body *astro = Frame::GetFrame(GetFrame())->GetBody(); if (!(astro && astro->IsType(Object::PLANET))) return; diff --git a/src/ModelBody.h b/src/ModelBody.h index dcc1ccad9..5133393e7 100644 --- a/src/ModelBody.h +++ b/src/ModelBody.h @@ -6,6 +6,7 @@ #include "Body.h" #include "CollMesh.h" +#include "FrameId.h" class Shields; class Geom; @@ -29,7 +30,7 @@ public: virtual ~ModelBody(); void SetPosition(const vector3d &p) override; void SetOrient(const matrix3x3d &r) override; - virtual void SetFrame(Frame *f) override; + virtual void SetFrame(FrameId fId) override; // Colliding: geoms are checked against collision space void SetColliding(bool colliding); bool IsColliding() const { return m_colliding; } diff --git a/src/Pi.cpp b/src/Pi.cpp index 358ff9a2e..86b77ab0b 100644 --- a/src/Pi.cpp +++ b/src/Pi.cpp @@ -1426,7 +1426,7 @@ void Pi::MainLoop() for (Body *b : game->GetSpace()->GetBodies()) { b->UpdateInterpTransform(Pi::GetGameTickAlpha()); } - game->GetSpace()->GetRootFrame()->UpdateInterpTransform(Pi::GetGameTickAlpha()); + Frame::GetFrame(game->GetSpace()->GetRootFrame())->UpdateInterpTransform(Pi::GetGameTickAlpha()); currentView->Update(); currentView->Draw3D(); diff --git a/src/Player.cpp b/src/Player.cpp index db8b4e1f3..874d2edb0 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -306,9 +306,9 @@ int Player::GetManeuverTime() const vector3d Player::GetManeuverVelocity() const { - const Frame *frame = GetFrame(); + Frame *frame = Frame::GetFrame(GetFrame()); if (frame->IsRotFrame()) - frame = frame->GetNonRotFrame(); + frame = Frame::GetFrame(frame->GetNonRotFrame()); const SystemBody *systemBody = frame->GetSystemBody(); if (Pi::planner->GetOffsetVel().ExactlyEqual(vector3d(0, 0, 0))) { diff --git a/src/Projectile.cpp b/src/Projectile.cpp index 39e5c09f8..b26486fcc 100644 --- a/src/Projectile.cpp +++ b/src/Projectile.cpp @@ -220,7 +220,7 @@ double Projectile::GetRadius() const return sqrt(m_length * m_length + m_width * m_width); } -void MiningLaserSpawnTastyStuff(Frame *f, const SystemBody *asteroid, const vector3d &pos) +void MiningLaserSpawnTastyStuff(FrameId fId, const SystemBody *asteroid, const vector3d &pos) { lua_State *l = Lua::manager->GetLuaState(); @@ -244,7 +244,7 @@ void MiningLaserSpawnTastyStuff(Frame *f, const SystemBody *asteroid, const vect lua_pop(l, 1); LUA_DEBUG_END(l, 0); - cargo->SetFrame(f); + cargo->SetFrame(fId); cargo->SetPosition(pos); const double x = Pi::rng.Double(); vector3d dir = pos.Normalized(); @@ -259,7 +259,8 @@ void Projectile::StaticUpdate(const float timeStep) CollisionContact c; // Collision spaces don't store velocity, so dirvel-only is still wrong but less awful than dirvel+basevel vector3d vel = m_dirVel * timeStep; - GetFrame()->GetCollisionSpace()->TraceRay(GetPosition(), vel.Normalized(), vel.Length(), &c); + Frame *frame = Frame::GetFrame(GetFrame()); + frame->GetCollisionSpace()->TraceRay(GetPosition(), vel.Normalized(), vel.Length(), &c); if (c.userData1) { Object *o = static_cast(c.userData1); @@ -279,7 +280,7 @@ void Projectile::StaticUpdate(const float timeStep) if (m_mining) // mining lasers can break off chunks of terrain { // need to test for terrain hit - Planet *const planet = static_cast(GetFrame()->GetBody()); // cache the value even for the if statement + Planet *const planet = static_cast(frame->GetBody()); // cache the value even for the if statement if (planet && planet->IsType(Object::PLANET)) { vector3d pos = GetPosition(); double terrainHeight = planet->GetTerrainHeight(pos.Normalized()); diff --git a/src/Sensors.cpp b/src/Sensors.cpp index 939a79c56..5c901e726 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -138,7 +138,7 @@ void Sensors::Update(float time) it->distance = m_owner->GetPositionRelTo(it->body).Length(); it->trail->Update(time); } else { - it->trail->Reset(nullptr); + it->trail->Reset(noFrameId); } it->fresh = false; ++it; diff --git a/src/Sfx.cpp b/src/Sfx.cpp index 484318513..ea0102c77 100644 --- a/src/Sfx.cpp +++ b/src/Sfx.cpp @@ -128,8 +128,9 @@ SfxManager::SfxManager() } } -void SfxManager::ToJson(Json &jsonObj, const Frame *f) +void SfxManager::ToJson(Json &jsonObj, const FrameId fId) { + Frame *f = Frame::GetFrame(fId); Json sfxArray = Json::array(); // Create JSON array to contain sfx data. if (f->m_sfx) { @@ -148,10 +149,12 @@ void SfxManager::ToJson(Json &jsonObj, const Frame *f) jsonObj["sfx_array"] = sfxArray; // Add sfx array to supplied object. } -void SfxManager::FromJson(const Json &jsonObj, Frame *f) +void SfxManager::FromJson(const Json &jsonObj, FrameId fId) { Json sfxArray = jsonObj["sfx_array"].get(); + Frame *f = Frame::GetFrame(fId); + if (sfxArray.size()) f->m_sfx.reset(new SfxManager); for (unsigned int i = 0; i < sfxArray.size(); ++i) { Sfx inst(sfxArray[i]); @@ -159,8 +162,10 @@ void SfxManager::FromJson(const Json &jsonObj, Frame *f) } } -SfxManager *SfxManager::AllocSfxInFrame(Frame *f) +SfxManager *SfxManager::AllocSfxInFrame(FrameId fId) { + Frame *f = Frame::GetFrame(fId); + if (!f->m_sfx) { f->m_sfx.reset(new SfxManager); } @@ -201,9 +206,12 @@ void SfxManager::AddThrustSmoke(const Body *b, const float speed, const vector3d sfxman->AddInstance(sfx); } -void SfxManager::TimeStepAll(const float timeStep, Frame *f) +void SfxManager::TimeStepAll(const float timeStep, FrameId fId) { PROFILE_SCOPED() + + Frame *f = Frame::GetFrame(fId); + if (f->m_sfx) { for (size_t t = TYPE_EXPLOSION; t < TYPE_NONE; t++) { for (size_t i = 0; i < f->m_sfx->GetNumberInstances(SFX_TYPE(t)); i++) { @@ -214,7 +222,7 @@ void SfxManager::TimeStepAll(const float timeStep, Frame *f) f->m_sfx->Cleanup(); } - for (Frame *kid : f->GetChildren()) { + for (FrameId kid : f->GetChildren()) { TimeStepAll(timeStep, kid); } } @@ -235,12 +243,14 @@ void SfxManager::Cleanup() } } -void SfxManager::RenderAll(Renderer *renderer, Frame *f, const Frame *camFrame) +void SfxManager::RenderAll(Renderer *renderer, FrameId fId, FrameId camFrameId) { + Frame *f = Frame::GetFrame(fId); + PROFILE_SCOPED() if (f->m_sfx) { matrix4x4d ftran; - Frame::GetFrameTransform(f, camFrame, ftran); + Frame::GetFrameTransform(fId, camFrameId, ftran); for (size_t t = TYPE_EXPLOSION; t < TYPE_NONE; t++) { const size_t numInstances = f->m_sfx->GetNumberInstances(SFX_TYPE(t)); @@ -292,8 +302,8 @@ void SfxManager::RenderAll(Renderer *renderer, Frame *f, const Frame *camFrame) } } - for (Frame *kid : f->GetChildren()) { - RenderAll(renderer, kid, camFrame); + for (FrameId kid : f->GetChildren()) { + RenderAll(renderer, kid, camFrameId); } } diff --git a/src/Sfx.h b/src/Sfx.h index 52f3a41db..2d10e91ed 100644 --- a/src/Sfx.h +++ b/src/Sfx.h @@ -4,6 +4,7 @@ #ifndef _SFX_H #define _SFX_H +#include "FrameId.h" #include "graphics/Material.h" #include "JsonFwd.h" @@ -54,10 +55,10 @@ public: static void Add(const Body *, SFX_TYPE); static void AddExplosion(Body *); static void AddThrustSmoke(const Body *b, float speed, const vector3d &adjustpos); - static void TimeStepAll(const float timeStep, Frame *f); - static void RenderAll(Graphics::Renderer *r, Frame *f, const Frame *camFrame); - static void ToJson(Json &jsonObj, const Frame *f); - static void FromJson(const Json &jsonObj, Frame *f); + static void TimeStepAll(const float timeStep, FrameId f); + static void RenderAll(Graphics::Renderer *r, FrameId f, const FrameId camFrame); + static void ToJson(Json &jsonObj, const FrameId f); + static void FromJson(const Json &jsonObj, FrameId f); //create shared models static void Init(Graphics::Renderer *r); @@ -92,7 +93,7 @@ private: }; // methods - static SfxManager *AllocSfxInFrame(Frame *f); + static SfxManager *AllocSfxInFrame(FrameId f); static vector2f CalculateOffset(const enum SFX_TYPE, const Sfx &); static bool SplitMaterialData(const std::string &spec, MaterialData &output); diff --git a/src/Ship.cpp b/src/Ship.cpp index 9537b6ae1..5e7a8f9c9 100644 --- a/src/Ship.cpp +++ b/src/Ship.cpp @@ -889,8 +889,12 @@ void Ship::Blastoff() if (m_flightState != LANDED) return; vector3d up = GetPosition().Normalized(); - assert(GetFrame()->GetBody()->IsType(Object::PLANET)); - const double planetRadius = 2.0 + static_cast(GetFrame()->GetBody())->GetTerrainHeight(up); + + Frame *f = Frame::GetFrame(GetFrame()); + + assert(f->GetBody()->IsType(Object::PLANET)); + + const double planetRadius = 2.0 + static_cast(f->GetBody())->GetTerrainHeight(up); SetVelocity(vector3d(0, 0, 0)); SetAngVelocity(vector3d(0, 0, 0)); SetFlightState(FLYING); @@ -898,7 +902,7 @@ void Ship::Blastoff() SetPosition(up * planetRadius - GetAabb().min.y * up); SetThrusterState(1, 1.0); // thrust upwards - LuaEvent::Queue("onShipTakeOff", this, GetFrame()->GetBody()); + LuaEvent::Queue("onShipTakeOff", this, f->GetBody()); } void Ship::TestLanded() @@ -906,10 +910,13 @@ void Ship::TestLanded() m_testLanded = false; if (m_launchLockTimeout > 0.0f) return; if (m_wheelState < 1.0f) return; - if (GetFrame()->GetBody()->IsType(Object::PLANET)) { + + Frame *f = Frame::GetFrame(GetFrame()); + + if (f->GetBody()->IsType(Object::PLANET)) { double speed = GetVelocity().Length(); vector3d up = GetPosition().Normalized(); - const double planetRadius = static_cast(GetFrame()->GetBody())->GetTerrainHeight(up); + const double planetRadius = static_cast(f->GetBody())->GetTerrainHeight(up); if (speed < MAX_LANDING_SPEED) { // check player is sortof sensibly oriented for landing @@ -926,7 +933,7 @@ void Ship::TestLanded() ClearThrusterState(); SetFlightState(LANDED); Sound::BodyMakeNoise(this, "Rough_Landing", 1.0f); - LuaEvent::Queue("onShipLanded", this, GetFrame()->GetBody()); + LuaEvent::Queue("onShipLanded", this, f->GetBody()); onLanded.emit(); } } @@ -937,8 +944,10 @@ void Ship::SetLandedOn(Planet *p, float latitude, float longitude) { m_wheelTransition = 0; m_wheelState = 1.0f; - Frame *f = p->GetFrame()->GetRotFrame(); - SetFrame(f); + Frame *f_non_rot = Frame::GetFrame(p->GetFrame()); + Frame *f = Frame::GetFrame(f_non_rot->GetRotFrame()); + SetFrame(f_non_rot->GetRotFrame()); + vector3d up = vector3d(cos(latitude) * sin(longitude), sin(latitude), cos(latitude) * cos(longitude)); const double planetRadius = p->GetTerrainHeight(up); SetPosition(up * (planetRadius - GetAabb().min.y)); @@ -952,9 +961,9 @@ void Ship::SetLandedOn(Planet *p, float latitude, float longitude) onLanded.emit(); } -void Ship::SetFrame(Frame *f) +void Ship::SetFrame(FrameId fId) { - DynamicBody::SetFrame(f); + DynamicBody::SetFrame(fId); m_sensors->ResetTrails(); } @@ -1181,7 +1190,8 @@ void Ship::StaticUpdate(const float timeStep) } if (m_flightState == FLYING) { - Body *astro = GetFrame()->GetBody(); + Frame *frame = Frame::GetFrame(GetFrame()); + Body *astro = frame->GetBody(); if (astro && astro->IsType(Object::PLANET)) { Planet *p = static_cast(astro); double dist = GetPosition().Length(); @@ -1204,7 +1214,8 @@ void Ship::StaticUpdate(const float timeStep) int capacity = 0; Properties().Get("fuel_scoop_cap", capacity); if (m_flightState == FLYING && capacity > 0) { - Body *astro = GetFrame()->GetBody(); + Frame *frame = Frame::GetFrame(GetFrame()); + Body *astro = frame->GetBody(); if (astro && astro->IsType(Object::PLANET)) { Planet *p = static_cast(astro); if (p->GetSystemBody()->IsScoopable()) { diff --git a/src/Ship.h b/src/Ship.h index cc1c0ac4b..9264cdd0f 100644 --- a/src/Ship.h +++ b/src/Ship.h @@ -65,7 +65,7 @@ public: Ship(const ShipType::Id &shipId); virtual ~Ship(); - virtual void SetFrame(Frame *f) override; + virtual void SetFrame(FrameId fId) override; void SetController(ShipController *c); //deletes existing ShipController *GetController() const { return m_controller; } diff --git a/src/ShipAICmd.cpp b/src/ShipAICmd.cpp index 44bff373e..09698b6a6 100644 --- a/src/ShipAICmd.cpp +++ b/src/ShipAICmd.cpp @@ -665,8 +665,9 @@ static double MaxEffectRad(Body *body, Propulsion *prop) } // returns acceleration due to gravity at that point -static double GetGravityAtPos(Frame *targframe, const vector3d &posoff) +static double GetGravityAtPos(FrameId targframeId, const vector3d &posoff) { + Frame *targframe = Frame::GetFrame(targframeId); Body *body = targframe->GetBody(); if (!body || body->IsType(Object::SPACESTATION)) return 0; double rsqr = posoff.LengthSqr(); @@ -675,31 +676,33 @@ static double GetGravityAtPos(Frame *targframe, const vector3d &posoff) } // gets position of (target + offset in target's frame) in frame -static vector3d GetPosInFrame(Frame *frame, Frame *target, const vector3d &offset) +static vector3d GetPosInFrame(FrameId frameId, FrameId targetId, const vector3d &offset) { - return target->GetOrientRelTo(frame) * offset + target->GetPositionRelTo(frame); + Frame *target = Frame::GetFrame(targetId); + return target->GetOrientRelTo(frameId) * offset + target->GetPositionRelTo(frameId); } -static vector3d GetVelInFrame(Frame *frame, Frame *target, const vector3d &offset) +static vector3d GetVelInFrame(FrameId frameId, FrameId targetId, const vector3d &offset) { vector3d vel = vector3d(0.0); - if (target != frame && target->IsRotFrame()) { + Frame* target = Frame::GetFrame(targetId); + if (targetId != frameId && target->IsRotFrame()) { // double ang = Pi::game->GetTimeStep() * target->GetAngSpeed(); // vector3d newpos = offset * matrix3x3d::RotateYMatrix(ang); // vel = (newpos - offset) / Pi::game->GetTimeStep(); vel = -target->GetStasisVelocity(offset); // stasis velocity not accurate enough } - return target->GetOrientRelTo(frame) * vel + target->GetVelocityRelTo(frame); + return target->GetOrientRelTo(frameId) * vel + target->GetVelocityRelTo(frameId); } // generates from (0,0,0) to spos, in plane of target // formula uses similar triangles // shiptarg in ship's frame // output in targframe -static vector3d GenerateTangent(DynamicBody *dBody, Frame *targframe, const vector3d &shiptarg, double alt) +static vector3d GenerateTangent(DynamicBody *dBody, FrameId targframeId, const vector3d &shiptarg, double alt) { - vector3d spos = dBody->GetPositionRelTo(targframe); - vector3d targ = GetPosInFrame(targframe, dBody->GetFrame(), shiptarg); + vector3d spos = dBody->GetPositionRelTo(targframeId); + vector3d targ = GetPosInFrame(targframeId, dBody->GetFrame(), shiptarg); double a = spos.Length(), b = alt; if (b * 1.02 > a) { spos *= b * 1.02 / a; @@ -723,7 +726,7 @@ static int CheckCollision(DynamicBody *dBody, const vector3d &pathdir, double pa assert(prop != nullptr); // ship is in obstructor's frame anyway, so is tpos if (pathdist < 100.0) return 0; - Body *body = dBody->GetFrame()->GetBody(); + Body *body = Frame::GetFrame(dBody->GetFrame())->GetBody(); if (!body) return 0; vector3d spos = dBody->GetPosition(); double tlen = tpos.Length(), slen = spos.Length(); @@ -776,22 +779,26 @@ static int CheckCollision(DynamicBody *dBody, const vector3d &pathdir, double pa // ok, need thing to step down through bodies and find closest approach // modify targpos directly to aim short of dangerous bodies -static bool ParentSafetyAdjust(DynamicBody *dBody, Frame *targframe, vector3d &targpos, vector3d &targvel) +static bool ParentSafetyAdjust(DynamicBody *dBody, FrameId targframeId, vector3d &targpos, vector3d &targvel) { - Body *body = 0; - Frame *frame = targframe->GetNonRotFrame(); + Body *body = nullptr; + FrameId frameId = Frame::GetFrame(targframeId)->GetNonRotFrame(); + Frame *frame = Frame::GetFrame(frameId); while (frame) { - if (dBody->GetFrame()->GetNonRotFrame() == frame) break; // ship in frame, stop + Frame *bFrame = Frame::GetFrame(dBody->GetFrame()); + if (bFrame->GetNonRotFrame() == frameId) break; // ship in frame, stop if (frame->GetBody()) body = frame->GetBody(); // ignore grav points? - double sdist = dBody->GetPositionRelTo(frame).Length(); + double sdist = dBody->GetPositionRelTo(frameId).Length(); if (sdist < frame->GetRadius()) break; // ship inside frame, stop // we should always be inside the root frame, so if we're not inside 'frame' // then it must not be the root frame (ie, it must have a parent) - assert(frame->GetParent()); + Frame *parent = Frame::GetFrame(frame->GetParent()); + assert(parent); - frame = frame->GetParent()->GetNonRotFrame(); // check next frame down + frameId = parent->GetNonRotFrame(); + frame = Frame::GetFrame(frameId); // check next frame down } if (!body) return false; @@ -812,7 +819,7 @@ static bool ParentSafetyAdjust(DynamicBody *dBody, Frame *targframe, vector3d &t // tandir is normal vector from planet to target pos or dir static bool CheckSuicide(DynamicBody *dBody, const vector3d &tandir) { - Body *body = dBody->GetFrame()->GetBody(); + Body *body = Frame::GetFrame(dBody->GetFrame())->GetBody(); if (dBody->Have(DynamicBody::PROPULSION)) return false; Propulsion *prop = dBody->GetPropulsion(); assert(prop != nullptr); @@ -842,15 +849,15 @@ void AICmdFlyTo::GetStatusText(char *str) m_target->GetLabel().c_str(), m_dist, m_state); else snprintf(str, 255, "FlyTo: %s, dist %.1fkm, endvel %.1fkm/s, state %i", - m_targframe->GetLabel().c_str(), m_posoff.Length() / 1000.0, m_endvel / 1000.0, m_state); + Frame::GetFrame(m_targframeId)->GetLabel().c_str(), m_posoff.Length() / 1000.0, m_endvel / 1000.0, m_state); } void AICmdFlyTo::PostLoadFixup(Space *space) { AICommand::PostLoadFixup(space); m_target = space->GetBodyByIndex(m_targetIndex); - m_targframe = Frame::FindFrame(m_targframeIndex); m_lockhead = true; + m_frameId = m_target ? m_target->GetFrame() : noFrameId; // Ensure needed sub-system: m_prop.Reset(m_dBody->GetPropulsion()); assert(m_prop != nullptr); @@ -862,7 +869,7 @@ AICmdFlyTo::AICmdFlyTo(DynamicBody *dBody, Body *target) : { m_prop.Reset(dBody->GetPropulsion()); assert(m_prop != nullptr); - m_frame = 0; + m_frameId = noFrameId; m_state = -6; m_lockhead = true; m_endvel = 0; @@ -876,27 +883,27 @@ AICmdFlyTo::AICmdFlyTo(DynamicBody *dBody, Body *target) : if (target->IsType(Object::SPACESTATION) && static_cast(target)->IsGroundStation()) { m_posoff = target->GetPosition() + VICINITY_MIN * target->GetOrient().VectorY(); // m_posoff += 500.0 * target->GetOrient().VectorX(); - m_targframe = target->GetFrame(); - m_target = 0; + m_targframeId = target->GetFrame(); + m_target = nullptr; } else { m_target = target; - m_targframe = 0; + m_targframeId = noFrameId; } - if (dBody->GetPositionRelTo(target).Length() <= VICINITY_MIN) m_targframe = 0; + if (dBody->GetPositionRelTo(target).Length() <= VICINITY_MIN) m_targframeId = noFrameId; } // Specified pos, endvel should be > 0 -AICmdFlyTo::AICmdFlyTo(DynamicBody *dBody, Frame *targframe, const vector3d &posoff, double endvel, bool tangent) : +AICmdFlyTo::AICmdFlyTo(DynamicBody *dBody, FrameId targframe, const vector3d &posoff, double endvel, bool tangent) : AICommand(dBody, CMD_FLYTO), m_target(nullptr), - m_targframe(targframe), + m_targframeId(targframe), m_posoff(posoff), m_endvel(endvel), m_tangent(tangent), m_state(-6), m_lockhead(true), - m_frame(nullptr) + m_frameId(noFrameId) { m_prop.Reset(dBody->GetPropulsion()); assert(m_prop != nullptr); @@ -908,7 +915,7 @@ AICmdFlyTo::AICmdFlyTo(const Json &jsonObj) : try { m_targetIndex = jsonObj["index_for_target"]; m_dist = jsonObj["dist"]; - m_targframeIndex = jsonObj["index_for_target_frame"]; + m_targframeId = jsonObj["target_frame"]; m_posoff = jsonObj["pos_off"]; m_endvel = jsonObj["end_vel"]; m_tangent = jsonObj["tangent"]; @@ -927,7 +934,7 @@ void AICmdFlyTo::SaveToJson(Json &jsonObj) AICommand::SaveToJson(aiCommandObj); aiCommandObj["index_for_target"] = Pi::game->GetSpace()->GetIndexForBody(m_target); aiCommandObj["dist"] = m_dist; - aiCommandObj["index_for_target_frame"] = (m_targframe != nullptr ? m_targframe->GetId() : noFrameId); + aiCommandObj["target_frame"] = m_targframeId; aiCommandObj["pos_off"] = m_posoff; aiCommandObj["end_vel"] = m_endvel; aiCommandObj["tangent"] = m_tangent; @@ -956,7 +963,7 @@ bool AICmdFlyTo::TimeStepUpdate() // may be an exploration probe ;-) return false; } - if (!m_target && !m_targframe) return true; // deleted object + if (!m_target && !IsIdValid(m_targframeId)) return true; // deleted object // generate base target pos (with vicinity adjustment) & vel double timestep = Pi::game->GetTimeStep(); @@ -966,11 +973,11 @@ bool AICmdFlyTo::TimeStepUpdate() targpos -= (targpos - m_dBody->GetPosition()).NormalizedSafe() * m_dist; targvel = m_target->GetVelocityRelTo(m_dBody->GetFrame()); } else { - targpos = GetPosInFrame(m_dBody->GetFrame(), m_targframe, m_posoff); - targvel = GetVelInFrame(m_dBody->GetFrame(), m_targframe, m_posoff); + targpos = GetPosInFrame(m_dBody->GetFrame(), m_targframeId, m_posoff); + targvel = GetVelInFrame(m_dBody->GetFrame(), m_targframeId, m_posoff); } - Frame *targframe = m_target ? m_target->GetFrame() : m_targframe; - ParentSafetyAdjust(m_dBody, targframe, targpos, targvel); + FrameId targframeId = m_target ? m_target->GetFrame() : m_targframeId; + ParentSafetyAdjust(m_dBody, targframeId, targpos, targvel); vector3d relpos = targpos - m_dBody->GetPosition(); vector3d reldir = relpos.NormalizedSafe(); vector3d relvel = targvel - m_dBody->GetVelocity(); @@ -983,20 +990,21 @@ bool AICmdFlyTo::TimeStepUpdate() #endif // frame switch stuff - clear children/collision state - if (m_frame != m_dBody->GetFrame()) { + if (m_frameId != m_dBody->GetFrame()) { if (m_child) { m_child.reset(); } - if (m_tangent && m_frame) return true; // regen tangent on frame switch + if (m_tangent && IsIdValid(m_frameId)) return true; // regen tangent on frame switch m_reldir = reldir; // for +vel termination condition - m_frame = m_dBody->GetFrame(); + m_frameId = m_dBody->GetFrame(); } // TODO: collision needs to be processed according to vdiff, not reldir? - Body *body = m_frame->GetBody(); + Body *body = Frame::GetFrame(m_frameId)->GetBody(); double erad = MaxEffectRad(body, m_prop.Get()); - if ((m_target && body != m_target) || (m_targframe && (!m_tangent || body != m_targframe->GetBody()))) { + Frame *targframe = Frame::GetFrame(targframeId); + if ((m_target && body != m_target) || (targframe && (!m_tangent || body != targframe->GetBody()))) { int coll = CheckCollision(m_dBody, reldir, targdist, targpos, m_endvel, erad); if (coll == 0) { // no collision if (m_child) { @@ -1006,7 +1014,7 @@ bool AICmdFlyTo::TimeStepUpdate() double ang = m_prop->AIFaceDirection(m_dBody->GetPosition()); m_prop->AIMatchVel(ang < 0.05 ? 1000.0 * m_dBody->GetPosition().Normalized() : vector3d(0.0)); } else { // same thing for 2/3/4 - if (!m_child) m_child.reset(new AICmdFlyAround(m_dBody, m_frame->GetBody(), erad * 1.05, 0.0)); + if (!m_child) m_child.reset(new AICmdFlyAround(m_dBody, Frame::GetFrame(m_frameId)->GetBody(), erad * 1.05, 0.0)); static_cast(m_child.get())->SetTargPos(targpos); ProcessChild(); } @@ -1030,7 +1038,7 @@ bool AICmdFlyTo::TimeStepUpdate() // target ship acceleration adjustment if (m_target && m_target->IsType(Object::SHIP)) { Ship *targship = static_cast(m_target); - matrix3x3d orient = m_target->GetFrame()->GetOrientRelTo(m_frame); + matrix3x3d orient = Frame::GetFrame(m_target->GetFrame())->GetOrientRelTo(m_frameId); vector3d targaccel = orient * targship->GetLastForce() / m_target->GetMass(); // fudge: targets accelerating towards you are usually going to flip if (targaccel.Dot(reldir) < 0.0 && !targship->IsDecelerating()) targaccel *= 0.5; @@ -1068,8 +1076,8 @@ bool AICmdFlyTo::TimeStepUpdate() if (ispeed > curspeed && curspeed > 0.9 * fuelspeed) ispeed = curspeed; // Don't exit a frame faster than some fraction of radius - // double maxframespeed = 0.2 * m_frame->GetRadius() / timestep; - // if (m_frame->GetParent() && ispeed > maxframespeed) ispeed = maxframespeed; + // double maxframespeed = 0.2 * m_frameId->GetRadius() / timestep; + // if (m_frameId->GetParent() && ispeed > maxframespeed) ispeed = maxframespeed; // cap perpspeed according to what's needed now perpspeed = std::min(perpspeed, 2.0 * sidefactor * timestep); @@ -1167,7 +1175,7 @@ AICmdDock::AICmdDock(DynamicBody *dBody, SpaceStation *target) : double grav = GetGravityAtPos(m_target->GetFrame(), m_target->GetPosition()); if (m_prop->GetAccelUp() < grav) { m_dBody->AIMessage(Ship::AIERROR_GRAV_TOO_HIGH); - m_target = 0; // bail out on next timestep call + m_target = nullptr; // bail out on next timestep call } } @@ -1238,8 +1246,8 @@ bool AICmdDock::TimeStepUpdate() } // if we're not close to target, do a flyto first - double targdist = m_target->GetPositionRelTo(ship).Length(); - if (targdist > 16000.0) { + double targdist = m_target->GetPositionRelTo(ship).LengthSqr(); + if (targdist > 16000.0 * 16000.0) { m_child.reset(new AICmdFlyTo(m_dBody, m_target)); ProcessChild(); return false; @@ -1324,7 +1332,7 @@ bool AICmdDock::TimeStepUpdate() #ifdef DEBUG_AUTOPILOT Output("AICmdDock dist = %.1f, speed = %.1f, ythrust = %.2f, state = %i\n", - targdist, relvel.Length(), m_ship->GetLinThrusterState().y, m_state); + sqrt(targdist), relvel.Length(), m_ship->GetLinThrusterState().y, m_state); #endif return false; @@ -1384,7 +1392,9 @@ void AICmdFlyAround::Setup(Body *obstructor, double alt, double vel, int mode) // drag within frame because orbits are impossible otherwise // timestep code also doesn't work correctly for ex-frame cases, should probably be fixed - alt = std::min(alt, 0.95 * obstructor->GetFrame()->GetNonRotFrame()->GetRadius()); + Frame *obsFrame = Frame::GetFrame(obstructor->GetFrame()); + Frame *nonRot = Frame::GetFrame(obsFrame->GetNonRotFrame()); + alt = std::min(alt, 0.95 * nonRot->GetRadius()); // generate suitable velocity if none provided double minacc = (mode == 2) ? 0 : m_prop->GetAccelMin(); @@ -1493,16 +1503,16 @@ bool AICmdFlyAround::TimeStepUpdate() // if too far away, fly to tangent if (obsdist > 1.1 * m_alt) { double v; - Frame *obsframe = m_obstructor->GetFrame()->GetNonRotFrame(); - vector3d tangent = GenerateTangent(m_dBody, obsframe, targpos, m_alt); - vector3d tpos_obs = GetPosInFrame(obsframe, m_dBody->GetFrame(), targpos); + FrameId obsframeId = Frame::GetFrame(m_obstructor->GetFrame())->GetNonRotFrame(); + vector3d tangent = GenerateTangent(m_dBody, obsframeId, targpos, m_alt); + vector3d tpos_obs = GetPosInFrame(obsframeId, m_dBody->GetFrame(), targpos); if (m_targmode) v = m_vel; else if (relpos.LengthSqr() < obsdist + tpos_obs.LengthSqr()) v = 0.0; else v = MaxVel((tpos_obs - tangent).Length(), tpos_obs.Length()); - m_child.reset(new AICmdFlyTo(m_dBody, obsframe, tangent, v, true)); + m_child.reset(new AICmdFlyTo(m_dBody, obsframeId, tangent, v, true)); ProcessChild(); return false; } @@ -1632,7 +1642,7 @@ bool AICmdFormation::TimeStepUpdate() vector3d reldir = (targdist < 1e-16) ? vector3d(1, 0, 0) : relpos / targdist; // adjust for target acceleration - matrix3x3d forient = m_target->GetFrame()->GetOrientRelTo(m_dBody->GetFrame()); + matrix3x3d forient = Frame::GetFrame(m_target->GetFrame())->GetOrientRelTo(m_dBody->GetFrame()); vector3d targaccel = forient * m_target->GetLastForce() / m_target->GetMass(); relvel -= targaccel * Pi::game->GetTimeStep(); double maxdecel = m_prop->GetAccelFwd() + targaccel.Dot(reldir); diff --git a/src/ShipAICmd.h b/src/ShipAICmd.h index 05d4ab6ea..e58c67684 100644 --- a/src/ShipAICmd.h +++ b/src/ShipAICmd.h @@ -8,10 +8,10 @@ #include "JsonFwd.h" #include "DynamicBody.h" +#include "FrameId.h" #include "FixedGuns.h" #include "ship/Propulsion.h" -class Frame; class Ship; class Space; class SpaceStation; @@ -119,7 +119,7 @@ private: class AICmdFlyTo : public AICommand { public: virtual bool TimeStepUpdate(); - AICmdFlyTo(DynamicBody *dBody, Frame *targframe, const vector3d &posoff, double endvel, bool tangent); + AICmdFlyTo(DynamicBody *dBody, FrameId targframeId, const vector3d &posoff, double endvel, bool tangent); AICmdFlyTo(DynamicBody *dBody, Body *target); virtual void GetStatusText(char *str); @@ -132,16 +132,16 @@ public: private: Body *m_target; // target for vicinity. Either this or targframe is 0 double m_dist; // vicinity distance - Frame *m_targframe; // target frame for waypoint + FrameId m_targframeId; // target frame for waypoint vector3d m_posoff; // offset in target frame double m_endvel; // target speed in direction of motion at end of path, positive only bool m_tangent; // true if path is to a tangent of the target frame's body int m_state; bool m_lockhead; - int m_targetIndex, m_targframeIndex; // used during deserialisation + int m_targetIndex; // used during deserialisation vector3d m_reldir; // target direction relative to ship at last frame change - Frame *m_frame; // last frame of ship + FrameId m_frameId; // last frame of ship }; class AICmdFlyAround : public AICommand { diff --git a/src/ShipCockpit.cpp b/src/ShipCockpit.cpp index 0d240bac3..3f4541a2c 100644 --- a/src/ShipCockpit.cpp +++ b/src/ShipCockpit.cpp @@ -181,13 +181,13 @@ void ShipCockpit::Update(const Player *player, float timeStep) } } -void ShipCockpit::RenderCockpit(Graphics::Renderer *renderer, const Camera *camera, Frame *frame) +void ShipCockpit::RenderCockpit(Graphics::Renderer *renderer, const Camera *camera, FrameId frameId) { PROFILE_SCOPED() renderer->ClearDepthBuffer(); - SetFrame(frame); + SetFrame(frameId); Render(renderer, camera, m_translate, m_transform); - SetFrame(nullptr); + SetFrame(noFrameId); } void ShipCockpit::OnActivated(const Player *player) diff --git a/src/ShipCockpit.h b/src/ShipCockpit.h index 7bfce970e..2afe2fa2c 100644 --- a/src/ShipCockpit.h +++ b/src/ShipCockpit.h @@ -24,7 +24,7 @@ public: virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) override; void Update(const Player *player, float timeStep); - void RenderCockpit(Graphics::Renderer *renderer, const Camera *camera, Frame *frame); + void RenderCockpit(Graphics::Renderer *renderer, const Camera *camera, FrameId frameId); void OnActivated(const Player *player); void resetInternalCameraController(void); diff --git a/src/Space.cpp b/src/Space.cpp index dff63676f..1c599ee1b 100644 --- a/src/Space.cpp +++ b/src/Space.cpp @@ -75,7 +75,7 @@ Space::Space(Game *game, RefCountedPtr galaxy, Space *oldSpace) : { m_background.reset(new Background::Container(Pi::renderer, Pi::rng)); - m_rootFrame.reset(Frame::CreateFrame(nullptr, Lang::SYSTEM, Frame::FLAG_DEFAULT, FLT_MAX)); + m_rootFrameId = Frame::CreateFrame(noFrameId, Lang::SYSTEM, Frame::FLAG_DEFAULT, FLT_MAX); GenSectorCache(galaxy, &game->GetHyperspaceDest()); } @@ -98,15 +98,16 @@ Space::Space(Game *game, RefCountedPtr galaxy, const SystemPath &path, S CityOnPlanet::SetCityModelPatterns(m_starSystem->GetPath()); - m_rootFrame.reset(Frame::CreateFrame(nullptr, Lang::SYSTEM, Frame::FLAG_DEFAULT, FLT_MAX)); + m_rootFrameId = Frame::CreateFrame(noFrameId, Lang::SYSTEM, Frame::FLAG_DEFAULT, FLT_MAX); std::vector positionAccumulator; - GenBody(m_game->GetTime(), m_starSystem->GetRootBody().Get(), m_rootFrame.get(), positionAccumulator); - m_rootFrame->UpdateOrbitRails(m_game->GetTime(), m_game->GetTimeStep()); + GenBody(m_game->GetTime(), m_starSystem->GetRootBody().Get(), m_rootFrameId, positionAccumulator); + Frame::GetFrame(m_rootFrameId)->UpdateOrbitRails(m_game->GetTime(), m_game->GetTimeStep()); + + //DebugDumpFrames(false); GenSectorCache(galaxy, &path); - //DebugDumpFrames(); } Space::Space(Game *game, RefCountedPtr galaxy, const Json &jsonObj, double at_time) : @@ -134,7 +135,7 @@ Space::Space(Game *game, RefCountedPtr galaxy, const Json &jsonObj, doub CityOnPlanet::SetCityModelPatterns(m_starSystem->GetPath()); if (!spaceObj.count("frame")) throw SavedGameCorruptException(); - m_rootFrame.reset(Frame::FromJson(spaceObj["frame"], this, nullptr, at_time)); + m_rootFrameId = Frame::FromJson(spaceObj["frame"], this, noFrameId, at_time); try { Json bodyArray = spaceObj["bodies"].get(); @@ -146,7 +147,7 @@ Space::Space(Game *game, RefCountedPtr galaxy, const Json &jsonObj, doub RebuildBodyIndex(); - Frame::PostUnserializeFixup(m_rootFrame.get(), this); + Frame::PostUnserializeFixup(m_rootFrameId, this); for (Body *b : m_bodies) b->PostLoadFixup(this); @@ -161,7 +162,7 @@ Space::~Space() for (std::list::iterator i = m_bodies.begin(); i != m_bodies.end(); ++i) KillBody(*i); UpdateBodies(); - Frame::DeleteFrame(m_rootFrame.get()); + Frame::DeleteFrame(m_rootFrameId); } void Space::RefreshBackground() @@ -183,7 +184,7 @@ void Space::ToJson(Json &jsonObj) StarSystem::ToJson(spaceObj, m_starSystem.Get()); Json frameObj({}); - Frame::ToJson(frameObj, m_rootFrame.get(), this); + Frame::ToJson(frameObj, m_rootFrameId, this); spaceObj["frame"] = frameObj; Json bodyArray = Json::array(); // Create JSON array to contain body data. @@ -394,25 +395,26 @@ Body *Space::FindBodyForPath(const SystemPath *path) const return 0; } -static Frame *find_frame_with_sbody(Frame *f, const SystemBody *b) +static FrameId find_frame_with_sbody(FrameId fId, const SystemBody *b) { + Frame *f = Frame::GetFrame(fId); if (f->GetSystemBody() == b) - return f; + return fId; else { - for (Frame *kid : f->GetChildren()) { - Frame *found = find_frame_with_sbody(kid, b); - if (found) return found; + for (FrameId kid : f->GetChildren()) { + FrameId found = find_frame_with_sbody(kid, b); + if (IsIdValid(found)) return found; } } - return 0; + return noFrameId; } -Frame *Space::GetFrameWithSystemBody(const SystemBody *b) const +FrameId Space::GetFrameWithSystemBody(const SystemBody *b) const { - return find_frame_with_sbody(m_rootFrame.get(), b); + return find_frame_with_sbody(m_rootFrameId, b); } -static void RelocateStarportIfNecessary(SystemBody *sbody, Frame *frame, Planet *planet, vector3d &pos, matrix3x3d &rot, const std::vector &prevPositions) +static void RelocateStarportIfNecessary(SystemBody *sbody, Planet *planet, vector3d &pos, matrix3x3d &rot, const std::vector &prevPositions) { const double radius = planet->GetSystemBody()->GetRadius(); @@ -537,110 +539,6 @@ static void RelocateStarportIfNecessary(SystemBody *sbody, Frame *frame, Planet } } -static Frame *MakeFrameFor(const double at_time, SystemBody *sbody, Body *b, Frame *f, std::vector &prevPositions) -{ - if (!sbody->GetParent()) { - if (b) b->SetFrame(f); - f->SetBodies(sbody, b); - return f; - } - - if (sbody->GetType() == SystemBody::TYPE_GRAVPOINT) { - Frame *orbFrame = Frame::CreateFrame(f, - sbody->GetName().c_str(), - Frame::FLAG_DEFAULT, - sbody->GetMaxChildOrbitalDistance() * 1.1 - ); - orbFrame->SetBodies(sbody, b); - return orbFrame; - } - - SystemBody::BodySuperType supertype = sbody->GetSuperType(); - - if ((supertype == SystemBody::SUPERTYPE_GAS_GIANT) || - (supertype == SystemBody::SUPERTYPE_ROCKY_PLANET)) { - // for planets we want an non-rotating frame for a few radii - // and a rotating frame with no radius to contain attached objects - double frameRadius = std::max(4.0 * sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance() * 1.05); - Frame *orbFrame = Frame::CreateFrame(f, - sbody->GetName().c_str(), - Frame::FLAG_HAS_ROT, - frameRadius - ); - orbFrame->SetBodies(sbody, b); - //Output("\t\t\t%s has frame size %.0fkm, body radius %.0fkm\n", sbody->name.c_str(), - // (frameRadius ? frameRadius : 10*sbody->GetRadius())*0.001f, - // sbody->GetRadius()*0.001f); - - assert(sbody->IsRotating() != 0); - // rotating frame has atmosphere radius or feature height, whichever is larger - Frame *rotFrame = Frame::CreateFrame(orbFrame, - sbody->GetName().c_str(), - Frame::FLAG_ROTATING, - b->GetPhysRadius() - ); - rotFrame->SetBodies(sbody, b); - - matrix3x3d rotMatrix = matrix3x3d::RotateX(sbody->GetAxialTilt()); - double angSpeed = 2.0 * M_PI / sbody->GetRotationPeriod(); - rotFrame->SetAngSpeed(angSpeed); - - if (sbody->HasRotationPhase()) - rotMatrix = rotMatrix * matrix3x3d::RotateY(sbody->GetRotationPhaseAtStart()); - rotFrame->SetInitialOrient(rotMatrix, at_time); - - b->SetFrame(rotFrame); - return orbFrame; - } else if (supertype == SystemBody::SUPERTYPE_STAR) { - // stars want a single small non-rotating frame - // bigger than it's furtherest orbiting body. - // if there are no orbiting bodies use a frame of several radii. - Frame *orbFrame = Frame::CreateFrame(f, sbody->GetName().c_str()); - orbFrame->SetBodies(sbody, b); - const double bodyRadius = sbody->GetEquatorialRadius(); - double frameRadius = std::max(10.0 * bodyRadius, sbody->GetMaxChildOrbitalDistance() * 1.1); - // Respect the frame of other stars in the multi-star system. We still make sure that the frame ends outside - // the body. For a minimum separation of 1.236 radii, nothing will overlap (see StarSystem::StarSystem()). - if (sbody->GetParent() && frameRadius > AU * 0.11 * sbody->GetOrbMin()) - frameRadius = std::max(1.1 * bodyRadius, AU * 0.11 * sbody->GetOrbMin()); - orbFrame->SetRadius(frameRadius); - b->SetFrame(orbFrame); - return orbFrame; - } else if (sbody->GetType() == SystemBody::TYPE_STARPORT_ORBITAL) { - // space stations want non-rotating frame to some distance - Frame *orbFrame = Frame::CreateFrame(f, - sbody->GetName().c_str(), - Frame::FLAG_DEFAULT, - 20000.0 - ); - orbFrame->SetBodies(sbody, b); - b->SetFrame(orbFrame); - return orbFrame; - - } else if (sbody->GetType() == SystemBody::TYPE_STARPORT_SURFACE) { - // just put body into rotating frame of planet, not in its own frame - // (because collisions only happen between objects in same frame, - // and we want collisions on starport and on planet itself) - Frame *rotFrame = f->GetRotFrame(); - b->SetFrame(rotFrame); - assert(rotFrame->IsRotFrame()); - assert(rotFrame->GetBody()->IsType(Object::PLANET)); - matrix3x3d rot; - vector3d pos; - Planet *planet = static_cast(rotFrame->GetBody()); - RelocateStarportIfNecessary(sbody, rotFrame, planet, pos, rot, prevPositions); - sbody->SetOrbitPlane(rot); - b->SetPosition(pos * planet->GetTerrainHeight(pos)); - b->SetOrient(rot); - // accumulate for testing against - prevPositions.push_back(pos); - return rotFrame; - } else { - assert(0); - } - return 0; -} - // used to define a cube centred on your current location static const int sectorRadius = 5; @@ -765,7 +663,120 @@ void Space::UpdateStarSystemCache(const SystemPath *here) m_starSystemCache->FillCache(paths); } -void Space::GenBody(const double at_time, SystemBody *sbody, Frame *f, std::vector &posAccum) +static FrameId MakeFramesFor(const double at_time, SystemBody *sbody, Body *b, FrameId fId, std::vector &prevPositions) +{ + Frame *f = Frame::GetFrame(fId); + + if (!sbody->GetParent()) { + if (b) b->SetFrame(fId); + Frame *f = Frame::GetFrame(fId); + f->SetBodies(sbody, b); + return fId; + } + + if (sbody->GetType() == SystemBody::TYPE_GRAVPOINT) { + FrameId orbFrameId = Frame::CreateFrame(fId, + sbody->GetName().c_str(), + Frame::FLAG_DEFAULT, + sbody->GetMaxChildOrbitalDistance() * 1.1 + ); + Frame *orbFrame = Frame::GetFrame(orbFrameId); + orbFrame->SetBodies(sbody, b); + return orbFrameId; + } + + SystemBody::BodySuperType supertype = sbody->GetSuperType(); + + if ((supertype == SystemBody::SUPERTYPE_GAS_GIANT) || + (supertype == SystemBody::SUPERTYPE_ROCKY_PLANET)) { + // for planets we want an non-rotating frame for a few radii + // and a rotating frame with no radius to contain attached objects + double frameRadius = std::max(4.0 * sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance() * 1.05); + FrameId orbFrameId = Frame::CreateFrame(fId, + sbody->GetName().c_str(), + Frame::FLAG_HAS_ROT, + frameRadius + ); + Frame *orbFrame = Frame::GetFrame(orbFrameId); + orbFrame->SetBodies(sbody, b); + //Output("\t\t\t%s has frame size %.0fkm, body radius %.0fkm\n", sbody->name.c_str(), + // (frameRadius ? frameRadius : 10*sbody->GetRadius())*0.001f, + // sbody->GetRadius()*0.001f); + + assert(sbody->IsRotating() != 0); + // rotating frame has atmosphere radius or feature height, whichever is larger + FrameId rotFrameId = Frame::CreateFrame(orbFrameId, + sbody->GetName().c_str(), + Frame::FLAG_ROTATING, + b->GetPhysRadius() + ); + Frame *rotFrame = Frame::GetFrame(rotFrameId); + rotFrame->SetBodies(sbody, b); + + matrix3x3d rotMatrix = matrix3x3d::RotateX(sbody->GetAxialTilt()); + double angSpeed = 2.0 * M_PI / sbody->GetRotationPeriod(); + rotFrame->SetAngSpeed(angSpeed); + + if (sbody->HasRotationPhase()) + rotMatrix = rotMatrix * matrix3x3d::RotateY(sbody->GetRotationPhaseAtStart()); + rotFrame->SetInitialOrient(rotMatrix, at_time); + + b->SetFrame(rotFrameId); + return orbFrameId; + } else if (supertype == SystemBody::SUPERTYPE_STAR) { + // stars want a single small non-rotating frame + // bigger than it's furtherest orbiting body. + // if there are no orbiting bodies use a frame of several radii. + FrameId orbFrameId = Frame::CreateFrame(fId, sbody->GetName().c_str()); + Frame *orbFrame = Frame::GetFrame(orbFrameId); + orbFrame->SetBodies(sbody, b); + const double bodyRadius = sbody->GetEquatorialRadius(); + double frameRadius = std::max(10.0 * bodyRadius, sbody->GetMaxChildOrbitalDistance() * 1.1); + // Respect the frame of other stars in the multi-star system. We still make sure that the frame ends outside + // the body. For a minimum separation of 1.236 radii, nothing will overlap (see StarSystem::StarSystem()). + if (sbody->GetParent() && frameRadius > AU * 0.11 * sbody->GetOrbMin()) + frameRadius = std::max(1.1 * bodyRadius, AU * 0.11 * sbody->GetOrbMin()); + orbFrame->SetRadius(frameRadius); + b->SetFrame(orbFrameId); + return orbFrameId; + } else if (sbody->GetType() == SystemBody::TYPE_STARPORT_ORBITAL) { + // space stations want non-rotating frame to some distance + FrameId orbFrameId = Frame::CreateFrame(fId, + sbody->GetName().c_str(), + Frame::FLAG_DEFAULT, + 20000.0 + ); + Frame *orbFrame = Frame::GetFrame(orbFrameId); + orbFrame->SetBodies(sbody, b); + b->SetFrame(orbFrameId); + return orbFrameId; + } else if (sbody->GetType() == SystemBody::TYPE_STARPORT_SURFACE) { + // just put body into rotating frame of planet, not in its own frame + // (because collisions only happen between objects in same frame, + // and we want collisions on starport and on planet itself) + FrameId rotFrameId = Frame::GetFrame(fId)->GetRotFrame(); + b->SetFrame(rotFrameId); + + Frame *rotFrame = Frame::GetFrame(rotFrameId); + assert(rotFrame->IsRotFrame()); + assert(rotFrame->GetBody()->IsType(Object::PLANET)); + matrix3x3d rot; + vector3d pos; + Planet *planet = static_cast(rotFrame->GetBody()); + RelocateStarportIfNecessary(sbody, planet, pos, rot, prevPositions); + sbody->SetOrbitPlane(rot); + b->SetPosition(pos * planet->GetTerrainHeight(pos)); + b->SetOrient(rot); + // accumulate for testing against + prevPositions.push_back(pos); + return rotFrameId; + } else { + assert(0); + } + return 0; +} + +void Space::GenBody(const double at_time, SystemBody *sbody, FrameId fId, std::vector &posAccum) { Body *b = nullptr; @@ -787,10 +798,10 @@ void Space::GenBody(const double at_time, SystemBody *sbody, Frame *f, std::vect b->SetPosition(vector3d(0, 0, 0)); AddBody(b); } - f = MakeFrameFor(at_time, sbody, b, f, posAccum); + fId = MakeFramesFor(at_time, sbody, b, fId, posAccum); for (SystemBody *kid : sbody->GetChildren()) { - GenBody(at_time, kid, f, posAccum); + GenBody(at_time, kid, fId, posAccum); } } @@ -937,8 +948,8 @@ static void CollideWithTerrain(Body *body, float timeStep) if (!dynBody->IsMoving()) return; - Frame *f = body->GetFrame(); - if (!f || !f->GetBody() || f != f->GetBody()->GetFrame()) + Frame *f = Frame::GetFrame(body->GetFrame()); + if (!f || !f->GetBody() || f->GetId() != f->GetBody()->GetFrame()) return; if (!f->GetBody()->IsType(Object::TERRAINBODY)) return; @@ -957,14 +968,12 @@ static void CollideWithTerrain(Body *body, float timeStep) hitCallback(&c); } -void Space::FrameDeleter::operator()(Frame* frame) { - Frame::DeleteFrame(frame); -}; - -void Space::CollideFrame(Frame *f) +void Space::CollideFrame(FrameId fId) { + Frame *f = Frame::GetFrame(fId); f->GetCollisionSpace()->Collide(&hitCallback); - for (Frame *kid : f->GetChildren()) + + for (FrameId kid : f->GetChildren()) CollideFrame(kid); } @@ -978,7 +987,7 @@ void Space::TimeStep(float step) m_bodyIndexValid = m_sbodyIndexValid = false; // XXX does not need to be done this often - CollideFrame(m_rootFrame.get()); + CollideFrame(m_rootFrameId); for (Body *b : m_bodies) CollideWithTerrain(b, step); @@ -991,7 +1000,7 @@ void Space::TimeStep(float step) for (Body *b : m_bodies) b->StaticUpdate(step); - m_rootFrame->UpdateOrbitRails(m_game->GetTime(), m_game->GetTimeStep()); + Frame::GetFrame(m_rootFrameId)->UpdateOrbitRails(m_game->GetTime(), m_game->GetTimeStep()); for (Body *b : m_bodies) b->TimeStepUpdate(step); @@ -1033,19 +1042,21 @@ void Space::UpdateBodies() static char space[256]; -static void DebugDumpFrame(Frame *f, bool details, unsigned int indent) +static void DebugDumpFrame(FrameId fId, bool details, unsigned int indent) { - Output("%.*s%p (%s)\n", indent, space, static_cast(f), f->GetLabel().c_str()); - if (f->GetParent()) - Output("%.*s parent %p (%s)\n", indent, space, static_cast(f->GetParent()), f->GetParent()->GetLabel().c_str()); - if (f->GetBody()) - Output("%.*s body %p (%s)\n", indent, space, static_cast(f->GetBody()), f->GetBody()->GetLabel().c_str()); - if (Body *b = f->GetBody()) - Output("%.*s bodyFor %p (%s)\n", indent, space, static_cast(b), b->GetLabel().c_str()); - Output("%.*s distance %f radius %f", indent, space, f->GetPosition().Length(), f->GetRadius()); - Output("%s\n", f->IsRotFrame() ? " [rotating]" : "[non rotating]"); + Frame *f = Frame::GetFrame(fId); + Frame *parent = Frame::GetFrame(f->GetParent()); - for (Frame *kid : f->GetChildren()) + Output("%.*s%2i) %p (%s)%s\n", indent, space, fId, static_cast(f), f->GetLabel().c_str(), f->IsRotFrame() ? " [rotating]" : " [non rotating]"); + if (IsIdValid(f->GetParent())) + Output("%.*s parent %p (%s)\n", indent + 3, space, static_cast(parent), parent->GetLabel().c_str()); + if (f->GetBody()) + Output("%.*s body %p (%s)\n", indent + 3, space, static_cast(f->GetBody()), f->GetBody()->GetLabel().c_str()); + if (Body *b = f->GetBody()) + Output("%.*s bodyFor %p (%s)\n", indent + 3, space, static_cast(b), b->GetLabel().c_str()); + Output("%.*s distance: %f radius: %f children: %u\n", indent + 3, space, f->GetPosition().Length(), f->GetRadius(), f->GetNumChildren()); + + for (FrameId kid : f->GetChildren()) DebugDumpFrame(kid, details, indent + 2); } @@ -1054,5 +1065,5 @@ void Space::DebugDumpFrames(bool details) memset(space, ' ', sizeof(space)); Output("Frame structure for '%s':\n", m_starSystem->GetName().c_str()); - DebugDumpFrame(m_rootFrame.get(), details, 2); + DebugDumpFrame(m_rootFrameId, details, 3); } diff --git a/src/Space.h b/src/Space.h index 758f706a4..0311caa60 100644 --- a/src/Space.h +++ b/src/Space.h @@ -5,6 +5,7 @@ #define _SPACE_H #include "Background.h" +#include "FrameId.h" #include "IterationProxy.h" #include "Object.h" #include "RefCounted.h" @@ -41,7 +42,7 @@ public: RefCountedPtr GetStarSystem() const { return m_starSystem; } - Frame *GetRootFrame() const { return m_rootFrame.get(); } + FrameId GetRootFrame() const { return m_rootFrameId; } void AddBody(Body *); void RemoveBody(Body *); @@ -87,20 +88,15 @@ public: private: void GenSectorCache(RefCountedPtr galaxy, const SystemPath *here); void UpdateStarSystemCache(const SystemPath *here); - void GenBody(const double at_time, SystemBody *b, Frame *f, std::vector &posAccum); + void GenBody(const double at_time, SystemBody *b, FrameId fId, std::vector &posAccum); // make sure SystemBody* is in Pi::currentSystem - Frame *GetFrameWithSystemBody(const SystemBody *b) const; + FrameId GetFrameWithSystemBody(const SystemBody *b) const; void UpdateBodies(); - void CollideFrame(Frame *f); + void CollideFrame(FrameId fId); - struct FrameDeleter { - /* Implemented in *cpp: prevent including Frame.h */ - void operator()(Frame* frame); - }; - - std::unique_ptr m_rootFrame; + FrameId m_rootFrameId; RefCountedPtr m_sectorCache; RefCountedPtr m_starSystemCache; diff --git a/src/SpaceStation.cpp b/src/SpaceStation.cpp index 2d4888ffd..eeafd0320 100644 --- a/src/SpaceStation.cpp +++ b/src/SpaceStation.cpp @@ -722,7 +722,7 @@ static const double SQRMAXCITYDIST = 1e5 * 1e5; void SpaceStation::Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) { - Body *b = GetFrame()->GetBody(); + Body *b = Frame::GetFrame(GetFrame())->GetBody(); assert(b); if (!b->IsType(Object::PLANET)) { @@ -780,7 +780,7 @@ bool SpaceStation::AllocateStaticSlot(int &slot) return false; } -vector3d SpaceStation::GetTargetIndicatorPosition(const Frame *relTo) const +vector3d SpaceStation::GetTargetIndicatorPosition(FrameId relToId) const { // return the next waypoint if permission has been granted for player, // and the docking point's position once the docking anim starts @@ -793,11 +793,11 @@ vector3d SpaceStation::GetTargetIndicatorPosition(const Frame *relTo) const PiVerify(m_type->GetDockAnimPositionOrient(i, m_type->NumDockingStages(), 1.0f, vector3d(0.0), dport, m_shipDocking[i].ship)); - vector3d v = GetInterpPositionRelTo(relTo); - return v + GetInterpOrientRelTo(relTo) * dport.pos; + vector3d v = GetInterpPositionRelTo(relToId); + return v + GetInterpOrientRelTo(relToId) * dport.pos; } } - return GetInterpPositionRelTo(relTo); + return GetInterpPositionRelTo(relToId); } bool SpaceStation::IsPortLocked(const int bay) const diff --git a/src/SpaceStation.h b/src/SpaceStation.h index 54ed7a9b0..a1405ee21 100644 --- a/src/SpaceStation.h +++ b/src/SpaceStation.h @@ -69,7 +69,7 @@ public: bool AllocateStaticSlot(int &slot); // use docking bay position, if player has been granted permission - virtual vector3d GetTargetIndicatorPosition(const Frame *relTo) const override; + virtual vector3d GetTargetIndicatorPosition(FrameId relToId) const override; // need this now because stations rotate in their frame virtual void UpdateInterpTransform(double alpha) override; diff --git a/src/SpeedLines.cpp b/src/SpeedLines.cpp index 78099f470..b2457eb11 100644 --- a/src/SpeedLines.cpp +++ b/src/SpeedLines.cpp @@ -58,7 +58,7 @@ void SpeedLines::Update(float time) // don't show if // vel < 100m/s // in rotating frame (near station or planet surface) - if (absVel < 100.f || m_ship->GetFrame()->IsRotFrame()) { + if (absVel < 100.f || Frame::GetFrame(m_ship->GetFrame())->IsRotFrame()) { m_visible = false; return; } diff --git a/src/SystemView.cpp b/src/SystemView.cpp index 6f4400c93..1b3840c8f 100644 --- a/src/SystemView.cpp +++ b/src/SystemView.cpp @@ -66,8 +66,9 @@ void TransferPlanner::AddStartTime(double timeStep) m_startTime += m_factor * timeStep; double deltaT = m_startTime - Pi::game->GetTime(); if (deltaT > 0.) { - Frame *frame = Pi::player->GetFrame()->GetNonRotFrame(); - Orbit playerOrbit = Orbit::FromBodyState(Pi::player->GetPositionRelTo(frame), Pi::player->GetVelocityRelTo(frame), frame->GetSystemBody()->GetMass()); + FrameId frameId = Frame::GetFrame(Pi::player->GetFrame())->GetNonRotFrame(); + Frame *frame = Frame::GetFrame(frameId); + Orbit playerOrbit = Orbit::FromBodyState(Pi::player->GetPositionRelTo(frameId), Pi::player->GetVelocityRelTo(frameId), frame->GetSystemBody()->GetMass()); m_position = playerOrbit.OrbitalPosAtTime(deltaT); m_velocity = playerOrbit.OrbitalVelocityAtTime(frame->GetSystemBody()->GetMass(), deltaT); @@ -78,14 +79,14 @@ void TransferPlanner::AddStartTime(double timeStep) void TransferPlanner::ResetStartTime() { m_startTime = 0; - Frame *frame = Pi::player->GetFrame(); + Frame *frame = Frame::GetFrame(Pi::player->GetFrame()); if (!frame || GetOffsetVel().ExactlyEqual(vector3d(0., 0., 0.))) { m_position = vector3d(0., 0., 0.); m_velocity = vector3d(0., 0., 0.); } else { - frame = frame->GetNonRotFrame(); - m_position = Pi::player->GetPositionRelTo(frame); - m_velocity = Pi::player->GetVelocityRelTo(frame); + frame = Frame::GetFrame(frame->GetNonRotFrame()); + m_position = Pi::player->GetPositionRelTo(frame->GetId()); + m_velocity = Pi::player->GetVelocityRelTo(frame->GetId()); } } @@ -128,7 +129,7 @@ std::string TransferPlanner::printDeltaTime() void TransferPlanner::AddDv(BurnDirection d, double dv) { if (m_position.ExactlyEqual(vector3d(0., 0., 0.))) { - Frame *frame = Pi::player->GetFrame()->GetNonRotFrame(); + FrameId frame = Frame::GetFrame(Pi::player->GetFrame())->GetNonRotFrame(); m_position = Pi::player->GetPositionRelTo(frame); m_velocity = Pi::player->GetVelocityRelTo(frame); m_startTime = Pi::game->GetTime(); @@ -753,9 +754,9 @@ void SystemView::PutBody(const SystemBody *b, const vector3d &offset, const matr PutLabel(b, offset); } - Frame *frame = Pi::player->GetFrame(); + Frame *frame = Frame::GetFrame(Pi::player->GetFrame()); if (frame->IsRotFrame()) - frame = frame->GetNonRotFrame(); + frame = Frame::GetFrame(frame->GetNonRotFrame()); // display the players orbit(?) if (frame->GetSystemBody() == b && frame->GetSystemBody()->GetMass() > 0) { @@ -1024,13 +1025,15 @@ void SystemView::DrawShips(const double t, const vector3d &offset) for (auto s = m_contacts.begin(); s != m_contacts.end(); s++) { vector3d pos = offset; if ((*s).first->GetFlightState() != Ship::FlightState::FLYING) { - Frame *frame = Pi::game->GetSpace()->GetRootFrame(); - pos += (*s).first->GetPositionRelTo(frame) * double(m_zoom); + FrameId frameId = Pi::game->GetSpace()->GetRootFrame(); + pos += (*s).first->GetPositionRelTo(frameId) * double(m_zoom); } else { - Frame *frame = (*s).first->GetFrame(); + FrameId frameId = (*s).first->GetFrame(); vector3d bpos = vector3d(0., 0., 0.); - if (frame != Pi::game->GetSpace()->GetRootFrame()) + if (frameId != Pi::game->GetSpace()->GetRootFrame()) { + Frame *frame = Frame::GetFrame(frameId); bpos += frame->GetPositionRelTo(Pi::game->GetSpace()->GetRootFrame()); + } pos += (bpos + (*s).second.OrbitalPosAtTime(t)) * double(m_zoom); } const bool isNavTarget = Pi::player->GetNavTarget() == (*s).first; diff --git a/src/TerrainBody.cpp b/src/TerrainBody.cpp index e53f1c67f..dc753db2e 100644 --- a/src/TerrainBody.cpp +++ b/src/TerrainBody.cpp @@ -123,14 +123,18 @@ void TerrainBody::Render(Graphics::Renderer *renderer, const Camera *camera, con renderer->ClearDepthBuffer(); } -void TerrainBody::SetFrame(Frame *f) +void TerrainBody::SetFrame(FrameId fId) { - if (GetFrame()) { - GetFrame()->SetPlanetGeom(0, 0); - } - Body::SetFrame(f); + Frame *f = Frame::GetFrame(GetFrame()); + if (f) { - GetFrame()->SetPlanetGeom(0, 0); + f->SetPlanetGeom(0, nullptr); + } + Body::SetFrame(fId); + + f = Frame::GetFrame(fId); + if (f) { + f->SetPlanetGeom(0, nullptr); } } diff --git a/src/TerrainBody.h b/src/TerrainBody.h index ee040c975..d4f4ee4dc 100644 --- a/src/TerrainBody.h +++ b/src/TerrainBody.h @@ -24,7 +24,7 @@ public: virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) override; virtual void SubRender(Graphics::Renderer *r, const matrix4x4d &modelView, const vector3d &camPos) {} - virtual void SetFrame(Frame *f) override; + virtual void SetFrame(FrameId fId) override; virtual bool OnCollision(Object *b, Uint32 flags, double relVel) override { return true; } virtual double GetMass() const override { return m_mass; } double GetTerrainHeight(const vector3d &pos) const; diff --git a/src/WorldView.cpp b/src/WorldView.cpp index e5404ccb4..6f449e5b1 100644 --- a/src/WorldView.cpp +++ b/src/WorldView.cpp @@ -302,8 +302,11 @@ void WorldView::Update() UpdateProjectedObjects(); - const Frame *playerFrame = Pi::player->GetFrame(); - const Frame *camFrame = m_cameraContext->GetCamFrame(); + FrameId playerFrameId = Pi::player->GetFrame(); + FrameId camFrameId = m_cameraContext->GetCamFrame(); + + const Frame *playerFrame = Frame::GetFrame(playerFrameId); + const Frame *camFrame = Frame::GetFrame(camFrameId); //speedlines and contact trails need camFrame for transform, so they //must be updated here @@ -311,7 +314,7 @@ void WorldView::Update() m_speedLines->Update(m_game->GetTimeStep()); matrix4x4d trans; - Frame::GetFrameTransform(playerFrame, camFrame, trans); + Frame::GetFrameTransform(playerFrameId, camFrameId, trans); if (m_speedLines.get() && Pi::AreSpeedLinesDisplayed()) { m_speedLines->Update(m_game->GetTimeStep()); @@ -324,13 +327,13 @@ void WorldView::Update() if (Pi::AreHudTrailsDisplayed()) { matrix4x4d trans; - Frame::GetFrameTransform(playerFrame, camFrame, trans); + Frame::GetFrameTransform(playerFrameId, camFrameId, trans); for (auto it = Pi::player->GetSensors()->GetContacts().begin(); it != Pi::player->GetSensors()->GetContacts().end(); ++it) it->trail->SetTransform(trans); } else { for (auto it = Pi::player->GetSensors()->GetContacts().begin(); it != Pi::player->GetSensors()->GetContacts().end(); ++it) - it->trail->Reset(playerFrame); + it->trail->Reset(playerFrameId); } UIView::Update(); @@ -416,7 +419,7 @@ static inline bool project_to_screen(const vector3d &in, vector3d &out, const Gr void WorldView::UpdateProjectedObjects() { - const Frame *cam_frame = m_cameraContext->GetCamFrame(); + const Frame *cam_frame = Frame::GetFrame(m_cameraContext->GetCamFrame()); matrix3x3d cam_rot = cam_frame->GetOrient(); // later we might want non-ship enemies (e.g., for assaults on military bases) @@ -427,7 +430,7 @@ void WorldView::UpdateProjectedObjects() if (enemy) { const vector3d targpos = enemy->GetInterpPositionRelTo(Pi::player) * cam_rot; const double dist = targpos.Length(); - const vector3d targScreenPos = enemy->GetInterpPositionRelTo(cam_frame); + const vector3d targScreenPos = enemy->GetInterpPositionRelTo(cam_frame->GetId()); UpdateIndicator(m_combatTargetIndicator, targScreenPos); @@ -875,21 +878,21 @@ static double wrapAngleToPositive(const double theta) */ std::tuple WorldView::CalculateHeadingPitchRoll(PlaneType pt) { - auto frame = Pi::player->GetFrame(); + FrameId frameId = Pi::player->GetFrame(); if (pt == ROTATIONAL) - frame = frame->GetRotFrame(); + frameId = Frame::GetFrame(frameId)->GetRotFrame(); else if (pt == PARENT) - frame = frame->GetNonRotFrame(); + frameId = Frame::GetFrame(frameId)->GetNonRotFrame(); // construct a frame of reference aligned with the ground plane // and with lines of longitude and latitude - const vector3d up = Pi::player->GetPositionRelTo(frame).NormalizedSafe(); + const vector3d up = Pi::player->GetPositionRelTo(frameId).NormalizedSafe(); const vector3d north = projectVecOntoPlane(vector3d(0, 1, 0), up).NormalizedSafe(); const vector3d east = north.Cross(up); // find the direction that the ship is facing - const auto shpRot = Pi::player->GetOrientRelTo(frame); + const auto shpRot = Pi::player->GetOrientRelTo(frameId); const vector3d hed = -shpRot.VectorZ(); const vector3d right = shpRot.VectorX(); const vector3d groundHed = projectVecOntoPlane(hed, up).NormalizedSafe(); @@ -929,7 +932,7 @@ vector3d WorldView::WorldSpaceToScreenSpace(const Body *body) const { if (body->IsType(Object::PLAYER) && shipView.GetCamType() == ShipViewController::CAM_INTERNAL) return vector3d(0, 0, 0); - const Frame *cam_frame = m_cameraContext->GetCamFrame(); + const FrameId cam_frame = m_cameraContext->GetCamFrame(); vector3d pos = body->GetInterpPositionRelTo(cam_frame); return projectToScreenSpace(pos, m_cameraContext); } @@ -937,7 +940,7 @@ vector3d WorldView::WorldSpaceToScreenSpace(const Body *body) const // needs to run inside m_cameraContext->Begin/EndFrame(); vector3d WorldView::WorldSpaceToScreenSpace(const vector3d &position) const { - const Frame *cam_frame = m_cameraContext->GetCamFrame(); + const Frame *cam_frame = Frame::GetFrame(m_cameraContext->GetCamFrame()); matrix3x3d cam_rot = cam_frame->GetInterpOrient(); vector3d pos = position * cam_rot; return projectToScreenSpace(pos, m_cameraContext); @@ -947,7 +950,7 @@ vector3d WorldView::WorldSpaceToScreenSpace(const vector3d &position) const vector3d WorldView::ShipSpaceToScreenSpace(const vector3d &pos) const { matrix3x3d orient = Pi::player->GetInterpOrient(); - const Frame *cam_frame = m_cameraContext->GetCamFrame(); + const Frame *cam_frame = Frame::GetFrame(m_cameraContext->GetCamFrame()); matrix3x3d cam_rot = cam_frame->GetInterpOrient(); vector3d camspace = orient * pos * cam_rot; return projectToScreenSpace(camspace, m_cameraContext, false); @@ -964,7 +967,7 @@ vector3d WorldView::GetTargetIndicatorScreenPosition(const Body *body) const { if (body->IsType(Object::PLAYER) && shipView.GetCamType() == ShipViewController::CAM_INTERNAL) return vector3d(0, 0, 0); - const Frame *cam_frame = m_cameraContext->GetCamFrame(); + FrameId cam_frame = m_cameraContext->GetCamFrame(); vector3d pos = body->GetTargetIndicatorPosition(cam_frame); return projectToScreenSpace(pos, m_cameraContext); } @@ -973,7 +976,7 @@ vector3d WorldView::GetTargetIndicatorScreenPosition(const Body *body) const vector3d WorldView::GetMouseDirection() const { // orientation according to mouse - const Frame *cam_frame = m_cameraContext->GetCamFrame(); + const Frame *cam_frame = Frame::GetFrame(m_cameraContext->GetCamFrame()); matrix3x3d cam_rot = cam_frame->GetInterpOrient(); vector3d mouseDir = Pi::player->GetPlayerController()->GetMouseDir() * cam_rot; if (shipView.GetCamType() == ShipViewController::CAM_INTERNAL && shipView.m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR) diff --git a/src/ship/PlayerShipController.cpp b/src/ship/PlayerShipController.cpp index a3c1b8148..dab400e50 100644 --- a/src/ship/PlayerShipController.cpp +++ b/src/ship/PlayerShipController.cpp @@ -184,7 +184,7 @@ void PlayerShipController::StaticUpdate(const float timeStep) // AIMatchVel(vector3d(0.0)); // just in case autopilot doesn't... // actually this breaks last timestep slightly in non-relative target cases m_ship->AIMatchAngVelObjSpace(vector3d(0.0)); - if (m_ship->GetFrame()->IsRotFrame()) + if (Frame::GetFrame(m_ship->GetFrame())->IsRotFrame()) SetFlightControlState(CONTROL_FIXSPEED); else SetFlightControlState(CONTROL_MANUAL); @@ -209,7 +209,7 @@ void PlayerShipController::CheckControlsLock() vector3d PlayerShipController::GetMouseDir() const { // translate from system to local frame - return m_mouseDir * m_ship->GetFrame()->GetOrient(); + return m_mouseDir * Frame::GetFrame(m_ship->GetFrame())->GetOrient(); } // mouse wraparound control function @@ -241,7 +241,7 @@ void PlayerShipController::PollControls(const float timeStep, const bool force_r // have to use this function. SDL mouse position event is bugged in windows if (Pi::input.MouseButtonState(SDL_BUTTON_RIGHT)) { // use ship rotation relative to system, unchanged by frame transitions - matrix3x3d rot = m_ship->GetOrientRelTo(m_ship->GetFrame()->GetNonRotFrame()); + matrix3x3d rot = m_ship->GetOrientRelTo(Frame::GetFrame(m_ship->GetFrame())->GetNonRotFrame()); if (!m_mouseActive && !m_disableMouseFacing) { m_mouseDir = -rot.VectorZ(); m_mouseX = m_mouseY = 0; diff --git a/src/sound/AmbientSounds.cpp b/src/sound/AmbientSounds.cpp index df5bf14f5..b54f74497 100644 --- a/src/sound/AmbientSounds.cpp +++ b/src/sound/AmbientSounds.cpp @@ -131,7 +131,7 @@ void AmbientSounds::Update() // lets try something random for the time being if (!s_planetSurfaceNoise.IsPlaying()) { - const SystemBody *sbody = Pi::player->GetFrame()->GetSystemBody(); + const SystemBody *sbody = Frame::GetFrame(Pi::player->GetFrame())->GetSystemBody(); assert(sbody); const char *sample = 0; @@ -149,8 +149,9 @@ void AmbientSounds::Update() } } else if (s_planetSurfaceNoise.IsPlaying()) { // s_planetSurfaceNoise.IsPlaying() - if we are out of the atmosphere then stop playing - if (Pi::player->GetFrame()->IsRotFrame()) { - const Body *astro = Pi::player->GetFrame()->GetBody(); + Frame *playerFrame = Frame::GetFrame(Pi::player->GetFrame()); + if (playerFrame->IsRotFrame()) { + const Body *astro = playerFrame->GetBody(); if (astro->IsType(Object::PLANET)) { const double dist = Pi::player->GetPosition().Length(); double pressure, density; @@ -187,7 +188,7 @@ void AmbientSounds::Update() } // when all the sounds are in we can use the body we are in frame of reference to if (!s_starNoise.IsPlaying()) { - Frame *f = Pi::player->GetFrame(); + Frame *f = Frame::GetFrame(Pi::player->GetFrame()); if (!f) return; // When player has no frame (game abort) then get outta here!! const SystemBody *sbody = f->GetSystemBody(); const char *sample = 0; @@ -220,14 +221,16 @@ void AmbientSounds::Update() s_starNoise.VolumeAnimate(.3f * v_env, .3f * v_env, .05f, .05f); } else { // go up orbital hierarchy tree to see if we can find a sound - f = f->GetParent(); - if (f == 0) break; + FrameId parent = f->GetParent(); + f = Frame::GetFrame(parent); + if (f == nullptr) break; } } } - const Body *astro = Pi::player->GetFrame()->GetBody(); - if (astro && Pi::player->GetFrame()->IsRotFrame() && (astro->IsType(Object::PLANET))) { + Frame *playerFrame = Frame::GetFrame(Pi::player->GetFrame()); + const Body *astro = playerFrame->GetBody(); + if (astro && playerFrame->IsRotFrame() != noFrameId && (astro->IsType(Object::PLANET))) { double dist = Pi::player->GetPosition().Length(); double pressure, density; static_cast(astro)->GetAtmosphericState(dist, &pressure, &density);