Descent3/physics/findintersection.h
Azamat H. Hackimov b9da6b59ff Isolate physics module
Update physics module, minor cleanups, remove unused code.
2024-07-28 16:50:42 +03:00

446 lines
13 KiB
C

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
--- HISTORICAL COMMENTS FOLLOW ---
* $Logfile: /DescentIII/Main/lib/findintersection.h $
* $Revision: 51 $
* $Date: 6/10/99 6:32p $
* $Author: Chris $
*
* Find intersection header
*
* $Log: /DescentIII/Main/lib/findintersection.h $
*
* 51 6/10/99 6:32p Chris
* New Editor Support
*
* 50 5/18/99 11:10a Matt
* Added variable ceiling height.
*
* 49 4/20/99 8:14p Chris
* Added support for object's that hit the ceiling and for making the
* level always check for the ceiling (inside and outside the mine)
*
* 48 1/15/99 5:59p Chris
*
* 47 1/13/99 2:29a Chris
* Massive AI, OSIRIS update
*
* 46 1/05/99 12:24p Chris
* More OSIRIS improvements
*
* 45 1/01/99 4:10p Chris
* Added some const parameters, improved ray cast object collide/rejection
* code
*
* 44 11/23/98 11:07a Chris
* Added another parameter to fvi_QuickDistObjectList
*
* 43 10/29/98 5:20p Chris
* Player ships collide smaller now
*
* 42 10/22/98 10:25p Kevin
* took out volatile
*
* 41 10/21/98 9:41p Chris
* Improved walking code!
*
* 40 10/17/98 12:25p Chris
* Fixed attached flares
*
* 39 10/16/98 8:33p Chris
* Fixed attached flare problem
*
* 38 10/16/98 3:39p Chris
* Improved the object linking system and AI and physics
*
* 37 10/16/98 1:07p Chris
* Lowered the max hits to 2 for now (we don't even use the info anyhow)
*
* 36 8/03/98 3:59p Chris
* Added support for FQ_IGNORE_WEAPONS, added .000001 attach code, fix a
* bug in polymodel collision detection
*
* 35 7/23/98 12:46p Chris
* Added a flag to ignore external rooms
*
* 34 7/02/98 2:51p Chris
* Added a fast line to bbox function
*
* 33 6/15/98 7:01a Chris
* Cleaned out DII stuff and added new PhysicsSim extern's
*
* 32 6/03/98 6:42p Chris
* Added multipoint collision detection an Assert on invalid (infinite
* endpoint).
*
* 31 5/22/98 4:44p Chris
* Added better melee hit prediction
*
* 30 5/05/98 5:23p Chris
* Faster external room collisions with FQ_EXTERNAL_ROOMS_AS_SPHERE
*
* 29 3/23/98 11:37a Chris
* Added the f_lightmap_only parameter to fvi_QuickDistObjectList
*
* 28 3/23/98 11:18a Chris
* Added int fvi_QuickDistObjectList(vector *pos, int init_room_index,
* float rad, int16_t *object_index_list, int max_elements)
*
*
* 27 3/17/98 11:33a Chris
* Improved performance (AABB updates on poly-sphere collide)
*
* 26 3/16/98 12:50p Chris
* Speed up?
*
* 25 3/16/98 9:43a Chris
* Added FQ_NO_RELINK
*
* 24 2/19/98 6:17p Chris
* Added some debug info
*
* 23 2/11/98 10:04p Chris
* Added FQ_ONLY_DOOR_OBJ and fixed a bug with FQ_ONLY_PLAYER_OBJ
*
* 22 2/04/98 6:09p Matt
* Changed object room number to indicate a terrain cell via a flag. Got
* rid of the object flag which used to indicate terrain.
*
* 21 1/30/98 4:34p Jason
* FROM CHRIS: Changed COL_CELL size to 1
*
* 20 1/20/98 11:35a Chris
* Raised ceiling to MAX_TERRAIN_HEIGHT
*
* 19 1/19/98 5:05p Chris
* Added ceiling collisions for players and powerups
*
* 18 12/16/97 6:11p Chris
* Attempt to improve FVI for outside
*
* 17 10/28/97 5:46p Chris
* Added a quick cell list function
*
* 16 10/28/97 12:20p Chris
* Added support to ignore wall collisions
*
* 15 10/22/97 12:41p Chris
* Incremental BBOX stuff and added support for subobject hit returned
* from fvi
*
* 14 10/07/97 4:03p Chris
* Added support for object backface checking
*
* 13 10/06/97 10:52a Jason
* added "FQ_IGNORE_NON_LIGHTMAP_OBJECTS" flag
*
* 12 9/19/97 6:58p Chris
* Fixed some bugs with the big object system and removed some annoying
* mprintf's
*
* 11 9/19/97 1:01p Chris
* Added better large object support
*
* 10 9/17/97 11:00a Chris
* Removed dependance on segment.h
*
* 9 9/15/97 6:24p Chris
* Added a second chance check if no rooms are initialy found
*
* 8 9/15/97 5:20a Chris
* Added sphere2poly support. Rearranged object collisions.
*
* 7 9/12/97 6:36p Chris
* Added collision terrain segment support
* Added some LARGE OBJECT collision support
*
* 6 9/11/97 3:08p Chris
* Added support for weapons flying through holes in transparent textures.
*
* 5 9/11/97 12:43p Chris
* Added new support for face_physics_info from room.h. Also, changed how
* we detect portals. Also added recorded faces.
*
* 4 9/02/97 11:41a Chris
* Added support the the quick face/room from distance function
*
* 3 8/18/97 1:53a Chris
* Added fvi_Relink
*
* 2 8/04/97 5:35p Chris
* Added support for back face collisions and new fvi code
*
* 10 6/11/97 10:43a Chris
*
* 9 6/10/97 5:34p Chris
*
* 8 5/13/97 5:52p Chris
* Added ability to exit and enter mine. Also did some
* incremental improvements.
*
* 7 5/05/97 5:41a Chris
* Added some better polygon collision code. It is still rough though.
*
* 6 4/17/97 3:10p Chris
* Added edge of world object delete. Also did some incremental
* improvements.
*
* 5 4/15/97 4:15p Chris
*
* 4 3/24/97 12:18p Chris
*
* 3 3/03/97 1:02p Chris
*
* 2 3/03/97 5:52a Chris
* Pre-alpha 0.01 -- just a starting point that compiles
*
* 1 3/03/97 3:26a Chris
*
* $NoKeywords: $
*/
#ifndef FVI_H
#define FVI_H
#include "object.h"
#include "vecmat.h"
#include "terrain.h"
#include "findintersection_external.h"
extern float Ceiling_height;
#define CEILING_HEIGHT (Ceiling_height)
#define PLAYER_SIZE_SCALAR 0.8f
extern bool FVI_always_check_ceiling;
// Big Object Info
#define CELLS_PER_COL_CELL 1
#define COL_TERRAIN_SIZE (TERRAIN_SIZE * (float)CELLS_PER_COL_CELL)
#define MIN_BIG_OBJ_RAD (COL_TERRAIN_SIZE)
// chrishack -- we could turn backface, on and off so that we
// can individually use backface checking on object and/or wall... :)
#define MAX_FVI_SEGS 100
#define MAX_HITS 2
#define Q_RIGHT 0
#define Q_LEFT 1
#define Q_MIDDLE 2
static inline bool FastVectorBBox(const float *min, const float *max, const float *origin, const float *dir) {
bool f_inside = true;
char quad[3];
int i;
float max_t[3];
float can_plane[3];
int which_plane;
float coord[3];
for (i = 0; i < 3; i++) {
if (origin[i] < min[i]) {
quad[i] = Q_LEFT;
can_plane[i] = min[i];
f_inside = false;
} else if (origin[i] > max[i]) {
quad[i] = Q_RIGHT;
can_plane[i] = max[i];
f_inside = false;
} else {
quad[i] = Q_MIDDLE;
}
}
if (f_inside) {
return true;
}
for (i = 0; i < 3; i++) {
if (quad[i] != Q_MIDDLE && dir[i] != 0.0f)
max_t[i] = (can_plane[i] - origin[i]) / dir[i];
else
max_t[i] = -1.0f;
}
which_plane = 0;
for (i = 0; i < 3; i++)
if (max_t[which_plane] < max_t[i])
which_plane = i;
if (max_t[which_plane] < 0.0f)
return false;
for (i = 0; i < 3; i++) {
if (which_plane != i) {
coord[i] = origin[i] + max_t[which_plane] * dir[i];
if ((quad[i] == Q_RIGHT && coord[i] < min[i]) || (quad[i] == Q_LEFT && coord[i] > max[i])) {
return false;
}
} else {
coord[i] = can_plane[i];
}
}
return true;
}
// this data structure gets filled in by find_vector_intersection()
struct fvi_info {
vector hit_pnt; // centerpoint when we hit
int hit_room; // what room hit_pnt is in
float hit_dist; // distance of the hit
int num_hits; // Number of recorded hits
int hit_type[MAX_HITS]; // what sort of intersection
vector hit_face_pnt[MAX_HITS]; // actual collision point (edge of rad)
int hit_face_room[MAX_HITS]; // what room the hit face is in
int hit_face[MAX_HITS]; // if hit wall, which face
vector hit_wallnorm[MAX_HITS]; // if hit wall, ptr to its surface normal
int hit_object[MAX_HITS]; // if object hit, which object
int hit_subobject[MAX_HITS]; // if a POLY_2_SPHERE hit, then it has the poly involved
int n_rooms; // how many segs we went through
int roomlist[MAX_FVI_SEGS]; // list of segs vector went through
// BBox hit results
matrix hit_orient;
vector hit_rotvel;
angle hit_turnroll;
vector hit_velocity;
float hit_time;
vector hit_subobj_fvec;
vector hit_subobj_uvec;
vector hit_subobj_pos;
};
// this data contains the parms to fvi()
struct fvi_query {
vector *p0, *p1;
int startroom;
float rad;
int16_t thisobjnum;
int *ignore_obj_list;
int flags;
// BBox stuff...
matrix *o_orient;
vector *o_rotvel;
vector *o_rotthrust;
vector *o_velocity;
angle *o_turnroll;
vector *o_thrust;
float frametime;
};
// Find out if a vector intersects with anything.
// Fills in hit_data, an fvi_info structure (see above).
// Parms:
// p0 & startseg describe the start of the vector
// p1 the end of the vector
// rad the radius of the cylinder
// thisobjnum used to prevent an object with colliding with itself
// ingore_obj_list NULL, or ptr to a list of objnums to ignore, terminated with -1
// check_obj_flag determines whether collisions with objects are checked
// Returns the hit_data->hit_type
extern int fvi_FindIntersection(fvi_query *fq, fvi_info *hit_data, bool no_subdivision = false);
// Face/Room list for some fvi call(s)
struct fvi_face_room_list {
uint16_t face_index;
uint16_t room_index;
};
#define MAX_RECORDED_FACES 200
// Recorded face list
extern fvi_face_room_list Fvi_recorded_faces[MAX_RECORDED_FACES];
extern int Fvi_num_recorded_faces;
// Generates a list of faces(with corresponding room numbers) within a given distance to a position.
// Return value is the number of faces in the list
extern int fvi_QuickDistFaceList(int init_room_index, vector *pos, float rad, fvi_face_room_list *quick_fr_list,
int max_elements);
// Returns the number of cells that are approximately within the specified radius
extern int fvi_QuickDistCellList(int init_cell_index, vector *pos, float rad, int *quick_cell_list, int max_elements);
// Returns the number of objects that are approximately within the specified radius
int fvi_QuickDistObjectList(vector *pos, int init_roomnum, float rad, int16_t *object_index_list, int max_elements,
bool f_lightmap_only, bool f_only_players_and_ais = false,
bool f_include_non_collide_objects = false, bool f_stop_at_closed_doors = false);
// finds the uv coords of the given point on the given seg & side
// fills in u & v. if l is non-NULL fills it in also
// extern void fvi_FindHitpointUV(float *u,float *v,float *l, vector *pnt,segment *seg,int sidenum,int facenum);
// Returns true if the object is through any walls
extern int fvi_ObjectIntersectsWall(object *objp);
extern int FVI_counter;
extern int FVI_room_counter;
bool fvi_QuickRoomCheck(vector *pos, room *cur_room, bool try_again = false);
extern fvi_info *fvi_hit_data_ptr;
extern fvi_query *fvi_query_ptr;
extern float fvi_collision_dist;
extern int fvi_curobj;
extern int fvi_moveobj;
bool PolyCollideObject(object *obj);
bool BBoxPlaneIntersection(bool fast_exit, vector *collision_point, vector *collision_normal, object *obj,
vector *new_pos, int nv, vector **vertex_ptr_list, vector *face_normal, matrix *orient);
extern uint32_t check_point_to_face(vector *colp, vector *face_normal, int nv, vector **vertex_ptr_list);
extern int check_vector_to_sphere_1(vector *intp, float *col_dist, const vector *p0, const vector *p1,
vector *sphere_pos, float sphere_rad, bool f_correcting, bool f_init_collisions);
extern int check_line_to_face(vector *newp, vector *colp, float *col_dist, vector *wall_norm, const vector *p0,
const vector *p1, vector *face_normal, vector **vertex_ptr_list, const int nv,
const float rad);
extern void InitFVI();
// Types of supported collisions
#ifdef NED_PHYSICS
#define RESULT_NOTHING 0
#define RESULT_CHECK_SPHERE_SPHERE 1
#define RESULT_CHECK_SPHERE_POLY 2
#define RESULT_CHECK_POLY_SPHERE 3
#define RESULT_CHECK_BBOX_POLY 4
#define RESULT_CHECK_POLY_BBOX 5
#define RESULT_CHECK_BBOX_BBOX 6
#define RESULT_CHECK_BBOX_SPHERE 7
#define RESULT_CHECK_SPHERE_BBOX 8
#define RESULT_CHECK_SPHERE_ROOM 9
#define RESULT_CHECK_BBOX_ROOM 10
#endif
#endif