From d6154a63a695e8212d0e4018330a2292c17704f3 Mon Sep 17 00:00:00 2001 From: Rtch90 Date: Tue, 26 Dec 2017 17:24:03 +0000 Subject: [PATCH] [Add] Initial work on rotating frames. Woop, our sun moves now. --- src/body.cpp | 4 +++- src/body.h | 2 ++ src/frame.cpp | 39 +++++++++++++++++++++++++++++---------- src/frame.h | 35 +++++++++++++++++++++-------------- src/l3d.h | 2 ++ src/main.cpp | 17 ++++++++++++----- src/matrix4x4.h | 26 ++++++++++++++++++++++++-- src/model_body.cpp | 11 +++++++---- src/model_body.h | 2 +- src/space.cpp | 32 ++++++++++++++++++++++++++++---- src/space_station.cpp | 2 -- src/world_view.cpp | 4 +++- 12 files changed, 132 insertions(+), 44 deletions(-) diff --git a/src/body.cpp b/src/body.cpp index ded37d4..7149f1d 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -17,7 +17,9 @@ Body::~Body(void) { /* f == NULL, then absolute position within system. */ vector3d Body::GetPositionRelTo(const Frame* relTo) { - return m_frame->GetPosRelativeToOtherFrame(relTo) + GetPosition(); + matrix4x4d m; + Frame::GetFrameTransform(m_frame, relTo, m); + return m * GetPosition(); } const vector3d& Body::GetProjectedPos(void) const { diff --git a/src/body.h b/src/body.h index d05e56a..cb71377 100644 --- a/src/body.h +++ b/src/body.h @@ -18,6 +18,8 @@ public: 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 SetRotMatrix(const matrix4x4d& r) {}; + virtual void GetRotMatrix(matrix4x4d& m) {}; virtual void Render(const Frame* camFrame) = 0; virtual void SetFrame(Frame* f) { m_frame = f; } /* return true if to we do collision response and apply damage. */ diff --git a/src/frame.cpp b/src/frame.cpp index 97aaf3c..bd93003 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -24,6 +24,8 @@ void Frame::Init(Frame* parent, const char* label, unsigned int flags) { m_radius = 0; m_pos = vector3d(0.0f); m_vel = vector3d(0.0); + m_angVel = vector3d(0.0); + m_orient = matrix4x4d::Identity(); m_dSpaceID = dHashSpaceCreate(0); if(m_parent) { m_parent->m_children.push_back(this); @@ -36,23 +38,40 @@ Frame::~Frame(void) { for(std::list::iterator i = m_children.begin(); i != m_children.end(); ++i) delete *i; } -vector3d Frame::GetFramePosRelativeToOther(const Frame* frame, const Frame* relTo) { - vector3d pos = vector3d(0,0,0); +void Frame::ApplyLeavingTransform(matrix4x4d& m) const { + m = matrix4x4d::Translation(m_pos) * m_orient * m; +} - const Frame* f = frame; +void Frame::ApplyEnteringTransform(matrix4x4d& m) const { + m = m * m_orient.InverseOf() * matrix4x4d::Translation(-m_pos); +} + +void Frame::GetFrameTransform(const Frame* fFrom, const Frame* fTo, matrix4x4d& m) { + matrix4x4d m2 = matrix4x4d::Identity(); + m = matrix4x4d::Identity(); + + const Frame* f = fFrom; const Frame* root = Space::GetRootFrame(); - while((f!=root) && (relTo !=f)) { - pos += f->m_pos; + while((f != root) && (fTo != f)) { + f->ApplyLeavingTransform(m); f = f->m_parent; } - /* Now pos is relative to root, or to desired frame. */ - while(relTo != f) { - pos -= relTo->m_pos; - relTo = relTo->m_parent; + while(fTo != f) { + fTo->ApplyEnteringTransform(m2); + fTo = fTo->m_parent; } - return pos; + m = m2 * m; +} + +void Frame::RotateInTimestep(double step) { + double ang = m_angVel.Length() * step; + if(ang == 0) return; + vector3d rotAxis = vector3d::Normalize(m_angVel); + matrix4x4d rotMatrix = matrix4x4d::RotateMatrix(ang, rotAxis.x, rotAxis.y, rotAxis.z); + + m_orient = m_orient * rotMatrix; } diff --git a/src/frame.h b/src/frame.h index 6799dc3..294d285 100644 --- a/src/frame.h +++ b/src/frame.h @@ -12,23 +12,28 @@ public: Frame(Frame* parent, const char* label, unsigned int flags); ~Frame(void); - 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; } + const char* GetLabel(void) const { return m_label.c_str(); } + void SetLabel(const char* label) { m_label = label; } + void SetPosition(const vector3d &pos) { m_pos = pos; } + vector3d GetPosition(void) const { return m_pos; } + void SetVelocity(const vector3d& vel) { m_vel = vel; } + vector3d GetVelocity(void) const { return m_vel; } + void SetAngVelocity(const vector3d& angvel) { m_angVel = angvel; } + vector3d GetAngVelocity(void) const { return m_angVel; } + const matrix4x4d& GetOrientation(void) const { return m_orient; } + void SetOrientation(const matrix4x4d& m) { m_orient = m; } + void SetRadius(double radius) { m_radius = radius; } void RemoveChild(Frame* f); - void AddGeom(dGeomID g) { dSpaceAdd(m_dSpaceID, g); } - void RemoveGeom(dGeomID g) { dSpaceRemove(m_dSpaceID, g); } - dSpaceID GetSpaceID(void) { return m_dSpaceID; } + void AddGeom(dGeomID g) { dSpaceAdd(m_dSpaceID, g); } + void RemoveGeom(dGeomID g) { dSpaceRemove(m_dSpaceID, g); } + dSpaceID GetSpaceID(void) const { return m_dSpaceID; } + void RotateInTimestep(double step); - static vector3d GetFramePosRelativeToOther(const Frame* frame, const Frame* relTo); - vector3d GetPosRelativeToOtherFrame(const Frame* relTo) const { - return GetFramePosRelativeToOther(this, relTo); - } + void ApplyLeavingTransform(matrix4x4d& m) const; + void ApplyEnteringTransform(matrix4x4d& m) const; + + static void GetFrameTransform(const Frame* fFrom, const Frame* fTo, matrix4x4d& m); bool IsLocalPosInFrame(const vector3d& pos) { return (pos.Length() < m_radius); @@ -46,6 +51,8 @@ private: vector3d m_pos; /* We don't use this to move frame, rather, orbital rails determine velocity. */ vector3d m_vel; + vector3d m_angVel; /* This however *is* directly applied (for rotating frames). */ + matrix4x4d m_orient; std::string m_label; double m_radius; int m_flags; diff --git a/src/l3d.h b/src/l3d.h index 08acfc0..6c6ec6d 100644 --- a/src/l3d.h +++ b/src/l3d.h @@ -34,6 +34,8 @@ public: } }; +class Frame; + /* Implementation is done in main.cpp, just to confuse you. :D */ class L3D { public: diff --git a/src/main.cpp b/src/main.cpp index 19691fc..d972e74 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -194,8 +194,6 @@ void L3D::MainLoop(void) { const float zpos = EARTH_RADIUS * 1; Frame* pframe = *(Space::rootFrame->m_children.begin()); - player->SetFrame(pframe); - player->SetPosition(vector3d(0, zpos*0.1, zpos)); for(int i = 0; i < 4; i++) { Ship* body = new Ship(ShipType::SLEEK/*LADYBIRD*/); @@ -207,12 +205,21 @@ void L3D::MainLoop(void) { Space::AddBody(body); } + Frame* stationFrame = new Frame(pframe, "Station frame..."); + stationFrame->SetRadius(5000); + stationFrame->sBody = 0; + stationFrame->SetPosition(vector3d(0,0,zpos)); + stationFrame->SetAngVelocity(vector3d(0,0,0.5)); + SpaceStation* station = new SpaceStation(); station->SetLabel("Poemi-chan's Folly"); - station->SetFrame(pframe); - station->SetPosition(vector3d(5000, zpos*0.1, zpos-10000)); + station->SetFrame(stationFrame); + station->SetPosition(vector3d(0,0,0)); Space::AddBody(station); + player->SetFrame(stationFrame); + player->SetPosition(vector3d(0,0,2000)); + Gui::Init(scrWidth, scrHeight, 640, 480); cpan = new ShipCpanel(); @@ -227,7 +234,7 @@ void L3D::MainLoop(void) { infoView = new InfoView(); SetView(world_view); - player->SetDockedWith(station); + //player->SetDockedWith(station); Uint32 last_stats = SDL_GetTicks(); int frame_stat = 0; diff --git a/src/matrix4x4.h b/src/matrix4x4.h index 22d8f35..f90b054 100644 --- a/src/matrix4x4.h +++ b/src/matrix4x4.h @@ -174,6 +174,12 @@ public: return m; } + void ClearToRotOnly(void) { + cell[12] = 0; + cell[13] = 0; + cell[14] = 0; + } + T& operator[] (const int i) { return cell[i]; } friend matrix4x4 operator+(const matrix4x4& a, const matrix4x4& b) { matrix4x4 m; @@ -223,12 +229,28 @@ public: return out; } - void Translatef(T x, T y, T z) { + void Translate(vector3 t) { + Translate(t.x, t.y, t.z); + } + + void Translate(T x, T y, T z) { matrix4x4 m = Identity(); m[12] = x; m[13] = y; m[14] = z; - *this = (*this) * m; + *this = m * (*this); + } + + static matrix4x4 Translation(vector3 v) { + return Translation(v.x, v.y, v.z); + } + + static matrix4x4 Translation(T x, T y, T z) { + matrix4x4 m = Identity(); + m[12] = x; + m[13] = y; + m[14] = z; + return m; } matrix4x4 InverseOf(void) const { diff --git a/src/model_body.cpp b/src/model_body.cpp index 4a40e5f..35d0475 100644 --- a/src/model_body.cpp +++ b/src/model_body.cpp @@ -88,7 +88,7 @@ double ModelBody::GetRadius(void) const { return std::max(aabbAll[1] - aabbAll[0], std::max(aabbAll[3] - aabbAll[2], aabbAll[5] - aabbAll[4])); } -void ModelBody::SetRotation(const matrix4x4d& r) { +void ModelBody::SetRotMatrix(const matrix4x4d& r) { dMatrix3 _m; r.SaveToOdeMatrix(_m); for(unsigned int i = 0; i < geoms.size(); i++) { @@ -168,12 +168,15 @@ void ModelBody::RenderSbreModel(const Frame* camFrame, int model, ObjParams* par sbreSetViewport(L3D::GetScrWidth(), L3D::GetScrHeight(), L3D::GetScrWidth() *0.5, 5.0f, 100000.0f, 0.0f, 1.0f); - vector3d pos = GetPositionRelTo(camFrame); - pos = L3D::world_view->viewingRotation*pos; + matrix4x4d frameTrans; + Frame::GetFrameTransform(GetFrame(), camFrame, frameTrans); + + vector3d pos = GetPosition(); + pos = L3D::world_view->viewingRotation * frameTrans * pos; Vector p; p.x = pos.x; p.y = pos.y; p.z = -pos.z; matrix4x4d rot; rot.LoadFromOdeMatrix(dGeomGetRotation(geoms[0])); - rot = L3D::world_view->viewingRotation * rot; + rot = L3D::world_view->viewingRotation * frameTrans * rot; Matrix m; m.x1 = rot[0]; m.x2 = rot[4]; m.x3 = -rot[8]; m.y1 = rot[1]; m.y2 = rot[5]; m.y3 = -rot[9]; diff --git a/src/model_body.h b/src/model_body.h index d772ba6..78d6088 100644 --- a/src/model_body.h +++ b/src/model_body.h @@ -12,7 +12,7 @@ public: ModelBody(void); virtual ~ModelBody(void); void SetPosition(vector3d p); - virtual void SetRotation(const matrix4x4d& r); + virtual void SetRotMatrix(const matrix4x4d& r); /* Not valid to SetVelocity on these. If you want them to move, use a DynamicBody. */ vector3d GetPosition(void); virtual double GetRadius(void) const; diff --git a/src/space.cpp b/src/space.cpp index d9062dc..a4ef3f1 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -50,6 +50,7 @@ void Space::MoveOrbitingObjectFrames(Frame* f) { f->SetPosition(pos); f->SetVelocity(vel); } + f->RotateInTimestep(L3D::GetTimeStep()); for(std::list::iterator i = f->m_children.begin(); i != f->m_children.end(); ++i) { MoveOrbitingObjectFrames(*i); @@ -117,13 +118,27 @@ 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()); + vector3d oldFrameVel = 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); + matrix4x4d m = matrix4x4d::Identity(); + b->GetFrame()->ApplyLeavingTransform(m); + + vector3d new_pos = m * b->GetPosition(); + + matrix4x4d rot; + b->GetRotMatrix(rot); + b->SetRotMatrix(m * rot); + b->SetFrame(new_frame); b->SetPosition(new_pos); + + /* Get rid of transforms. */ + m.ClearToRotOnly(); + b->SetVelocity(m*b->GetVelocity() + oldFrameVel); + } else { + b->SetVelocity(b->GetVelocity() + oldFrameVel); } } @@ -131,12 +146,21 @@ void Space::UpdateFramesOfReference(void) { for(std::list::iterator j = b->GetFrame()->m_children.begin(); j != b->GetFrame()->m_children.end(); ++j) { Frame* child = *j; - vector3d pos = b->GetFrame()->GetPosRelativeToOtherFrame(child) + b->GetPosition(); + matrix4x4d m; + Frame::GetFrameTransform(b->GetFrame(), child, m); + vector3d pos = m * b->GetPosition(); if(child->IsLocalPosInFrame(pos)) { printf("%s enters frame %s\n", b->GetLabel().c_str(), child->GetLabel()); b->SetPosition(pos); b->SetFrame(child); - b->SetVelocity(b->GetVelocity() - child->GetVelocity()); + + matrix4x4d rot; + b->GetRotMatrix(rot); + b->SetRotMatrix(m * rot); + + /* Get rid of transforms. */ + m.ClearToRotOnly(); + b->SetVelocity(m*b->GetVelocity()-child->GetVelocity()); break; } } diff --git a/src/space_station.cpp b/src/space_station.cpp index 60a0c04..4db8b58 100644 --- a/src/space_station.cpp +++ b/src/space_station.cpp @@ -57,8 +57,6 @@ void SpaceStation::GetDockingSurface(CollMeshSet* mset, int midx) { SpaceStation::SpaceStation(void) : ModelBody() { SetModel(STATION_SBRE_MODEL); - matrix4x4d m = matrix4x4d::RotateYMatrix(M_PI-M_PI/6); - SetRotation(m); CollMeshSet* mset = GetModelCollMeshSet(STATION_SBRE_MODEL); for(unsigned int i = 0; i < geomColl.size(); i++) { diff --git a/src/world_view.cpp b/src/world_view.cpp index d261847..a5df94e 100644 --- a/src/world_view.cpp +++ b/src/world_view.cpp @@ -109,7 +109,9 @@ void WorldView::Draw3D(void) { glCallList(m_bgstarsDlist); /* Position light at sol. */ - vector3d lpos = vector3d::Normalize(Frame::GetFramePosRelativeToOther(Space::GetRootFrame(), &cam_frame)); + matrix4x4d m; + Frame::GetFrameTransform(Space::GetRootFrame(), &cam_frame, m); + vector3d lpos = vector3d::Normalize(m*vector3d(0,0,0)); float lightPos[4]; lightPos[0] = lpos.x; lightPos[1] = lpos.y;