Skip to content

Commit

Permalink
Fixes and changes for functions in LuaBody
Browse files Browse the repository at this point in the history
Rewrite of GetAltitudeRelTo:
1. This function is moved to body class to support this functionality in C++ code;
2. This function is used in the LUA version of GetAltitudeRelTo, GetGroundPosition and GetGPS for consistency in calculating altitudes;
3. This function supports the choice of which height to calculate (sea-level, above-ground).

Other change:
GetGPS is moved to LuaShip.cpp to support this function for other ships, not only the player.

Fixes for this issues:

1. GetAltitudeRelTo using player pos no matter what first argument is passed;
2. GetGroundPosition returns nil when not in the rotating frame of ref;
3. GetGPS sometimes return different height than GetAltitudeRelTo;
4. Access violation when trying to access frameBody, frameRotation and call GetGroundPosition when body doesn't have frame of ref (ex. when ship is hyperspacing).

Co-Authored-By: Webster Sheets <[email protected]>
  • Loading branch information
Max5377 and sturnclaw committed Oct 19, 2023
1 parent 86153e7 commit 58c31bc
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 87 deletions.
30 changes: 30 additions & 0 deletions src/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,36 @@ vector3d Body::GetVelocityRelTo(const Body *relTo) const
return GetVelocityRelTo(relTo->m_frame) - relTo->GetVelocityRelTo(relTo->m_frame);
}

double Body::GetAltitudeRelTo(const Body* relTo, AltitudeType altType)
{
vector3d pos = GetPositionRelTo(relTo);
double center_dist = pos.Length();
if (relTo && relTo->IsType(ObjectType::TERRAINBODY)) {
const TerrainBody* terrain = static_cast<const TerrainBody*>(relTo);
vector3d surface_pos = pos.Normalized();
double radius;
if (altType != AltitudeType::DEFAULT)
{
radius = altType == AltitudeType::SEA_LEVEL ? terrain->GetSystemBody()->GetRadius() :
terrain->GetTerrainHeight(surface_pos);
}
else
{
radius = terrain->GetSystemBody()->GetRadius();
if (center_dist <= 3.0 * terrain->GetMaxFeatureRadius()) {
radius = terrain->GetTerrainHeight(surface_pos);
}
}
double altitude = center_dist - radius;
if (altitude < 0)
altitude = 0;
return altitude;
}
else {
return center_dist;
}
}

void Body::OrientOnSurface(double radius, double latitude, double longitude)
{
vector3d up = vector3d(cos(latitude) * cos(longitude), sin(latitude) * cos(longitude), sin(longitude));
Expand Down
8 changes: 8 additions & 0 deletions src/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ enum class ObjectType { // <enum name=PhysicsObjectType scope='ObjectType' publi
HYPERSPACECLOUD // <enum skip>
};

enum class AltitudeType {
//SEA_LEVEL if distant, ABOVE_TERRAIN otherwise
DEFAULT,
SEA_LEVEL,
ABOVE_TERRAIN
};

#define OBJDEF(__thisClass, __parentClass, __TYPE) \
static constexpr ObjectType StaticType() { return ObjectType::__TYPE; } \
static constexpr ObjectType SuperType() { return __parentClass::StaticType(); } \
Expand Down Expand Up @@ -175,6 +182,7 @@ class Body : public DeleteEmitter, public PropertiedObject {
vector3d GetInterpPositionRelTo(FrameId relToId) const;
vector3d GetInterpPositionRelTo(const Body *relTo) const;
matrix3x3d GetInterpOrientRelTo(FrameId relToId) const;
double GetAltitudeRelTo(const Body* relTo, AltitudeType altType = AltitudeType::DEFAULT);

// should set m_interpolatedTransform to the smoothly interpolated value
// (interpolated by 0 <= alpha <=1) between the previous and current physics tick
Expand Down
74 changes: 47 additions & 27 deletions src/lua/LuaBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "Ship.h"
#include "SpaceStation.h"
#include "Star.h"
#include <unordered_map>

namespace PiGui {
// Declared in LuaPiGuiInternal.h
Expand Down Expand Up @@ -375,6 +376,8 @@ static int l_body_get_position_rel_to(lua_State *l)
* Parameters:
*
* other - the other body
* (optional) altType - what altitude to calculate (sea-level, above-ground)
* if not specified, sea-level for distant bodies, above-ground otherwise
*
* Availability:
*
Expand All @@ -385,27 +388,33 @@ static int l_body_get_position_rel_to(lua_State *l)
* stable
*/

static std::unordered_map<std::string, AltitudeType> altitudeTypesStringMap =
{
{"default", AltitudeType::DEFAULT},
{"sea-level", AltitudeType::SEA_LEVEL},
{"above-ground", AltitudeType::ABOVE_TERRAIN}
};

static int l_body_get_altitude_rel_to(lua_State *l)
{
Body *b = LuaObject<Body>::CheckFromLua(1);
const Body *other = LuaObject<Body>::CheckFromLua(2);
vector3d pos = Pi::player->GetPositionRelTo(other);
double center_dist = pos.Length();
if (other && other->IsType(ObjectType::TERRAINBODY)) {
const TerrainBody *terrain = static_cast<const TerrainBody *>(other);
vector3d surface_pos = pos.Normalized();
double radius = terrain->GetSystemBody()->GetRadius();
if (center_dist <= 3.0 * terrain->GetMaxFeatureRadius()) {
radius = terrain->GetTerrainHeight(surface_pos);
std::string typeString = LuaPull<const char*>(l, 3, "default");
AltitudeType altType = AltitudeType::DEFAULT;
if (typeString.compare("default"))
{
if (auto str = altitudeTypesStringMap.find(typeString); str != altitudeTypesStringMap.end())
{
altType = str->second;
}
else
{
return luaL_error(l, "invalid altitude type: %s", typeString.c_str());
}
double altitude = center_dist - radius;
if (altitude < 0)
altitude = 0;
LuaPush(l, altitude);
return 1;
} else {
LuaPush(l, center_dist);
return 1;
}
double altitude = b->GetAltitudeRelTo(other, altType);
LuaPush(l, altitude);
return 1;
}

/*
Expand Down Expand Up @@ -493,6 +502,13 @@ static int l_body_attr_frame_body(lua_State *l)
}

Frame *f = Frame::GetFrame(b->GetFrame());

if (!f)
{
lua_pushnil(l);
return 1;
}

LuaObject<Body>::PushToLua(f->GetBody());
return 1;
}
Expand Down Expand Up @@ -522,6 +538,12 @@ static int l_body_attr_frame_rotating(lua_State *l)
}

Frame *f = Frame::GetFrame(b->GetFrame());
if (!f)
{
lua_pushnil(l);
return 1;
}

lua_pushboolean(l, f->IsRotFrame());
return 1;
}
Expand Down Expand Up @@ -601,8 +623,7 @@ static int l_body_distance_to(lua_State *l)
/*
* Method: GetGroundPosition
*
* Get latitude, longitude and altitude of a dynamic body close to the ground or nil the body is not a dynamic body
* or is not close to the ground.
* Get latitude, longitude and altitude of frame of ref of a dynamic body or nil if the body is not a dynamic body
*
* > latitude, longitude, altitude = body:GetGroundPosition()
*
Expand All @@ -629,29 +650,28 @@ static int l_body_distance_to(lua_State *l)
*/
static int l_body_get_ground_position(lua_State *l)
{

Body *b = LuaObject<Body>::CheckFromLua(1);
if (!b->IsType(ObjectType::DYNAMICBODY)) {
lua_pushnil(l);
return 1;
}

Frame *f = Frame::GetFrame(b->GetFrame());
if (!f->IsRotFrame())
return 0;

if (!f)
{
lua_pushnil(l);
return 1;
}
vector3d pos = b->GetPosition();
double latitude = atan2(pos.y, sqrt(pos.x * pos.x + pos.z * pos.z));
double longitude = atan2(pos.x, pos.z);
lua_pushnumber(l, latitude);
lua_pushnumber(l, longitude);
Body *astro = f->GetBody();
if (astro->IsType(ObjectType::TERRAINBODY)) {
double radius = static_cast<TerrainBody *>(astro)->GetTerrainHeight(pos.Normalized());
double altitude = pos.Length() - radius;
lua_pushnumber(l, altitude);
} else {
lua_pushnil(l);
}
double altitude = b->GetAltitudeRelTo(astro);
lua_pushnumber(l, altitude);
return 3;
}

Expand Down
60 changes: 0 additions & 60 deletions src/lua/LuaPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,65 +576,6 @@ static int l_toggle_rotation_damping(lua_State *l)
return 0;
}

/*
* Function: GetGPS()
*
* Get altitude, speed, and position of player's ship
*
* Example:
*
* > alt, vspd, lat, long = player:GetGPS()
*
* Returns:
*
* alt - altitude
*
* vspd - vertical speed
*
* latitude - latitude
*
* longitude - longitude
*
*/
static int l_get_gps(lua_State *l)
{
Player *player = LuaObject<Player>::CheckFromLua(1);
vector3d pos = Pi::player->GetPosition();
double center_dist = pos.Length();
FrameId playerFrameId = player->GetFrame();
Frame *playerFrame = Frame::GetFrame(playerFrameId);
if (playerFrameId.valid()) {
Body *astro = Frame::GetFrame(playerFrameId)->GetBody();
if (astro && astro->IsType(ObjectType::TERRAINBODY)) {
TerrainBody *terrain = static_cast<TerrainBody *>(astro);
if (!playerFrame->IsRotFrame())
playerFrame = Frame::GetFrame(playerFrame->GetRotFrame());
vector3d surface_pos = pos.Normalized();
double radius = terrain->GetSystemBody()->GetRadius();
if (center_dist <= 3.0 * terrain->GetMaxFeatureRadius()) {
radius = terrain->GetTerrainHeight(surface_pos);
}
double altitude = center_dist - radius;
vector3d velocity = player->GetVelocity();
double vspeed = velocity.Dot(surface_pos);
if (fabs(vspeed) < 0.05) vspeed = 0.0; // Avoid alternating between positive/negative zero

// RefreshHeadingPitch();

if (altitude < 0) altitude = 0;
LuaPush(l, altitude);
LuaPush(l, vspeed);
const float lat = RAD2DEG(asin(surface_pos.y));
const float lon = RAD2DEG(atan2(surface_pos.x, surface_pos.z));
LuaPush(l, lat);
LuaPush(l, lon);
return 4;
// }
}
}
return 0;
}

static int l_get_alert_state(lua_State *l)
{
Player *player = LuaObject<Player>::CheckFromLua(1);
Expand Down Expand Up @@ -883,7 +824,6 @@ void LuaObject<Player>::RegisterClass()
{ "GetMouseDirection", l_get_mouse_direction },
{ "GetRotationDamping", l_get_rotation_damping },
{ "SetRotationDamping", l_set_rotation_damping },
{ "GetGPS", l_get_gps },
{ "ToggleRotationDamping", l_toggle_rotation_damping },
{ "GetAlertState", l_get_alert_state },
{ "GetLowThrustPower", l_get_low_thrust_power },
Expand Down
53 changes: 53 additions & 0 deletions src/lua/LuaShip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,58 @@ static int l_ship_get_position(lua_State *l)
return 1;
}

/*
* Function: GetGPS()
*
* Get altitude, speed, and position of a ship
*
* Example:
*
* > alt, vspd, lat, long = ship:GetGPS()
*
* Returns:
*
* alt - altitude
*
* vspd - vertical speed
*
* latitude - latitude
*
* longitude - longitude
*
*/
static int l_get_gps(lua_State* l)
{
Ship* ship = LuaObject<Ship>::CheckFromLua(1);
vector3d pos = ship->GetPosition();
FrameId shipFrameId = ship->GetFrame();
Frame* shipFrame = Frame::GetFrame(shipFrameId);
if (shipFrameId.valid()) {
Body* astro = Frame::GetFrame(shipFrameId)->GetBody();
if (astro && astro->IsType(ObjectType::TERRAINBODY)) {
if (!shipFrame->IsRotFrame())
shipFrame = Frame::GetFrame(shipFrame->GetRotFrame());
double altitude = ship->GetAltitudeRelTo(astro);
vector3d surface_pos = pos.Normalized();
vector3d velocity = ship->GetVelocity();
double vspeed = velocity.Dot(surface_pos);
if (fabs(vspeed) < 0.05) vspeed = 0.0; // Avoid alternating between positive/negative zero

// RefreshHeadingPitch();

LuaPush(l, altitude);
LuaPush(l, vspeed);
const float lat = RAD2DEG(asin(surface_pos.y));
const float lon = RAD2DEG(atan2(surface_pos.x, surface_pos.z));
LuaPush(l, lat);
LuaPush(l, lon);
return 4;
// }
}
}
return 0;
}

/* Method: GetHullTemperature
*
* Return the current hull temperature (0.0 - 1.0).
Expand Down Expand Up @@ -1721,6 +1773,7 @@ void LuaObject<Ship>::RegisterClass()

{ "GetHyperspaceCountdown", l_ship_get_hyperspace_countdown },
{ "IsHyperspaceActive", l_ship_is_hyperspace_active },
{ "GetGPS", l_get_gps },

{ "GetHullTemperature", l_ship_get_hull_temperature },
{ "GetGunTemperature", l_ship_get_gun_temperature },
Expand Down

0 comments on commit 58c31bc

Please sign in to comment.