dxx-rebirth/common/main/gameseg.h
2022-02-19 14:52:17 +00:00

227 lines
9.6 KiB
C++

/*
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING.txt.
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below.
* See COPYING.txt for license details.
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
*/
/*
*
* Header file for stuff moved from segment.c to gameseg.c.
*
*/
#pragma once
#include <random>
#include "pstypes.h"
#include "maths.h"
#include "vecmat.h"
#include "segment.h"
#include <utility>
#include "dxxsconf.h"
#include "dsx-ns.h"
#include <array>
namespace dcx {
struct segmasks
{
short facemask; //which faces sphere pokes through (12 bits)
sidemask_t sidemask; //which sides sphere pokes through (6 bits)
sidemask_t centermask; //which sides center point is on back of (6 bits)
};
struct segment_depth_array_t : public std::array<ubyte, MAX_SEGMENTS> {};
struct side_vertnum_list_t : std::array<vertnum_t, 4> {};
struct vertnum_array_list_t : std::array<vertnum_t, 6> {};
struct vertex_array_list_t : std::array<segment_relative_vertnum, 6> {};
struct vertex_vertnum_pair
{
vertnum_t vertex;
side_relative_vertnum vertnum;
};
using vertex_vertnum_array_list = std::array<vertex_vertnum_pair, 6>;
#ifdef dsx
[[nodiscard]]
sidenum_t find_connect_side(vcsegidx_t base_seg, const shared_segment &con_seg);
void compute_center_point_on_side(fvcvertptr &vcvertptr, vms_vector &vp, const shared_segment &sp, sidenum_t side);
static inline vms_vector compute_center_point_on_side(fvcvertptr &vcvertptr, const shared_segment &sp, const sidenum_t side)
{
vms_vector v;
return compute_center_point_on_side(vcvertptr, v, sp, side), v;
}
void compute_segment_center(fvcvertptr &vcvertptr, vms_vector &vp, const shared_segment &sp);
static inline vms_vector compute_segment_center(fvcvertptr &vcvertptr, const shared_segment &sp)
{
vms_vector v;
compute_segment_center(vcvertptr, v, sp);
return v;
}
// Fill in array with four absolute point numbers for a given side
void get_side_verts(side_vertnum_list_t &vertlist, const shared_segment &seg, sidenum_t sidenum);
static inline side_vertnum_list_t get_side_verts(const shared_segment &segnum, const sidenum_t sidenum)
{
side_vertnum_list_t r;
return get_side_verts(r, segnum, sidenum), r;
}
#endif
}
#ifdef dsx
namespace dsx {
#if defined(DXX_BUILD_DESCENT_II) || DXX_USE_EDITOR
extern int Doing_lighting_hack_flag;
#endif
#if DXX_USE_EDITOR
// Create all vertex lists (1 or 2) for faces on a side.
// Sets:
// num_faces number of lists
// vertices vertices in all (1 or 2) faces
// If there is one face, it has 4 vertices.
// If there are two faces, they both have three vertices, so face #0 is stored in vertices 0,1,2,
// face #1 is stored in vertices 3,4,5.
// Note: these are not absolute vertex numbers, but are relative to the segment
// Note: for triagulated sides, the middle vertex of each trianle is the one NOT
// adjacent on the diagonal edge
uint_fast32_t create_all_vertex_lists(vertex_array_list_t &vertices, const shared_segment &seg, const shared_side &sidep, sidenum_t sidenum);
[[nodiscard]]
static inline std::pair<uint_fast32_t, vertex_array_list_t> create_all_vertex_lists(const shared_segment &segnum, const shared_side &sidep, const sidenum_t sidenum)
{
vertex_array_list_t r;
const auto &&n = create_all_vertex_lists(r, segnum, sidep, sidenum);
return {n, r};
}
#endif
//like create_all_vertex_lists(), but generate absolute point numbers
uint_fast32_t create_abs_vertex_lists(vertnum_array_list_t &vertices, const shared_segment &segnum, const shared_side &sidep, sidenum_t sidenum);
[[nodiscard]]
static inline std::pair<uint_fast32_t, vertnum_array_list_t> create_abs_vertex_lists(const shared_segment &segnum, const shared_side &sidep, const sidenum_t sidenum)
{
vertnum_array_list_t r;
const auto &&n = create_abs_vertex_lists(r, segnum, sidep, sidenum);
return {n, r};
}
[[nodiscard]]
static inline std::pair<uint_fast32_t, vertnum_array_list_t> create_abs_vertex_lists(const shared_segment &segp, const sidenum_t sidenum)
{
return create_abs_vertex_lists(segp, segp.sides[sidenum], sidenum);
}
// -----------------------------------------------------------------------------------
// Like create all vertex lists, but returns the vertnums (relative to
// the side) for each of the faces that make up the side.
// If there is one face, it has 4 vertices.
// If there are two faces, they both have three vertices, so face #0 is stored in vertices 0,1,2,
// face #1 is stored in vertices 3,4,5.
void create_all_vertnum_lists(vertex_vertnum_array_list &vertnums, const shared_segment &seg, const shared_side &sidep, sidenum_t sidenum);
[[nodiscard]]
static inline vertex_vertnum_array_list create_all_vertnum_lists(const shared_segment &segnum, const shared_side &sidep, const sidenum_t sidenum)
{
vertex_vertnum_array_list r;
return create_all_vertnum_lists(r, segnum, sidep, sidenum), r;
}
}
namespace dcx {
// Given a side, return the number of faces
bool get_side_is_quad(const shared_side &sidep);
struct WALL_IS_DOORWAY_mask_t;
}
namespace dsx {
//returns 3 different bitmasks with info telling if this sphere is in
//this segment. See segmasks structure for info on fields
segmasks get_seg_masks(fvcvertptr &, const vms_vector &checkp, const shared_segment &segnum, fix rad);
//this macro returns true if the segnum for an object is correct
#define check_obj_seg(vcvertptr, obj) (get_seg_masks(vcvertptr, (obj)->pos, vcsegptr((obj)->segnum), 0).centermask == 0)
//Tries to find a segment for a point, in the following way:
// 1. Check the given segment
// 2. Recursively trace through attached segments
// 3. Check all the segmentns
//Returns segnum if found, or -1
imsegptridx_t find_point_seg(const d_level_shared_segment_state &, d_level_unique_segment_state &, const vms_vector &p, imsegptridx_t segnum);
icsegptridx_t find_point_seg(const d_level_shared_segment_state &, const vms_vector &p, icsegptridx_t segnum);
// ----------------------------------------------------------------------------------------------------------
// Determine whether seg0 and seg1 are reachable using wid_flag to go through walls.
// For example, set to WID_RENDPAST_FLAG to see if sound can get from one segment to the other.
// set to WID_FLY_FLAG to see if a robot could fly from one to the other.
// Search up to a maximum depth of max_depth.
// Return the distance.
vm_distance find_connected_distance(const vms_vector &p0, vcsegptridx_t seg0, const vms_vector &p1, vcsegptridx_t seg1, int max_depth, WALL_IS_DOORWAY_mask_t wid_flag);
//create a matrix that describes the orientation of the given segment
void extract_orient_from_segment(fvcvertptr &vcvertptr, vms_matrix &m, const shared_segment &seg);
void validate_segment_all(d_level_shared_segment_state &);
#if DXX_USE_EDITOR
// In segment.c
// Make a just-modified segment valid.
// check all sides to see how many faces they each should have (0,1,2)
// create new vector normals
void validate_segment(fvcvertptr &vcvertptr, vmsegptridx_t sp);
// Extract the forward vector from segment *sp, return in *vp.
// The forward vector is defined to be the vector from the the center of the front face of the segment
// to the center of the back face of the segment.
void extract_forward_vector_from_segment(fvcvertptr &, const shared_segment &sp, vms_vector &vp);
// Extract the right vector from segment *sp, return in *vp.
// The forward vector is defined to be the vector from the the center of the left face of the segment
// to the center of the right face of the segment.
void extract_right_vector_from_segment(fvcvertptr &, const shared_segment &sp, vms_vector &vp);
// Extract the up vector from segment *sp, return in *vp.
// The forward vector is defined to be the vector from the the center of the bottom face of the segment
// to the center of the top face of the segment.
void extract_up_vector_from_segment(fvcvertptr &, const shared_segment &sp, vms_vector &vp);
void create_walls_on_side(fvcvertptr &, shared_segment &sp, sidenum_t sidenum);
void validate_segment_side(fvcvertptr &, vmsegptridx_t sp, sidenum_t sidenum);
#endif
void pick_random_point_in_seg(fvcvertptr &vcvertptr, vms_vector &new_pos, const shared_segment &sp, std::minstd_rand);
static inline vms_vector pick_random_point_in_seg(fvcvertptr &vcvertptr, const shared_segment &sp, std::minstd_rand r)
{
vms_vector v;
return pick_random_point_in_seg(vcvertptr, v, sp, r), v;
}
int check_segment_connections(void);
unsigned set_segment_depths(vcsegidx_t start_seg, const std::array<uint8_t, MAX_SEGMENTS> *limit, segment_depth_array_t &depths);
#if defined(DXX_BUILD_DESCENT_I)
static inline void flush_fcd_cache() {}
#elif defined(DXX_BUILD_DESCENT_II)
void flush_fcd_cache();
void apply_all_changed_light(const d_level_shared_destructible_light_state &LevelSharedDestructibleLightState, fvmsegptridx &vmsegptridx);
void set_ambient_sound_flags(void);
#endif
}
#endif