Skip to content
Open
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
6 changes: 6 additions & 0 deletions code/io/spacemouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ std::unique_ptr<SpaceMouse> SpaceMouse::searchSpaceMice(int pollingFrequency) {
return mouse;
}

SpaceMouse* SpaceMouse::getSharedSpaceMouse(int pollingFrequency)
{
static std::unique_ptr<SpaceMouse> sharedMouse = SpaceMouse::searchSpaceMice(pollingFrequency);
return sharedMouse.get();
}

#define HANDLE_NONLINEARITY(field, idx) field = copysignf(powf(field, std::get<0>(spacemouse_nonlinearity[idx])) * std::get<1>(spacemouse_nonlinearity[idx]), field)

void SpaceMouseMovement::handleNonlinearities(std::array<std::tuple<float, float>, 6>& spacemouse_nonlinearity) {
Expand Down
9 changes: 9 additions & 0 deletions code/io/spacemouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ namespace io
@returns An optional SpaceMouse object, if found
*/
static std::unique_ptr<SpaceMouse> searchSpaceMice(int pollingFrequency = 10);

/*
@brief Returns a shared SpaceMouse instance for the process.

This avoids opening the same HID device from multiple call sites.
@param pollingFrequency Polling frequency to use when creating the shared instance.
@returns A pointer to the shared SpaceMouse instance, or nullptr if no supported device is present.
*/
static SpaceMouse* getSharedSpaceMouse(int pollingFrequency = 10);
};
}
}
2 changes: 2 additions & 0 deletions qtfred/source_groups.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ if (WIN32)
endif()

add_file_folder("Source/Mission"
src/mission/CameraController.cpp
src/mission/CameraController.h
src/mission/Editor.cpp
src/mission/EditorWing.cpp
src/mission/Editor.h
Expand Down
108 changes: 108 additions & 0 deletions qtfred/src/mission/CameraController.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include "CameraController.h"

#include "ui/ControlBindings.h"

#include <io/spacemouse.h>
#include <mod_table/mod_table.h>

namespace fso::fred {

void CameraController::resetView() {
vec3d f, u, r;

physics_init(&view_physics);
view_physics.max_vel.xyz.z = 5.0f;
view_physics.max_rotvel.xyz.x = 1.5f;
memset(&view_controls, 0, sizeof(control_info));

vm_vec_make(&view_pos, 0.0f, 150.0f, -200.0f);
vm_vec_make(&f, 0.0f, -0.5f, 0.866025404f);
vm_vec_make(&u, 0.0f, 0.866025404f, 0.5f);
vm_vec_make(&r, 1.0f, 0.0f, 0.0f);
vm_vector_2_matrix(&view_orient, &f, &u, &r);
}

void CameraController::resetViewPhysics() {
physics_init(&view_physics);
view_physics.max_vel.xyz.x *= _physicsSpeed / 3.0f;
view_physics.max_vel.xyz.y *= _physicsSpeed / 3.0f;
view_physics.max_vel.xyz.z *= _physicsSpeed / 3.0f;
view_physics.max_rear_vel *= _physicsSpeed / 3.0f;
view_physics.max_rotvel.xyz.x *= _physicsRot / 30.0f;
view_physics.max_rotvel.xyz.y *= _physicsRot / 30.0f;
view_physics.max_rotvel.xyz.z *= _physicsRot / 30.0f;
view_physics.flags |= PF_ACCELERATES | PF_SLIDE_ENABLED;
}

void CameraController::savePosition() {
saved_cam_pos = view_pos;
saved_cam_orient = view_orient;
}

void CameraController::restorePosition() {
view_pos = saved_cam_pos;
view_orient = saved_cam_orient;
}

bool CameraController::hasSavedPosition() const {
return !IS_VEC_NULL(&saved_cam_orient.vec.fvec);
}

bool CameraController::hasEyeMoved() {
if (vm_vec_cmp(&eye_pos, &Last_eye_pos) || vm_matrix_cmp(&eye_orient, &Last_eye_orient)) {
Last_eye_pos = eye_pos;
Last_eye_orient = eye_orient;
return true;
}
return false;
}

const matrix& CameraController::getLastRotMat() const {
return view_physics.last_rotmat;
}

bool CameraController::processControls(vec3d* pos, matrix* orient, float frametime, bool use_editor_physics) {
io::spacemouse::SpaceMouse* const spacemouse = io::spacemouse::SpaceMouse::getSharedSpaceMouse(0);

memset(&view_controls, 0, sizeof(control_info));

if (spacemouse != nullptr) {
auto spacemouse_movement = spacemouse->getMovement();
spacemouse_movement.handleNonlinearities(Fred_spacemouse_nonlinearity);
view_controls.pitch += spacemouse_movement.rotation.p;
view_controls.vertical += spacemouse_movement.translation.xyz.z;
view_controls.heading += spacemouse_movement.rotation.h;
view_controls.sideways += spacemouse_movement.translation.xyz.x;
view_controls.bank += spacemouse_movement.rotation.b;
view_controls.forward += spacemouse_movement.translation.xyz.y;
}

auto& bindings = ControlBindings::instance();
view_controls.pitch += bindings.isPressed(ControlAction::PitchUp) ? -1.0f : 0.0f;
view_controls.pitch += bindings.isPressed(ControlAction::PitchDown) ? 1.0f : 0.0f;
view_controls.heading += bindings.isPressed(ControlAction::YawLeft) ? -1.0f : 0.0f;
view_controls.heading += bindings.isPressed(ControlAction::YawRight) ? 1.0f : 0.0f;
view_controls.sideways += bindings.isPressed(ControlAction::MoveLeft) ? -1.0f : 0.0f;
view_controls.sideways += bindings.isPressed(ControlAction::MoveRight) ? 1.0f : 0.0f;
view_controls.forward += bindings.isPressed(ControlAction::MoveForward) ? 1.0f : 0.0f;
view_controls.forward += bindings.isPressed(ControlAction::MoveBackward) ? -1.0f : 0.0f;
view_controls.vertical += bindings.isPressed(ControlAction::MoveUp) ? 1.0f : 0.0f;
view_controls.vertical += bindings.isPressed(ControlAction::MoveDown) ? -1.0f : 0.0f;

bool wantsUpdate = (fabs(view_controls.pitch) > (frametime / 100))
|| (fabs(view_controls.vertical) > (frametime / 100))
|| (fabs(view_controls.heading) > (frametime / 100))
|| (fabs(view_controls.sideways) > (frametime / 100))
|| (fabs(view_controls.bank) > (frametime / 100))
|| (fabs(view_controls.forward) > (frametime / 100));

physics_read_flying_controls(orient, &view_physics, &view_controls, frametime);
if (use_editor_physics) {
physics_sim_editor(pos, orient, &view_physics, frametime);
} else {
physics_sim(pos, orient, &view_physics, &vmd_zero_vector, frametime);
}
return wantsUpdate;
}

} // namespace fso::fred
66 changes: 66 additions & 0 deletions qtfred/src/mission/CameraController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#pragma once

#include <globalincs/pstypes.h>
#include <physics/physics.h>

namespace fso::fred {

class CameraController {
physics_info view_physics;
control_info view_controls;

vec3d saved_cam_pos = vmd_zero_vector;
matrix saved_cam_orient = {};

vec3d Last_eye_pos = vmd_zero_vector;
matrix Last_eye_orient = vmd_identity_matrix;

int _physicsSpeed = 1;
int _physicsRot = 25;
int _viewpoint = 0;
int _viewObj = -1;
int _controlMode = 0;
bool _lookatMode = false;

public:
vec3d eye_pos;
matrix eye_orient;

vec3d view_pos;
matrix view_orient = vmd_identity_matrix;

void resetView();
void resetViewPhysics();

void savePosition();
void restorePosition();
bool hasSavedPosition() const;

bool hasEyeMoved();

const matrix& getLastRotMat() const;

// Returns true if the caller should schedule a view update
bool processControls(vec3d* pos, matrix* orient, float frametime, bool use_editor_physics);

int getPhysicsSpeed() const { return _physicsSpeed; }
void setPhysicsSpeed(int speed) { _physicsSpeed = speed; resetViewPhysics(); }

int getPhysicsRot() const { return _physicsRot; }
void setPhysicsRot(int rot) { _physicsRot = rot; resetViewPhysics(); }

int getViewpoint() const { return _viewpoint; }
void setViewpoint(int vp) { _viewpoint = vp; }

int getViewObj() const { return _viewObj; }
void setViewObj(int obj) { _viewObj = obj; }

int getControlMode() const { return _controlMode; }
void setControlMode(int mode) { _controlMode = mode; }
void toggleControlMode() { _controlMode = (_controlMode + 1) % 2; }

bool getLookatMode() const { return _lookatMode; }
void setLookatMode(bool mode) { _lookatMode = mode; }
};

} // namespace fso::fred
14 changes: 6 additions & 8 deletions qtfred/src/mission/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ int Editor::autosave(const char* /*desc*/) {

Fred_mission_save save;
save.set_always_save_display_names(_lastActiveViewport->Always_save_display_names);
save.set_view_pos(_lastActiveViewport->view_pos);
save.set_view_orient(_lastActiveViewport->view_orient);
save.set_view_pos(_lastActiveViewport->camera.view_pos);
save.set_view_orient(_lastActiveViewport->camera.view_orient);
save.set_fred_alt_names(Fred_alt_names);
save.set_fred_callsigns(Fred_callsigns);

Expand Down Expand Up @@ -460,8 +460,8 @@ bool Editor::loadMission(const std::string& mission_name, int flags) {
}

for (auto& viewport : _viewports) {
viewport->view_orient = Parse_viewer_orient;
viewport->view_pos = Parse_viewer_pos;
viewport->camera.view_orient = Parse_viewer_orient;
viewport->camera.view_pos = Parse_viewer_pos;
}

if (flags & MPF_IS_TEMPLATE) {
Expand All @@ -479,8 +479,7 @@ bool Editor::loadMission(const std::string& mission_name, int flags) {
strcpy_s(The_mission.mission_desc, "Put mission description here");

for (auto& viewport : _viewports) {
viewport->resetView();
viewport->resetViewPhysics();
viewport->reset();
}
}

Expand Down Expand Up @@ -654,8 +653,7 @@ void Editor::clearMission(bool fast_reload) {
unmark_all();

for (auto& viewport : _viewports) {
viewport->resetView();
viewport->resetViewPhysics();
viewport->reset();
}

Event_annotations.clear();
Expand Down
Loading
Loading