Files
Goober5000 86f75c5d17 fix normalized vector handling (#6650)
Although normalized vectors in FSO are supposed to stay normalized, occasionally small floating point errors can pop up.  In most cases these do not cause a problem, but in certain cases these errors can rapidly accumulate and corrupt an otherwise well-behaved matrix.  This can most easily be seen with daisy-chained dock sequences or docked ships with angled dockpoints.

This PR audits the usage of `vm_vector_2_matrix_norm` to re-normalize vectors in cases where floating point errors could accumulate.  There are also a few new Assertions for extra vigilance.

Follow-up to #6596.  Fixes #6634.
2025-03-28 23:54:51 +01:00

199 lines
5.5 KiB
C++

#ifndef _CAMERA_H
#define _CAMERA_H
#include "globalincs/globals.h"
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "object/object.h"
#include "physics/physics.h" //for avd
#include <string>
#include <variant>
#define CAM_STATIONARY_FOV (1<<0)
#define CAM_STATIONARY_ORI (1<<1)
#define CAM_STATIONARY_POS (1<<2)
#define CAM_DEFAULT_FLAGS 0
#define EXTERN_CAM_BBOX_CONSTANT_PADDING 5.0f
#define EXTERN_CAM_BBOX_MULTIPLIER_PADDING 1.5f
#define DEFAULT_FOV 0.75f;
struct asymmetric_fov {
float left, right, up, down;
friend asymmetric_fov operator* (const asymmetric_fov&, const float&);
friend asymmetric_fov operator+ (const asymmetric_fov&, const float&);
friend asymmetric_fov operator- (const asymmetric_fov&, const float&);
};
using fov_t = std::variant<float, asymmetric_fov>;
fov_t operator* (const fov_t&, const float&);
fov_t operator+ (const fov_t&, const float&);
fov_t operator- (const fov_t&, const float&);
class camera
{
protected:
char name[NAME_LENGTH];
int sig;
int flags;
object_h object_host;
int object_host_submodel;
object_h object_target;
int object_target_submodel;
void (*func_custom_position)(camera *cam, vec3d *pos);
void (*func_custom_orientation)(camera *cam, matrix *ori);
avd_movement fov;
avd_movement pos_x;
avd_movement pos_y;
avd_movement pos_z;
avd_movement ori[9];
//Cache stuff
fov_t c_fov;
vec3d c_pos;
matrix c_ori;
public:
camera(const char *in_name=NULL, int in_signature=-1);
~camera();
void clear();
void reset();
//Set
void set_name(const char *in_name);
void set_object_host(object *objp, int n_object_host_submodel = -1);
void set_object_target(object *objp, int n_object_target_submodel = -1);
void set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *pos));
void set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *ori));
void set_fov(fov_t in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_position(vec3d *in_position = NULL, float in_translation_time = 0.0f, float in_translation_acceleration_time = 0.0f, float in_translation_deceleration_time = 0.0f, float in_end_velocity = 0.0f);
void set_rotation(matrix *in_orientation = NULL, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
void set_rotation(angles *in_angles, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
void set_rotation_facing(vec3d *in_target, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
//Get
const char* get_name() { return name; }
int get_signature() {return sig;}
object *get_object_host();
int get_object_host_submodel();
object *get_object_target();
int get_object_target_submodel();
fov_t get_fov();
void get_info(vec3d *position, matrix *orientation, bool apply_camera_orientation = true);
//Is
bool is_empty(){return sig < 0;}
//Do
void do_frame(float in_frametime);
};
class warp_camera
{
private:
float c_time;
float c_damping;
vec3d c_vel;
vec3d c_desired_vel;
vec3d c_pos;
matrix c_ori;
public:
warp_camera();
warp_camera(object *objp);
void reset();
void set_position(vec3d *in_pos);
void set_rotation(matrix *in_ori);
void set_velocity(vec3d *in_vel, bool instantaneous);
void do_frame(float in_frametime);
void get_info(vec3d *position, matrix *orientation);
};
extern warp_camera Warp_camera;
class subtitle
{
private:
void clone(const subtitle &sub);
SCP_vector<SCP_string> text_lines;
struct { int x; int y; } text_pos;
float display_time;
float fade_time;
color text_color;
int text_fontnum;
int line_height_modifier;
//Done with set
char imageanim[MAX_FILENAME_LEN];
int image_id;
struct { int x; int y; int w; int h; } image_pos;
//Time this has been displayed
float time_displayed;
//When to end it
float time_displayed_end;
bool post_shaded;
bool do_screen_scaling;
public:
subtitle(int in_x_pos, int in_y_pos, const char* in_text = NULL, const char* in_imageanim = NULL,
float in_display_time = 0, float in_fade_time = 0.0f, const color *in_text_color = NULL, int in_text_fontnum = -1,
bool center_x = false, bool center_y = false, int in_width = 0, int in_height = 0, bool post_shaded = false,
int in_line_height_modifier = 0, bool in_adjust_wh = true);
~subtitle();
subtitle(const subtitle &sub) { clone(sub); }
subtitle& operator=(const subtitle &sub);
void do_frame(float frametime);
bool is_post_shaded( ) { return post_shaded; }
};
//Some global stuff
extern SCP_vector<subtitle> Subtitles;
extern fov_t VIEWER_ZOOM_DEFAULT;
extern fov_t COCKPIT_ZOOM_DEFAULT;
extern float Sexp_fov;
//Helpful functions
void cam_init();
void cam_close();
void cam_do_frame(float frametime);
camid cam_create(const char *n_name=NULL, vec3d *n_pos=NULL, matrix *n_ori=NULL, object *n_object=NULL, int n_submodel_parent=-1);
void cam_delete(camid cid);
bool cam_set_camera(camid cid);
void cam_reset_camera();
camid cam_lookup(const char* name);
camid cam_get_camera(uint index);
camid cam_get_current();
size_t cam_get_num();
float cam_get_bbox_dist(const object* viewer_obj, float preferred_distance, const matrix* cam_orient);
void get_turret_cam_pos(camera *cam, vec3d *pos);
void get_turret_cam_orient(camera *cam, matrix *ori);
void subtitles_close();
void subtitles_do_frame(float frametime);
void subtitles_do_frame_post_shaded(float frametime);
#endif // _CAMERA_H