add flyby camera view

Signed-off-by: Paul B Mahol <onemda@gmail.com>
master
Paul B Mahol 2018-06-20 19:30:31 +02:00
parent eaad62391f
commit 7742a5ddcc
10 changed files with 170 additions and 10 deletions

View File

@ -415,6 +415,10 @@
"description": "",
"message": "Fire missile"
},
"FLYBY_VIEW": {
"description": "camera view setting",
"message": "Flyby view"
},
"FOLLOWING_SELECTION": {
"description": "",
"message": "following selection"

View File

@ -579,6 +579,10 @@
"description": "Tooltip: fix heading retrograde",
"message": "Fix heading retrograde"
},
"HUD_BUTTON_FLYBY_VIEW": {
"description": "Tooltip: Flyby camera view",
"message": "Flyby view"
},
"HUD_BUTTON_HYPERDRIVE_DISABLED": {
"description": "Tooltip: Hyperdrive disabled (docked or landed)",
"message": "Hyperdrive disabled"

View File

@ -27,8 +27,8 @@ end
local currentView = "internal"
local next_cam_type = { ["internal"] = "external", ["external"] = "sidereal", ["sidereal"] = "internal" }
local cam_tooltip = { ["internal"] = lui.HUD_BUTTON_INTERNAL_VIEW, ["external"] = lui.HUD_BUTTON_EXTERNAL_VIEW, ["sidereal"] = lui.HUD_BUTTON_SIDEREAL_VIEW }
local next_cam_type = { ["internal"] = "external", ["external"] = "sidereal", ["sidereal"] = "internal", ["flyby"] = "internal" }
local cam_tooltip = { ["internal"] = lui.HUD_BUTTON_INTERNAL_VIEW, ["external"] = lui.HUD_BUTTON_EXTERNAL_VIEW, ["sidereal"] = lui.HUD_BUTTON_SIDEREAL_VIEW, ["flyby"] = lui.HUD_BUTTON_FLYBY_VIEW }
local function button_world(current_view)
ui.sameLine()
if current_view ~= "world" then
@ -40,6 +40,9 @@ local function button_world(current_view)
if mainMenuButton(icons["view_" .. camtype], true, cam_tooltip[camtype]) or (ui.noModifierHeld() and ui.isKeyReleased(ui.keys.f1)) then
Game.SetWorldCamType(next_cam_type[camtype])
end
if (ui.altHeld() and ui.isKeyReleased(ui.keys.f1)) then
Game.SetWorldCamType("flyby")
end
end
end

View File

@ -233,6 +233,7 @@ theme.icons = {
hud = 168,
factory = 169,
star = 170,
view_flyby = 191,
-- TODO: manual / autopilot
-- dummy, until actually defined correctly
mouse_move_direction = 14,

View File

@ -26,12 +26,16 @@ void CameraController::Reset()
void CameraController::Update()
{
m_camera->SetFrame(m_ship->GetFrame());
// interpolate between last physics tick position and current one,
// to remove temporal aliasing
const matrix3x3d &m = m_ship->GetInterpOrient();
m_camera->SetOrient(m * m_orient);
m_camera->SetPosition(m * m_pos + m_ship->GetInterpPosition());
if (GetType() == FLYBY) {
m_camera->SetOrient(m_orient);
m_camera->SetPosition(m_pos);
} else {
// interpolate between last physics tick position and current one,
// to remove temporal aliasing
const matrix3x3d &m = m_ship->GetInterpOrient();
m_camera->SetOrient(m * m_orient);
m_camera->SetPosition(m * m_pos + m_ship->GetInterpPosition());
}
}
@ -404,3 +408,104 @@ void SiderealCameraController::LoadFromJson(const Json::Value &jsonObj)
m_dist = StrToDouble(siderealCameraObj["dist"].asString());
m_distTo = m_dist;
}
FlyByCameraController::FlyByCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship) :
MoveableCameraController(camera, ship),
m_dist(500), m_distTo(m_dist),
m_roll(0)
{
}
void FlyByCameraController::ZoomIn(float frameTime)
{
ZoomOut(-frameTime);
}
void FlyByCameraController::ZoomOut(float frameTime)
{
m_dist += 400 * frameTime;
m_dist = std::max(GetShip()->GetClipRadius(), m_dist);
m_distTo = m_dist;
}
void FlyByCameraController::ZoomEvent(float amount)
{
m_distTo += 400 * amount;
m_distTo = std::max(GetShip()->GetClipRadius(), m_distTo);
}
void FlyByCameraController::ZoomEventUpdate(float frameTime)
{
AnimationCurves::Approach(m_dist, m_distTo, frameTime, 4.0, 50. / std::max(m_distTo, 1e-7)); // std::max() here just avoid dividing by 0.
m_dist = std::max(GetShip()->GetClipRadius(), m_dist);
}
void FlyByCameraController::RollLeft(float frameTime)
{
m_roll += M_PI / 4 * frameTime;
}
void FlyByCameraController::RollRight(float frameTime)
{
m_roll += -M_PI / 4 * frameTime;
}
void FlyByCameraController::Reset()
{
m_dist = 500;
m_distTo = m_dist;
SetPosition(vector3d(0, 0, 0));
}
static matrix3x3d LookAt(const vector3d eye, const vector3d target, const vector3d up)
{
const vector3d z = (eye - target).NormalizedSafe();
const vector3d x = (up.Cross(z)).NormalizedSafe();
const vector3d y = (z.Cross(x)).NormalizedSafe();
return matrix3x3d::FromVectors(x, y, z);
}
void FlyByCameraController::Update()
{
const Ship *ship = GetShip();
matrix3x3d camerao;
vector3d ship_pos = ship->GetInterpPosition();
vector3d camerap;
if (GetPosition() == vector3d(0, 0, 0) || m_old_frame != ship->GetFrame()) {
m_old_pos = ship_pos;
m_old_frame = ship->GetFrame();
}
camerap = m_old_pos + vector3d(0, 0, 2) * m_dist;
SetPosition(camerap);
camerao = LookAt(camerap, ship_pos, vector3d(0, 1, 0));
const vector3d rotAxis = camerao.VectorZ();
camerao = matrix3x3d::Rotate(m_roll, rotAxis) * camerao;
SetOrient(camerao);
CameraController::Update();
}
void FlyByCameraController::SaveToJson(Json::Value &jsonObj)
{
Json::Value flybyCameraObj(Json::objectValue); // Create JSON object to contain flyby camera data.
flybyCameraObj["roll"] = FloatToStr(m_roll);
flybyCameraObj["dist"] = DoubleToStr(m_dist);
jsonObj["flyby"] = flybyCameraObj; // Add flyby camera object to supplied object.
}
void FlyByCameraController::LoadFromJson(const Json::Value &jsonObj)
{
if (!jsonObj.isMember("flyby")) return; //throw SavedGameCorruptException();
Json::Value flybyCameraObj = jsonObj["flyby"];
if (!flybyCameraObj.isMember("dist")) throw SavedGameCorruptException();
m_roll = StrToFloat(flybyCameraObj["roll"].asString());
m_dist = StrToDouble(flybyCameraObj["dist"].asString());
m_distTo = m_dist;
}

View File

@ -18,7 +18,8 @@ public:
enum Type { //can be used for serialization & identification
INTERNAL,
EXTERNAL,
SIDEREAL
SIDEREAL,
FLYBY
};
CameraController(RefCountedPtr<CameraContext> camera, const Ship *ship);
@ -187,4 +188,33 @@ private:
matrix3x3d m_sidOrient;
};
// Zoomable, fly by camera, always looks at the ship
class FlyByCameraController : public MoveableCameraController {
public:
FlyByCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship);
Type GetType() const { return FLYBY; }
const char *GetName() const { return Lang::FLYBY_VIEW; }
void RollLeft(float frameTime);
void RollRight(float frameTime);
void ZoomIn(float frameTime);
void ZoomOut(float frameTime);
void ZoomEvent(float amount);
void ZoomEventUpdate(float frameTime);
void Reset();
bool IsExternal() const { return true; }
void SaveToJson(Json::Value &jsonObj);
void LoadFromJson(const Json::Value &jsonObj);
void Update();
private:
double m_dist, m_distTo;
float m_roll;
vector3d m_old_pos;
Frame *m_old_frame;
};
#endif

View File

@ -166,6 +166,7 @@ DECLARE_STRING(GENERAL_VIEW_CONTROLS)
DECLARE_STRING(INTERNAL_VIEW)
DECLARE_STRING(EXTERNAL_VIEW)
DECLARE_STRING(SIDEREAL_VIEW)
DECLARE_STRING(FLYBY_VIEW)
DECLARE_STRING(SECTOR_MAP_VIEW)
DECLARE_STRING(SEARCH_MAP)
DECLARE_STRING(MAP_LOCK_HYPERSPACE_TARGET)

