Improve/fix system map
- add a "static" orbit for bodies that are not moving anywhere - now bodies in a rotating frame and also in the spaceport frame have such "static" orbits - add display of the orbits of objects moving strictly to the star or from the star - fix compile warning for possibly uninitiated variable in LuaSystemView.cpp - fix an issue where smooth animation sometimes have a hard time catching up with a newly selected object Fixes #5062master
parent
23772169d3
commit
5004b09483
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -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);
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
|
||||
// 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),
|
||||
|
@ -58,6 +59,7 @@ private:
|
|||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue