From 96e36dab615b8bb9965206706e2c3a40997c0771 Mon Sep 17 00:00:00 2001 From: Allanis Date: Sun, 24 Dec 2017 17:57:14 +0000 Subject: [PATCH] [Fix] Set body velocities correctly as they enter and leave moving frames. --- src/body.h | 2 ++ src/dynamic_body.cpp | 5 +++++ src/dynamic_body.h | 3 ++- src/frame.cpp | 1 + src/frame.h | 5 +++++ src/main.cpp | 3 ++- src/space.cpp | 27 ++++++++++++++++----------- src/space.h | 2 +- 8 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/body.h b/src/body.h index d04b925..d05e56a 100644 --- a/src/body.h +++ b/src/body.h @@ -15,6 +15,8 @@ public: virtual Object::Type GetType(void) { return Object::BODY; } virtual void SetPosition(vector3d p) = 0; virtual vector3d GetPosition(void) = 0; /* Within frame. */ + virtual void SetVelocity(vector3d v) { assert(0); } + virtual vector3d GetVelocity(void) { assert(0); return vector3d(0.0); } virtual double GetRadius(void) const = 0 ; virtual void Render(const Frame* camFrame) = 0; virtual void SetFrame(Frame* f) { m_frame = f; } diff --git a/src/dynamic_body.cpp b/src/dynamic_body.cpp index 11eb438..a1cbeab 100644 --- a/src/dynamic_body.cpp +++ b/src/dynamic_body.cpp @@ -53,6 +53,11 @@ DynamicBody::~DynamicBody(void) { dBodyDestroy(m_body); } +vector3d DynamicBody::GetVelocity(void) { + const dReal* v = dBodyGetLinearVel(m_body); + return vector3d(v[0], v[1], v[2]); +} + void DynamicBody::SetVelocity(vector3d v) { dBodySetLinearVel(m_body, v.x, v.y, v.z); } diff --git a/src/dynamic_body.h b/src/dynamic_body.h index f210a80..e866c5f 100644 --- a/src/dynamic_body.h +++ b/src/dynamic_body.h @@ -11,7 +11,8 @@ public: DynamicBody(void); virtual ~DynamicBody(void); virtual void SetRotation(const matrix4x4d& r); - void SetVelocity(vector3d v); + virtual void SetVelocity(vector3d v); + virtual vector3d GetVelocity(void); void SetAngVelocity(vector3d v); void SetMesh(ObjMesh* m); virtual bool OnCollision(Body* b, Uint32 flags) { return true; } diff --git a/src/frame.cpp b/src/frame.cpp index 84ccc7d..97aaf3c 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -23,6 +23,7 @@ void Frame::Init(Frame* parent, const char* label, unsigned int flags) { m_flags = flags; m_radius = 0; m_pos = vector3d(0.0f); + m_vel = vector3d(0.0); m_dSpaceID = dHashSpaceCreate(0); if(m_parent) { m_parent->m_children.push_back(this); diff --git a/src/frame.h b/src/frame.h index 917890f..6799dc3 100644 --- a/src/frame.h +++ b/src/frame.h @@ -15,6 +15,9 @@ public: const char* GetLabel(void) { return m_label.c_str(); } void SetLabel(const char* label) { m_label = label; } void SetPosition(const vector3d &pos) { m_pos = pos; } + vector3d GetPosition(void) { return m_pos; } + void SetVelocity(const vector3d& vel) { m_vel = vel; } + vector3d GetVelocity(void) { return m_vel; } void SetRadius(double radius) { m_radius = radius; } void RemoveChild(Frame* f); void AddGeom(dGeomID g) { dSpaceAdd(m_dSpaceID, g); } @@ -41,6 +44,8 @@ public: private: void Init(Frame* parent, const char* label, unsigned int flags); vector3d m_pos; + /* We don't use this to move frame, rather, orbital rails determine velocity. */ + vector3d m_vel; std::string m_label; double m_radius; int m_flags; diff --git a/src/main.cpp b/src/main.cpp index 56c7717..19691fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -318,7 +318,8 @@ void L3D::HyperspaceTo(StarSystem* dest) { Space::Clear(); Space::BuildSystem(); float ang = rng.Double(M_PI); - L3D::player->SetPosition(vector3d(sin(ang)*8*AU, cos(ang)*8*AU, 0)); + L3D::player->SetPosition(vector3d(sin(ang)*AU, cos(ang)*AU,0)); + L3D::player->SetVelocity(vector3d(0.0)); dest->GetPos(&L3D::playerLoc); } diff --git a/src/space.cpp b/src/space.cpp index 7ef4ff7..d9062dc 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -41,14 +41,18 @@ void Space::Clear(void) { L3D::player->SetFrame(rootFrame); } -void Space::MoveFramesOfReference(Frame* f) { +void Space::MoveOrbitingObjectFrames(Frame* f) { if(f->sBody) { + /* Not too efficient. */ vector3d pos = f->sBody->orbit.CartesianPosAtTime(L3D::GetGameTime()); + vector3d pos2 = f->sBody->orbit.CartesianPosAtTime(L3D::GetGameTime()+1.0); + vector3d vel = pos2 - pos; f->SetPosition(pos); + f->SetVelocity(vel); } for(std::list::iterator i = f->m_children.begin(); i != f->m_children.end(); ++i) { - MoveFramesOfReference(*i); + MoveOrbitingObjectFrames(*i); } } @@ -67,11 +71,8 @@ void Space::GenBody(StarSystem::SBody* sbody, Frame* f) { b->SetLabel(sbody->name.c_str()); Frame* myframe; - if(sbody->parent) { myframe = new Frame(f, sbody->name.c_str()); - vector3d pos = sbody->orbit.CartesianPosAtTime(0); - myframe->SetPosition(pos); myframe->SetRadius(10*sbody->GetRadius()); myframe->sBody = sbody; b->SetFrame(myframe); @@ -94,6 +95,7 @@ just_make_child: void Space::BuildSystem(void) { GenBody(L3D::current_system->rootBody, rootFrame); + MoveOrbitingObjectFrames(rootFrame); } void Space::AddBody(Body* b) { @@ -115,6 +117,8 @@ void Space::UpdateFramesOfReference(void) { if(!b->GetFrame()->IsLocalPosInFrame(b->GetPosition())) { printf("%s leaves frame %s\n", b->GetLabel().c_str(), b->GetFrame()->GetLabel()); + b->SetVelocity(b->GetVelocity() + b->GetFrame()->GetVelocity()); + Frame* new_frame = b->GetFrame()->m_parent; if(new_frame) { /* Don't fall out of root frame. */ vector3d new_pos = b->GetPositionRelTo(new_frame); @@ -126,12 +130,13 @@ void Space::UpdateFramesOfReference(void) { /* Entering into frames. */ for(std::list::iterator j = b->GetFrame()->m_children.begin(); j != b->GetFrame()->m_children.end(); ++j) { - Frame* kid = *j; - vector3d pos = b->GetFrame()->GetPosRelativeToOtherFrame(kid) + b->GetPosition(); - if(kid->IsLocalPosInFrame(pos)) { - printf("%s enters frame %s\n", b->GetLabel().c_str(), kid->GetLabel()); + Frame* child = *j; + vector3d pos = b->GetFrame()->GetPosRelativeToOtherFrame(child) + b->GetPosition(); + if(child->IsLocalPosInFrame(pos)) { + printf("%s enters frame %s\n", b->GetLabel().c_str(), child->GetLabel()); b->SetPosition(pos); - b->SetFrame(kid); + b->SetFrame(child); + b->SetVelocity(b->GetVelocity() - child->GetVelocity()); break; } } @@ -240,7 +245,7 @@ void Space::TimeStep(float step) { /* TODO: Does not need to be done this often. */ UpdateFramesOfReference(); - MoveFramesOfReference(rootFrame); + MoveOrbitingObjectFrames(rootFrame); for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) { (*i)->TimeStepUpdate(step); diff --git a/src/space.h b/src/space.h index 08366e5..4f04d39 100644 --- a/src/space.h +++ b/src/space.h @@ -24,7 +24,7 @@ public: typedef std::list::iterator bodiesIter_t; static Frame* rootFrame; private: - static void MoveFramesOfReference(Frame* f); + static void MoveOrbitingObjectFrames(Frame* f); static void UpdateFramesOfReference(void); static void CollideFrame(Frame* f); static void PruneCorpses(void);