View File

@ -591,6 +591,7 @@ static int l_game_get_world_cam_type(lua_State *l)
case WorldView::CAM_INTERNAL: lua_pushstring(l, "internal"); break;
case WorldView::CAM_EXTERNAL: lua_pushstring(l, "external"); break;
case WorldView::CAM_SIDEREAL: lua_pushstring(l, "sidereal"); break;
case WorldView::CAM_FLYBY: lua_pushstring(l, "flyby"); break;
default: Output("Unknown world view cam type\n"); break;
}
return 1;
@ -617,6 +618,8 @@ static int l_game_set_world_cam_type(lua_State *l)
Pi::game->GetWorldView()->SetCamType(WorldView::CAM_EXTERNAL);
else if(!cam.compare("sidereal"))
Pi::game->GetWorldView()->SetCamType(WorldView::CAM_SIDEREAL);
else if(!cam.compare("flyby"))
Pi::game->GetWorldView()->SetCamType(WorldView::CAM_FLYBY);
else {
// TODO else error
}

View File

@ -70,6 +70,7 @@ WorldView::WorldView(const Json::Value &jsonObj, Game* game) : UIView(), m_game(
m_internalCameraController->LoadFromJson(worldViewObj);
m_externalCameraController->LoadFromJson(worldViewObj);
m_siderealCameraController->LoadFromJson(worldViewObj);
m_flybyCameraController->LoadFromJson(worldViewObj);
}
void WorldView::InitObject()
@ -156,6 +157,7 @@ void WorldView::InitObject()
m_internalCameraController.reset(new InternalCameraController(m_cameraContext, Pi::player));
m_externalCameraController.reset(new ExternalCameraController(m_cameraContext, Pi::player));
m_siderealCameraController.reset(new SiderealCameraController(m_cameraContext, Pi::player));
m_flybyCameraController.reset(new FlyByCameraController(m_cameraContext, Pi::player));
SetCamType(m_camType); //set the active camera
m_onPlayerChangeTargetCon =
@ -186,6 +188,7 @@ void WorldView::SaveToJson(Json::Value &jsonObj)
m_internalCameraController->SaveToJson(worldViewObj);
m_externalCameraController->SaveToJson(worldViewObj);
m_siderealCameraController->SaveToJson(worldViewObj);
m_flybyCameraController->SaveToJson(worldViewObj);
jsonObj["world_view"] = worldViewObj; // Add world view object to supplied object.
}
@ -212,6 +215,9 @@ void WorldView::SetCamType(enum CamType c)
case CAM_SIDEREAL:
m_activeCameraController = m_siderealCameraController.get();
break;
case CAM_FLYBY:
m_activeCameraController = m_flybyCameraController.get();
break;
}
Pi::player->GetPlayerController()->SetMouseForRearView(m_camType == CAM_INTERNAL && m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR);
@ -774,6 +780,7 @@ int WorldView::GetActiveWeapon() const
case CAM_EXTERNAL:
case CAM_SIDEREAL:
case CAM_FLYBY:
default:
return 0;
}

View File

@ -55,7 +55,8 @@ public:
enum CamType {
CAM_INTERNAL,
CAM_EXTERNAL,
CAM_SIDEREAL
CAM_SIDEREAL,
CAM_FLYBY
};
void SetCamType(enum CamType);
enum CamType GetCamType() const { return m_camType; }
@ -180,6 +181,7 @@ private:
std::unique_ptr<InternalCameraController> m_internalCameraController;
std::unique_ptr<ExternalCameraController> m_externalCameraController;
std::unique_ptr<SiderealCameraController> m_siderealCameraController;
std::unique_ptr<FlyByCameraController> m_flybyCameraController;
CameraController *m_activeCameraController; //one of the above
Indicator m_combatTargetIndicator;