Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve/fix system map #5123

Merged
merged 1 commit into from
Feb 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/DynamicBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,12 @@ bool DynamicBody::OnCollision(Body *o, Uint32 flags, double relVel)
// return parameters for orbit of any body, gives both elliptic and hyperbolic trajectories
Orbit DynamicBody::ComputeOrbit() const
{
FrameId nrFrameId = Frame::GetFrame(GetFrame())->GetNonRotFrame();
auto f = Frame::GetFrame(GetFrame());
// if we are in a rotating frame, then dynamic body currently under the
// influence of a rotational frame, therefore getting the orbital parameters
// is not appropriate, return the orbit as a fixed point
if (f->IsRotFrame()) return Orbit::ForStaticBody(GetPosition());
FrameId nrFrameId = f->GetId();
const Frame *nrFrame = Frame::GetFrame(nrFrameId);
const double mass = nrFrame->GetSystemBody()->GetMass();

Expand Down
38 changes: 26 additions & 12 deletions src/Orbit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ double Orbit::MeanAnomalyAtTime(double time) const

vector3d Orbit::OrbitalPosAtTime(double t) const
{
if (is_zero_general(m_semiMajorAxis)) return m_positionForStaticBody;
double cos_v, sin_v, r;
calc_position_from_mean_anomaly(MeanAnomalyAtTime(t), m_eccentricity, m_semiMajorAxis, cos_v, sin_v, &r);
return m_orient * vector3d(-cos_v * r, sin_v * r, 0);
Expand Down Expand Up @@ -298,31 +299,44 @@ void Orbit::SetShapeAroundPrimary(double semiMajorAxis, double centralMass, doub
m_velocityAreaPerSecond = calc_velocity_area_per_sec(semiMajorAxis, centralMass, eccentricity);
}

Orbit Orbit::FromBodyState(const vector3d &pos, const vector3d &vel, double centralMass)
Orbit Orbit::ForStaticBody(const vector3d &position)
{
Orbit ret;
// just remember the current position of the body, and we will return it, for any t
ret.m_positionForStaticBody = position;
return ret;
}

const double r_now = pos.Length() + 1e-12;
const double v_now = vel.Length() + 1e-12;
Orbit Orbit::FromBodyState(const vector3d &pos, const vector3d &vel_raw, double centralMass)
{
Orbit ret;

// standard gravitational parameter
const double u = centralMass * G;

// maybe we will adjust the speed a little now
vector3d vel = vel_raw;
// angular momentum
const vector3d ang = pos.Cross(vel);
vector3d ang = pos.Cross(vel);
// quite a rare case - the speed is directed strictly to the star or away from the star
// let's make a small disturbance to the velocity, so as not to calculate the radial orbit
if (is_zero_general(ang.LengthSqr()) && !is_zero_general(centralMass)) {
if (is_zero_general(pos.x) && is_zero_general(pos.y)) // even rarer case, the body lies strictly on the z-axis
vel.x += 0.001;
else
vel.z += 0.001;
ang = pos.Cross(vel); // recalculate angular momentum
}

const double r_now = pos.Length();

const double LLSqr = ang.LengthSqr();

// total energy
const double EE = vel.LengthSqr() / 2.0 - u / r_now;

if (is_zero_general(centralMass) || is_zero_general(r_now) || is_zero_general(v_now) || is_zero_general(EE) || (ang.z * ang.z / LLSqr > 1.0)) {
ret.m_eccentricity = 0.0;
ret.m_semiMajorAxis = 0.0;
ret.m_velocityAreaPerSecond = 0.0;
ret.m_orbitalPhaseAtStart = 0.0;
ret.m_orient = matrix3x3d::Identity();
return ret;
}
if (is_zero_general(centralMass) || is_zero_general(EE) || (ang.z * ang.z / LLSqr > 1.0))
return Orbit::ForStaticBody(pos);

// http://en.wikipedia.org/wiki/Orbital_eccentricity
ret.m_eccentricity = 1 + 2 * EE * LLSqr / (u * u);
Expand Down
2 changes: 2 additions & 0 deletions src/Orbit.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Orbit {

// note: the resulting Orbit is at the given position at t=0
static Orbit FromBodyState(const vector3d &position, const vector3d &velocity, double central_mass);
static Orbit ForStaticBody(const vector3d &position);

Orbit() :
m_eccentricity(0.0),
Expand Down Expand Up @@ -58,6 +59,7 @@ class Orbit {
double MeanAnomalyFromTrueAnomaly(double trueAnomaly) const;
double MeanAnomalyAtTime(double time) const;

vector3d m_positionForStaticBody;
double m_eccentricity;
double m_semiMajorAxis;
double m_orbitalPhaseAtStart; // 0 to 2 pi radians
Expand Down
44 changes: 31 additions & 13 deletions src/SystemView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ void SystemView::ResetViewpoint()
m_zoomTo = 1.0f / float(AU);
m_timeStep = 1.0f;
m_time = m_game->GetTime();
m_transTo *= 0.0;
m_animateTransition = MAX_TRANSITION_FRAMES;
}

Expand Down Expand Up @@ -263,6 +264,11 @@ void SystemView::GetTransformTo(const SystemBody *b, vector3d &pos)

void SystemView::GetTransformTo(Projectable &p, vector3d &pos)
{
if (m_selectedObject.type == Projectable::NONE) {
// notning selected
pos *= 0.0;
return;
}
// accept only real objects (no orbit icons or lagrange points)
assert(p.type == Projectable::OBJECT);
pos = vector3d(0., 0., 0.);
Expand All @@ -285,16 +291,15 @@ void SystemView::CalculateShipPositionAtTime(const Ship *s, Orbit o, double t, v
pos = vector3d(0., 0., 0.);
FrameId shipFrameId = s->GetFrame();
FrameId shipNonRotFrameId = Frame::GetFrame(shipFrameId)->GetNonRotFrame();
if (s->GetFlightState() != Ship::FlightState::FLYING) {
// if the ship is in a rotating frame, we will rotate it with the frame
if (Frame::GetFrame(shipFrameId)->IsRotFrame()) {
vector3d rpos(0.0);
if (Frame::GetFrame(shipFrameId)->IsRotFrame()) {
Frame *rotframe = Frame::GetFrame(shipFrameId);
if (t == m_game->GetTime()) {
pos = s->GetPositionRelTo(m_game->GetSpace()->GetRootFrame());
return;
} else
rpos = s->GetPositionRelTo(shipNonRotFrameId) * rotframe->GetOrient() * matrix3x3d::RotateY(rotframe->GetAngSpeed() * (t - m_game->GetTime())) * rotframe->GetOrient().Transpose();
}
Frame *rotframe = Frame::GetFrame(shipFrameId);
if (t == m_game->GetTime()) {
pos = s->GetPositionRelTo(m_game->GetSpace()->GetRootFrame());
return;
} else
rpos = s->GetPositionRelTo(shipNonRotFrameId) * rotframe->GetOrient() * matrix3x3d::RotateY(rotframe->GetAngSpeed() * (t - m_game->GetTime())) * rotframe->GetOrient().Transpose();
vector3d fpos(0.0);
CalculateFramePositionAtTime(shipNonRotFrameId, t, fpos);
pos += fpos + rpos;
Expand Down Expand Up @@ -388,16 +393,21 @@ void SystemView::Draw3D()
m_renderer->SetTransform(m_cameraSpace);

// smooth transition animation
m_transTo *= 0.0;
if (m_selectedObject.type != Projectable::NONE) GetTransformTo(m_selectedObject, m_transTo);
if (m_animateTransition) {
// since the object being approached can move, we need to compensate for its movement
// making an imprint of the old value (from previous frame)
m_trans -= m_transTo;
// calculate the new value
GetTransformTo(m_selectedObject, m_transTo);
// now the difference between the new and the old value is added to m_trans
m_trans += m_transTo;
const float ft = Pi::GetFrameTime();
m_animateTransition--;
AnimationCurves::Approach(m_trans.x, m_transTo.x, ft);
AnimationCurves::Approach(m_trans.y, m_transTo.y, ft);
AnimationCurves::Approach(m_trans.z, m_transTo.z, ft);
} else {
m_trans = m_transTo;
GetTransformTo(m_selectedObject, m_trans);
}

vector3d pos = m_trans;
Expand Down Expand Up @@ -537,7 +547,7 @@ void SystemView::DrawShips(const double t, const vector3d &offset)
AddProjected<Body>(Projectable::OBJECT, Projectable::SHIP, static_cast<Body *>((*s).first), pos);
if (m_shipDrawing == ORBITS && (*s).first->GetFlightState() == Ship::FlightState::FLYING) {
vector3d framepos(0.0);
CalculateFramePositionAtTime(Frame::GetFrame((*s).first->GetFrame())->GetNonRotFrame(), m_time, framepos);
CalculateFramePositionAtTime((*s).first->GetFrame(), m_time, framepos);
PutOrbit<Body>(Projectable::SHIP, static_cast<Body *>((*s).first), &(*s).second, offset + framepos, isSelected ? svColor[SELECTED_SHIP_ORBIT] : svColor[SHIP_ORBIT], 0);
}
}
Expand Down Expand Up @@ -649,6 +659,10 @@ void SystemView::SetSelectedObject(Projectable::types type, Projectable::bases b
m_selectedObject.type = type;
m_selectedObject.base = base;
m_selectedObject.ref.sbody = sb;
// we will immediately determine the coordinates of the selected body so that
// there is a correct starting point of the transition animation, otherwise
// there may be an unwanted shift in the next frame
GetTransformTo(m_selectedObject, m_transTo);
m_animateTransition = MAX_TRANSITION_FRAMES;
}

Expand All @@ -657,6 +671,10 @@ void SystemView::SetSelectedObject(Projectable::types type, Projectable::bases b
m_selectedObject.type = type;
m_selectedObject.base = base;
m_selectedObject.ref.body = b;
// we will immediately determine the coordinates of the selected body so that
// there is a correct starting point of the transition animation, otherwise
// there may be an unwanted shift in the next frame
GetTransformTo(m_selectedObject, m_transTo);
m_animateTransition = MAX_TRANSITION_FRAMES;
}

Expand Down
2 changes: 1 addition & 1 deletion src/lua/LuaSystemView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ static int l_systemview_get_projected_grouped(lua_State *l)
touchedGroups.push_back(&group);
//now select the nearest group (if have)
if (touchedGroups.size()) {
GroupInfo *nearest;
GroupInfo *nearest = nullptr;
double min_length = 1e64;
for (GroupInfo *&g : touchedGroups) {
double this_length = (g->m_mainObject.screenpos - special_object[object_type]->screenpos).Length();
Expand Down