Use enumerated_array for unique_side::uvls
This commit is contained in:
parent
075495aa8b
commit
636e1b6d5e
|
@ -18,8 +18,8 @@ extern imsegptridx_t Cursegp; // Pointer to current segment in the mine, the
|
|||
#define New_segment (Segments.back())
|
||||
|
||||
extern sidenum_t Curside; // Side index in 0..MAX_SIDES_PER_SEGMENT of active side.
|
||||
extern int Curedge; // Current edge on current side, in 0..3
|
||||
extern int Curvert; // Current vertex on current side, in 0..3
|
||||
extern side_relative_vertnum Curedge; // Current edge on current side, in 0..3
|
||||
extern side_relative_vertnum Curvert; // Current vertex on current side, in 0..3
|
||||
extern sidenum_t AttachSide; // Side on segment to attach
|
||||
extern int Draw_all_segments; // Set to 1 means draw_world draws all segments in Segments, else draw only connected segments
|
||||
extern imsegptridx_t Markedsegp; // Marked segment, used in conjunction with *Cursegp to form joints.
|
||||
|
|
|
@ -46,7 +46,6 @@ DXX_VALPTRIDX_DECLARE_SUBTYPE(dcx::, segment, segnum_t, MAX_SEGMENTS);
|
|||
|
||||
namespace dcx {
|
||||
constexpr std::integral_constant<std::size_t, 8> MAX_VERTICES_PER_SEGMENT{};
|
||||
constexpr std::integral_constant<std::size_t, 4> MAX_VERTICES_PER_POLY{};
|
||||
|
||||
constexpr std::size_t MAX_SEGMENTS_ORIGINAL = 900;
|
||||
constexpr std::integral_constant<std::size_t, 4 * MAX_SEGMENTS_ORIGINAL> MAX_SEGMENT_VERTICES_ORIGINAL{};
|
||||
|
@ -113,8 +112,10 @@ struct unique_side;
|
|||
|
||||
struct vertex;
|
||||
enum class vertnum_t : uint32_t;
|
||||
enum class side_relative_vertnum : uint8_t;
|
||||
enum class segment_relative_vertnum : uint8_t;
|
||||
enum class segment_special : uint8_t;
|
||||
constexpr constant_xrange<side_relative_vertnum, side_relative_vertnum{0}, side_relative_vertnum{4}> MAX_VERTICES_PER_SIDE{};
|
||||
}
|
||||
|
||||
/* `vertex` has only integer members, so wild reads are unlikely to
|
||||
|
@ -147,7 +148,7 @@ struct d_level_shared_vertex_state;
|
|||
struct d_level_shared_segment_state;
|
||||
struct d_level_unique_segment_state;
|
||||
|
||||
extern const enumerated_array<std::array<segment_relative_vertnum, 4>, MAX_SIDES_PER_SEGMENT, sidenum_t> Side_to_verts; // Side_to_verts[my_side] is list of vertices forming side my_side.
|
||||
extern const enumerated_array<enumerated_array<segment_relative_vertnum, 4, side_relative_vertnum>, MAX_SIDES_PER_SEGMENT, sidenum_t> Side_to_verts; // Side_to_verts[my_side] is list of vertices forming side my_side.
|
||||
extern const enumerated_array<sidenum_t, MAX_SIDES_PER_SEGMENT, sidenum_t> Side_opposite; // Side_opposite[my_side] returns side opposite cube from my_side.
|
||||
|
||||
void segment_side_wall_tmap_write(PHYSFS_File *fp, const shared_side &sside, const unique_side &uside);
|
||||
|
|
|
@ -53,7 +53,7 @@ struct vertex_array_list_t : std::array<segment_relative_vertnum, 6> {};
|
|||
struct vertex_vertnum_pair
|
||||
{
|
||||
vertnum_t vertex;
|
||||
unsigned vertnum;
|
||||
side_relative_vertnum vertnum;
|
||||
};
|
||||
using vertex_vertnum_array_list = std::array<vertex_vertnum_pair, 6>;
|
||||
|
||||
|
|
|
@ -62,6 +62,11 @@ static constexpr sidenum_t &operator++(sidenum_t &a)
|
|||
return a = static_cast<sidenum_t>(static_cast<unsigned>(a) + 1);
|
||||
}
|
||||
|
||||
static constexpr side_relative_vertnum &operator++(side_relative_vertnum &a)
|
||||
{
|
||||
return a = static_cast<side_relative_vertnum>(static_cast<uint8_t>(a) + 1);
|
||||
}
|
||||
|
||||
//Structure for storing u,v,light values.
|
||||
//NOTE: this structure should be the same as the one in 3d.h
|
||||
struct uvl
|
||||
|
@ -76,6 +81,14 @@ enum class side_type : uint8_t
|
|||
tri_13 = 3, // render side as two triangles, triangulated along edge from 1 to 3
|
||||
};
|
||||
|
||||
enum class side_relative_vertnum : uint8_t
|
||||
{
|
||||
_0,
|
||||
_1,
|
||||
_2,
|
||||
_3,
|
||||
};
|
||||
|
||||
enum class segment_relative_vertnum : uint8_t
|
||||
{
|
||||
_0,
|
||||
|
@ -199,11 +212,17 @@ static constexpr texture2_value build_texture2_value(const texture_index t, cons
|
|||
#undef TEXTURE2_ROTATION_SHIFT
|
||||
#undef TEXTURE2_ROTATION_INDEX_MASK
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr side_relative_vertnum next_side_vertex(const side_relative_vertnum a, unsigned add = 1)
|
||||
{
|
||||
return static_cast<side_relative_vertnum>((static_cast<uint8_t>(a) + add) & 3);
|
||||
}
|
||||
|
||||
struct unique_side
|
||||
{
|
||||
texture1_value tmap_num;
|
||||
texture2_value tmap_num2;
|
||||
std::array<uvl, 4> uvls;
|
||||
enumerated_array<uvl, 4, side_relative_vertnum> uvls;
|
||||
};
|
||||
|
||||
#ifdef dsx
|
||||
|
@ -340,7 +359,7 @@ struct delta_light : prohibit_void_ptr<delta_light>
|
|||
{
|
||||
segnum_t segnum;
|
||||
sidenum_t sidenum;
|
||||
std::array<ubyte, 4> vert_light;
|
||||
enumerated_array<uint8_t, 4, side_relative_vertnum> vert_light;
|
||||
};
|
||||
|
||||
// Light at segnum:sidenum casts light on count sides beginning at index (in array Delta_lights)
|
||||
|
|
|
@ -35,8 +35,8 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
imsegptridx_t Cursegp = segment_none; // Pointer to current segment in mine.
|
||||
imsegptridx_t Markedsegp = segment_none; // Marked segment, used in conjunction with *Cursegp to form joints.
|
||||
sidenum_t Curside; // Side index in 0..MAX_SIDES_PER_SEGMENT of active side.
|
||||
int Curedge; // Current edge on current side, in 0..3
|
||||
int Curvert; // Current vertex on current side, in 0..3
|
||||
side_relative_vertnum Curedge; // Current edge on current side, in 0..3
|
||||
side_relative_vertnum Curvert; // Current vertex on current side, in 0..3
|
||||
sidenum_t AttachSide = WFRONT; // Side on segment to attach.
|
||||
sidenum_t Markedside; // Marked side on Markedsegp.
|
||||
|
||||
|
|
|
@ -42,15 +42,13 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Return light intensity at an instance of a vertex on a side in a segment.
|
||||
static fix get_light_intensity(const unique_side &s, const uint_fast32_t vert)
|
||||
static fix get_light_intensity(const unique_side &s, const side_relative_vertnum vert)
|
||||
{
|
||||
Assert(vert <= 3);
|
||||
return s.uvls[vert].l;
|
||||
}
|
||||
|
||||
static fix get_light_intensity(const unique_segment &segp, const sidenum_t sidenum, const uint_fast32_t vert)
|
||||
static fix get_light_intensity(const unique_segment &segp, const sidenum_t sidenum, const side_relative_vertnum vert)
|
||||
{
|
||||
Assert(sidenum <= MAX_SIDES_PER_SEGMENT);
|
||||
return get_light_intensity(segp.sides[sidenum], vert);
|
||||
}
|
||||
|
||||
|
@ -65,14 +63,13 @@ static fix clamp_light_intensity(const fix intensity)
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Set light intensity at a vertex, saturating in .5 to 15.5
|
||||
static void set_light_intensity(unique_side &s, const uint_fast32_t vert, const fix intensity)
|
||||
static void set_light_intensity(unique_side &s, const side_relative_vertnum vert, const fix intensity)
|
||||
{
|
||||
Assert(vert <= 3);
|
||||
s.uvls[vert].l = clamp_light_intensity(intensity);
|
||||
Update_flags |= UF_WORLD_CHANGED;
|
||||
}
|
||||
|
||||
static void set_light_intensity(unique_segment &segp, const sidenum_t sidenum, const uint_fast32_t vert, const fix intensity)
|
||||
static void set_light_intensity(unique_segment &segp, const sidenum_t sidenum, const side_relative_vertnum vert, const fix intensity)
|
||||
{
|
||||
set_light_intensity(segp.sides[sidenum], vert, intensity);
|
||||
}
|
||||
|
@ -173,24 +170,16 @@ int LightAmbientLighting()
|
|||
// -----------------------------------------------------------------------------
|
||||
int LightSelectNextVertex(void)
|
||||
{
|
||||
Curvert++;
|
||||
if (Curvert >= 4)
|
||||
Curvert = 0;
|
||||
|
||||
Curvert = next_side_vertex(Curvert);
|
||||
Update_flags |= UF_WORLD_CHANGED;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
int LightSelectNextEdge(void)
|
||||
{
|
||||
Curedge++;
|
||||
if (Curedge >= 4)
|
||||
Curedge = 0;
|
||||
|
||||
Curedge = next_side_vertex(Curedge);
|
||||
Update_flags |= UF_WORLD_CHANGED;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -203,7 +192,7 @@ int LightCopyIntensity(void)
|
|||
unique_segment &segp = Cursegp;
|
||||
intensity = get_light_intensity(segp, Curside, Curvert);
|
||||
|
||||
range_for (const int v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
if (v != Curvert)
|
||||
set_light_intensity(segp, Curside, v, intensity);
|
||||
|
||||
|
@ -220,7 +209,7 @@ int LightCopyIntensitySegment(void)
|
|||
intensity = get_light_intensity(segp, Curside, Curvert);
|
||||
|
||||
for (const auto s : MAX_SIDES_PER_SEGMENT)
|
||||
range_for (const int v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
if ((s != Curside) || (v != Curvert))
|
||||
set_light_intensity(segp, s, v, intensity);
|
||||
|
||||
|
@ -249,7 +238,7 @@ int LightIncreaseLightVertex(void)
|
|||
int LightDecreaseLightSide(void)
|
||||
{
|
||||
unique_segment &segp = Cursegp;
|
||||
range_for (const int v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
set_light_intensity(segp, Curside, v, get_light_intensity(segp, Curside, v) - F1_0 / NUM_LIGHTING_LEVELS);
|
||||
|
||||
return 1;
|
||||
|
@ -259,7 +248,7 @@ int LightDecreaseLightSide(void)
|
|||
int LightIncreaseLightSide(void)
|
||||
{
|
||||
unique_segment &segp = Cursegp;
|
||||
range_for (const int v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
set_light_intensity(segp, Curside, v, get_light_intensity(segp, Curside, v) + F1_0 / NUM_LIGHTING_LEVELS);
|
||||
|
||||
return 1;
|
||||
|
@ -270,7 +259,7 @@ int LightDecreaseLightSegment(void)
|
|||
{
|
||||
unique_segment &segp = Cursegp;
|
||||
for (const auto s : MAX_SIDES_PER_SEGMENT)
|
||||
range_for (const int v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
set_light_intensity(segp, s, v, get_light_intensity(segp, s, v) - F1_0 / NUM_LIGHTING_LEVELS);
|
||||
|
||||
return 1;
|
||||
|
@ -281,7 +270,7 @@ int LightIncreaseLightSegment(void)
|
|||
{
|
||||
unique_segment &segp = Cursegp;
|
||||
for (const auto s : MAX_SIDES_PER_SEGMENT)
|
||||
range_for (const int v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
set_light_intensity(segp, s, v, get_light_intensity(segp, s, v) + F1_0 / NUM_LIGHTING_LEVELS);
|
||||
|
||||
return 1;
|
||||
|
@ -291,7 +280,7 @@ int LightIncreaseLightSegment(void)
|
|||
int LightSetDefault(void)
|
||||
{
|
||||
unique_segment &segp = Cursegp;
|
||||
range_for (const int v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
set_light_intensity(segp, Curside, v, DEFAULT_LIGHTING);
|
||||
|
||||
return 1;
|
||||
|
@ -302,7 +291,7 @@ int LightSetDefault(void)
|
|||
int LightSetMaximum(void)
|
||||
{
|
||||
unique_segment &segp = Cursegp;
|
||||
range_for (const int v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
set_light_intensity(segp, Curside, v, (NUM_LIGHTING_LEVELS - 1) * F1_0 / NUM_LIGHTING_LEVELS);
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -119,7 +119,7 @@ static void scale_vert(const shared_segment &sp, const vertnum_t vertex_ind, con
|
|||
auto &sv = Side_to_verts[Curside];
|
||||
const auto edge = Curedge;
|
||||
range_for (const int v, xrange(2u))
|
||||
if (verts[sv[(edge + v) % 4]] == vertex_ind)
|
||||
if (verts[sv[next_side_vertex(edge, v)]] == vertex_ind)
|
||||
scale_vert_aux(vertex_ind, vp, scale_factor);
|
||||
break;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ static void med_scale_segment_new(const shared_segment &sp, const int dimension,
|
|||
// ------------------------------------------------------------------------------------------
|
||||
// Extract a vector from a segment. The vector goes from the start face to the end face.
|
||||
// The point on each face is the average of the four points forming the face.
|
||||
static void extract_vector_from_segment_side(const shared_segment &sp, const sidenum_t side, vms_vector &vp, const unsigned vla, const unsigned vlb, const unsigned vra, const unsigned vrb)
|
||||
static void extract_vector_from_segment_side(const shared_segment &sp, const sidenum_t side, vms_vector &vp, const side_relative_vertnum vla, const side_relative_vertnum vlb, const side_relative_vertnum vra, const side_relative_vertnum vrb)
|
||||
{
|
||||
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
||||
auto &Vertices = LevelSharedVertexState.get_vertices();
|
||||
|
@ -207,7 +207,7 @@ static void extract_vector_from_segment_side(const shared_segment &sp, const sid
|
|||
// to the center of the right face of the segment.
|
||||
void med_extract_right_vector_from_segment_side(const shared_segment &sp, const sidenum_t sidenum, vms_vector &vp)
|
||||
{
|
||||
extract_vector_from_segment_side(sp, sidenum, vp, 3, 2, 0, 1);
|
||||
extract_vector_from_segment_side(sp, sidenum, vp, side_relative_vertnum::_3, side_relative_vertnum::_2, side_relative_vertnum::_0, side_relative_vertnum::_1);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
@ -216,7 +216,7 @@ void med_extract_right_vector_from_segment_side(const shared_segment &sp, const
|
|||
// to the center of the top face of the segment.
|
||||
void med_extract_up_vector_from_segment_side(const shared_segment &sp, const sidenum_t sidenum, vms_vector &vp)
|
||||
{
|
||||
extract_vector_from_segment_side(sp, sidenum, vp, 1, 2, 0, 3);
|
||||
extract_vector_from_segment_side(sp, sidenum, vp, side_relative_vertnum::_1, side_relative_vertnum::_2, side_relative_vertnum::_0, side_relative_vertnum::_3);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -95,6 +95,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
|
||||
#include "compiler-range_for.h"
|
||||
#include "d_levelstate.h"
|
||||
#include "d_zip.h"
|
||||
|
||||
//#define _MARK_ON 1
|
||||
//#include <wsample.h> //should come after inferno.h to get mark setting //Not included here.
|
||||
|
@ -536,7 +537,7 @@ static void move_player_2_segment_and_rotate(const vmsegptridx_t seg, const unsi
|
|||
auto &Objects = LevelUniqueObjectState.Objects;
|
||||
auto &vmobjptr = Objects.vmptr;
|
||||
auto &vmobjptridx = Objects.vmptridx;
|
||||
static int edgenum=0;
|
||||
static side_relative_vertnum edgenum;
|
||||
|
||||
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
||||
auto &Vertices = LevelSharedVertexState.get_vertices();
|
||||
|
@ -547,8 +548,8 @@ static void move_player_2_segment_and_rotate(const vmsegptridx_t seg, const unsi
|
|||
|
||||
auto &sv = Side_to_verts[Curside];
|
||||
auto &verts = Cursegp->verts;
|
||||
const auto upvec = vm_vec_sub(vcvertptr(verts[sv[edgenum % 4]]), vcvertptr(verts[sv[(edgenum + 3) % 4]]));
|
||||
edgenum++;
|
||||
const auto en = std::exchange(edgenum, next_side_vertex(edgenum));
|
||||
const auto upvec = vm_vec_sub(vcvertptr(verts[sv[en]]), vcvertptr(verts[sv[next_side_vertex(en, 3)]]));
|
||||
|
||||
vm_vector_2_matrix(ConsoleObject->orient,vp,&upvec,nullptr);
|
||||
// vm_vector_2_matrix(&ConsoleObject->orient,&vp,NULL,NULL);
|
||||
|
@ -563,7 +564,6 @@ int SetPlayerFromCursegAndRotate()
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//sets the player facing curseg/curside, normal to face0 of curside, and
|
||||
//far enough away to see all of curside
|
||||
int SetPlayerFromCursegMinusOne()
|
||||
|
@ -573,7 +573,7 @@ int SetPlayerFromCursegMinusOne()
|
|||
auto &vmobjptridx = Objects.vmptridx;
|
||||
std::array<g3s_point, 4> corner_p;
|
||||
fix max,view_dist=f1_0*10;
|
||||
static int edgenum=0;
|
||||
static side_relative_vertnum edgenum;
|
||||
const auto view_vec = vm_vec_negated(Cursegp->shared_segment::sides[Curside].normals[0]);
|
||||
|
||||
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
||||
|
@ -585,8 +585,8 @@ int SetPlayerFromCursegMinusOne()
|
|||
|
||||
auto &sv = Side_to_verts[Curside];
|
||||
auto &verts = Cursegp->verts;
|
||||
const auto upvec = vm_vec_sub(vcvertptr(verts[sv[edgenum % 4]]), vcvertptr(verts[sv[(edgenum + 3) % 4]]));
|
||||
edgenum++;
|
||||
const auto en = std::exchange(edgenum, next_side_vertex(edgenum));
|
||||
const auto upvec = vm_vec_sub(vcvertptr(verts[sv[en]]), vcvertptr(verts[sv[next_side_vertex(en, 3)]]));
|
||||
|
||||
vm_vector_2_matrix(ConsoleObject->orient,view_vec,&upvec,nullptr);
|
||||
|
||||
|
@ -594,11 +594,12 @@ int SetPlayerFromCursegMinusOne()
|
|||
g3_start_frame(*grd_curcanv);
|
||||
g3_set_view_matrix(ConsoleObject->pos,ConsoleObject->orient,Render_zoom);
|
||||
|
||||
for (unsigned i = max = 0; i < 4; ++i)
|
||||
max = 0;
|
||||
for (auto &&[corner, vert] : zip(corner_p, sv))
|
||||
{
|
||||
g3_rotate_point(corner_p[i], vcvertptr(verts[sv[i]]));
|
||||
if (labs(corner_p[i].p3_x) > max) max = labs(corner_p[i].p3_x);
|
||||
if (labs(corner_p[i].p3_y) > max) max = labs(corner_p[i].p3_y);
|
||||
g3_rotate_point(corner, vcvertptr(verts[vert]));
|
||||
if (labs(corner.p3_x) > max) max = labs(corner.p3_x);
|
||||
if (labs(corner.p3_y) > max) max = labs(corner.p3_y);
|
||||
}
|
||||
|
||||
view_dist = fixmul(view_dist,fixdiv(fixdiv(max,SIDE_VIEW_FRAC),corner_p[0].p3_z));
|
||||
|
|
|
@ -166,13 +166,13 @@ static void check_segment(const vmsegptridx_t seg)
|
|||
range_for (auto &fn, Side_to_verts)
|
||||
{
|
||||
std::array<cg3s_point *, 3> vert_list;
|
||||
vert_list[0] = &Segment_points[seg->verts[fn[0]]];
|
||||
vert_list[1] = &Segment_points[seg->verts[fn[1]]];
|
||||
vert_list[2] = &Segment_points[seg->verts[fn[2]]];
|
||||
vert_list[0] = &Segment_points[seg->verts[fn[side_relative_vertnum::_0]]];
|
||||
vert_list[1] = &Segment_points[seg->verts[fn[side_relative_vertnum::_1]]];
|
||||
vert_list[2] = &Segment_points[seg->verts[fn[side_relative_vertnum::_2]]];
|
||||
g3_check_and_draw_poly(*grd_curcanv, vert_list, color);
|
||||
|
||||
vert_list[1] = &Segment_points[seg->verts[fn[2]]];
|
||||
vert_list[2] = &Segment_points[seg->verts[fn[3]]];
|
||||
vert_list[1] = &Segment_points[seg->verts[fn[side_relative_vertnum::_2]]];
|
||||
vert_list[2] = &Segment_points[seg->verts[fn[side_relative_vertnum::_3]]];
|
||||
g3_check_and_draw_poly(*grd_curcanv, vert_list, color);
|
||||
}
|
||||
}
|
||||
|
@ -193,17 +193,13 @@ static void draw_seg_side(const shared_segment &seg, const sidenum_t side, const
|
|||
auto &vcvertptr = Vertices.vcptr;
|
||||
if (!rotate_list(vcvertptr, svp).uand)
|
||||
{ //all off screen?
|
||||
int i;
|
||||
|
||||
auto &stv = Side_to_verts[side];
|
||||
for (i=0;i<3;i++)
|
||||
draw_line(*grd_curcanv, svp[stv[i]], svp[stv[i+1]], color);
|
||||
|
||||
draw_line(*grd_curcanv, svp[stv[i]], svp[stv[0]], color);
|
||||
for (const auto i : MAX_VERTICES_PER_SIDE)
|
||||
draw_line(*grd_curcanv, svp[stv[i]], svp[stv[next_side_vertex(i)]], color);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_side_edge(const shared_segment &seg, const sidenum_t side, const unsigned edge, const color_palette_index color)
|
||||
static void draw_side_edge(const shared_segment &seg, const sidenum_t side, const side_relative_vertnum edge, const color_palette_index color)
|
||||
{
|
||||
auto &svp = seg.verts;
|
||||
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
||||
|
@ -212,7 +208,7 @@ static void draw_side_edge(const shared_segment &seg, const sidenum_t side, cons
|
|||
if (!rotate_list(vcvertptr, svp).uand) //on screen?
|
||||
{
|
||||
auto &stv = Side_to_verts[side];
|
||||
draw_line(*grd_curcanv, svp[stv[edge]], svp[stv[(edge + 1) % 4]], color);
|
||||
draw_line(*grd_curcanv, svp[stv[edge]], svp[stv[next_side_vertex(edge)]], color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,7 +405,7 @@ static void draw_trigger_side(const shared_segment &seg, const sidenum_t side, c
|
|||
{ //all off screen?
|
||||
// Draw diagonals
|
||||
auto &stv = Side_to_verts[side];
|
||||
draw_line(*grd_curcanv, svp[stv[0]], svp[stv[2]], color);
|
||||
draw_line(*grd_curcanv, svp[stv[side_relative_vertnum::_0]], svp[stv[side_relative_vertnum::_2]], color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,8 +420,8 @@ static void draw_wall_side(const shared_segment &seg, const sidenum_t side, cons
|
|||
{ //all off screen?
|
||||
// Draw diagonals
|
||||
auto &stv = Side_to_verts[side];
|
||||
draw_line(*grd_curcanv, svp[stv[0]], svp[stv[2]], color);
|
||||
draw_line(*grd_curcanv, svp[stv[1]], svp[stv[3]], color);
|
||||
draw_line(*grd_curcanv, svp[stv[side_relative_vertnum::_0]], svp[stv[side_relative_vertnum::_2]], color);
|
||||
draw_line(*grd_curcanv, svp[stv[side_relative_vertnum::_1]], svp[stv[side_relative_vertnum::_3]], color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1058,9 +1058,9 @@ static fix seg_seg_vertex_distsum(const shared_segment &seg1, const sidenum_t si
|
|||
|
||||
distsum = 0;
|
||||
auto &vcvertptr = Vertices.vcptr;
|
||||
range_for (const unsigned secondv, xrange(4u))
|
||||
for (const auto secondv : MAX_VERTICES_PER_SIDE)
|
||||
{
|
||||
const unsigned firstv = (4 - secondv + (3 - firstv1)) % 4;
|
||||
const auto firstv = static_cast<side_relative_vertnum>((4 - underlying_value(secondv) + (3 - firstv1)) % 4);
|
||||
distsum += vm_vec_dist(vcvertptr(seg1.verts[Side_to_verts[side1][firstv]]),vcvertptr(seg2.verts[Side_to_verts[side2][secondv]]));
|
||||
}
|
||||
|
||||
|
@ -1142,8 +1142,8 @@ int med_form_joint(const vmsegptridx_t seg1, const sidenum_t side1, const vmsegp
|
|||
lv = seg2->verts[vi];
|
||||
|
||||
// Now, for each vertex in lost_vertices, determine which vertex it maps to.
|
||||
for (const unsigned v : xrange(4u))
|
||||
remap_vertices[3 - ((v + bfi) % 4)] = seg1->verts[vp1[v]];
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
remap_vertices[3 - ((underlying_value(v) + bfi) % 4)] = seg1->verts[vp1[v]];
|
||||
|
||||
// Now, in all segments, replace all occurrences of vertices in lost_vertices with remap_vertices
|
||||
|
||||
|
@ -1213,8 +1213,8 @@ int med_form_bridge_segment(const vmsegptridx_t seg1, const sidenum_t side1, con
|
|||
// Copy vertices from seg2 into last 4 vertices of bridge segment.
|
||||
{
|
||||
auto &sv = Side_to_verts[side2];
|
||||
for (const auto v : xrange(4u))
|
||||
sbs.verts[(segment_relative_vertnum{static_cast<uint8_t>((3 - v) + 4)})] = seg2->verts[sv[v]];
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
sbs.verts[(segment_relative_vertnum{static_cast<uint8_t>((3 - underlying_value(v)) + 4)})] = seg2->verts[sv[v]];
|
||||
}
|
||||
|
||||
// Copy vertices from seg1 into first 4 vertices of bridge segment.
|
||||
|
@ -1222,8 +1222,8 @@ int med_form_bridge_segment(const vmsegptridx_t seg1, const sidenum_t side1, con
|
|||
|
||||
{
|
||||
auto &sv = Side_to_verts[side1];
|
||||
for (const auto v : xrange(4u))
|
||||
bs->verts[(segment_relative_vertnum{static_cast<uint8_t>((v + bfi) % 4)})] = seg1->verts[sv[v]];
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
bs->verts[(segment_relative_vertnum{static_cast<uint8_t>((underlying_value(v) + bfi) % 4)})] = seg1->verts[sv[v]];
|
||||
}
|
||||
|
||||
// Form connections to children, first initialize all to unconnected.
|
||||
|
@ -1458,9 +1458,9 @@ static int check_seg_concavity(const shared_segment &s)
|
|||
for (unsigned vn = 0; vn <= 4; ++vn)
|
||||
{
|
||||
const auto n1 = vm_vec_normal(
|
||||
vcvertptr(s.verts[sn[vn % 4]]),
|
||||
vcvertptr(s.verts[sn[(vn + 1) % 4]]),
|
||||
vcvertptr(s.verts[sn[(vn + 2) % 4]]));
|
||||
vcvertptr(s.verts[sn[static_cast<side_relative_vertnum>(vn % 4)]]),
|
||||
vcvertptr(s.verts[sn[static_cast<side_relative_vertnum>((vn + 1) % 4)]]),
|
||||
vcvertptr(s.verts[sn[static_cast<side_relative_vertnum>((vn + 2) % 4)]]));
|
||||
|
||||
//vm_vec_normalize(&n1);
|
||||
|
||||
|
@ -1522,10 +1522,10 @@ void warn_if_concave_segment(const vmsegptridx_t s)
|
|||
// If not found, return an empty optional.
|
||||
std::optional<std::pair<vmsegptridx_t, sidenum_t>> med_find_adjacent_segment_side(const vmsegptridx_t sp, sidenum_t side)
|
||||
{
|
||||
std::array<vertnum_t, 4> abs_verts;
|
||||
enumerated_array<vertnum_t, 4, side_relative_vertnum> abs_verts;
|
||||
|
||||
// Stuff abs_verts[4] array with absolute vertex indices
|
||||
range_for (const unsigned v, xrange(4u))
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
abs_verts[v] = sp->verts[Side_to_verts[side][v]];
|
||||
|
||||
// Scan all segments, looking for a segment which contains the four abs_verts
|
||||
|
|
|
@ -96,7 +96,7 @@ static fix get_average_light_at_vertex(const vertnum_t vnum, segnum_t *segs)
|
|||
const auto vi = std::find(vb, ve, relvnum);
|
||||
if (vi != ve)
|
||||
{
|
||||
const auto v = std::distance(vb, vi);
|
||||
const auto v = static_cast<side_relative_vertnum>(std::distance(vb, vi));
|
||||
total_light += uside.uvls[v].l;
|
||||
num_occurrences++;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ static void set_average_light_at_vertex(vertnum_t vnum)
|
|||
const auto vi = std::find(vb, ve, relvnum);
|
||||
if (vi != ve)
|
||||
{
|
||||
const auto v = std::distance(vb, vi);
|
||||
const auto v = static_cast<side_relative_vertnum>(std::distance(vb, vi));
|
||||
sidep.uvls[v].l = average_light;
|
||||
}
|
||||
} // end if
|
||||
|
@ -301,20 +301,26 @@ namespace {
|
|||
// (Actually, assign them to the coordinates in the faces.)
|
||||
// va, vb = face-relative vertex indices corresponding to uva, uvb. Ie, they are always in 0..3 and should be looked up in
|
||||
// Side_to_verts[side] to get the segment relative index.
|
||||
static void assign_uvs_to_side(fvcvertptr &vcvertptr, const vmsegptridx_t segp, const sidenum_t sidenum, const uvl &uva, const uvl &uvb, int va, int vb)
|
||||
static void assign_uvs_to_side(fvcvertptr &vcvertptr, const vmsegptridx_t segp, const sidenum_t sidenum, const uvl &uva, const uvl &uvb, const side_relative_vertnum va, const side_relative_vertnum vb)
|
||||
{
|
||||
int vlo,vhi;
|
||||
std::array<uvl, 4> uvls;
|
||||
uvl ruvmag,fuvmag;
|
||||
const uvl *uvlo, *uvhi;
|
||||
fix fmag,mag01;
|
||||
Assert( (va<4) && (vb<4) );
|
||||
Assert((abs(va - vb) == 1) || (abs(va - vb) == 3)); // make sure the verticies specify an edge
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
const auto distance_between_side_vertices = underlying_value(va) - underlying_value(vb);
|
||||
const auto abs_distance_between_side_vertices = std::abs(distance_between_side_vertices);
|
||||
// make sure the vertices specify an edge
|
||||
assert(abs_distance_between_side_vertices == 1 || abs_distance_between_side_vertices == 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto &vp = Side_to_verts[sidenum];
|
||||
|
||||
side_relative_vertnum vlo, vhi;
|
||||
// We want vlo precedes vhi, ie vlo < vhi, or vlo = 3, vhi = 0
|
||||
if (va == ((vb + 1) % 4)) { // va = vb + 1
|
||||
if (va == next_side_vertex(vb))
|
||||
{ // va = vb + 1
|
||||
vlo = vb;
|
||||
vhi = va;
|
||||
uvlo = &uvb;
|
||||
|
@ -326,7 +332,8 @@ static void assign_uvs_to_side(fvcvertptr &vcvertptr, const vmsegptridx_t segp,
|
|||
uvhi = &uvb;
|
||||
}
|
||||
|
||||
Assert(((vlo+1) % 4) == vhi); // If we are on an edge, then uvhi is one more than uvlo (mod 4)
|
||||
assert(next_side_vertex(vlo) == vhi); // If we are on an edge, then uvhi is one more than uvlo (mod 4)
|
||||
enumerated_array<uvl, 4, side_relative_vertnum> uvls;
|
||||
uvls[vlo] = *uvlo;
|
||||
uvls[vhi] = *uvhi;
|
||||
|
||||
|
@ -349,8 +356,10 @@ static void assign_uvs_to_side(fvcvertptr &vcvertptr, const vmsegptridx_t segp,
|
|||
|
||||
const auto v0 = segp->verts[vp[vlo]];
|
||||
const auto v1 = segp->verts[vp[vhi]];
|
||||
const auto v2 = segp->verts[vp[(vhi+1)%4]];
|
||||
const auto v3 = segp->verts[vp[(vhi+2)%4]];
|
||||
const auto vhi1 = next_side_vertex(vhi);
|
||||
const auto vhi2 = next_side_vertex(vhi, 2);
|
||||
const auto v2 = segp->verts[vp[vhi1]];
|
||||
const auto v3 = segp->verts[vp[vhi2]];
|
||||
|
||||
// Compute right vector by computing orientation matrix from:
|
||||
// forward vector = vlo:vhi
|
||||
|
@ -358,10 +367,10 @@ static void assign_uvs_to_side(fvcvertptr &vcvertptr, const vmsegptridx_t segp,
|
|||
const auto &&vp0 = vcvertptr(v0);
|
||||
const auto &vv1v0 = vm_vec_sub(vcvertptr(v1), vp0);
|
||||
mag01 = vm_vec_mag(vv1v0);
|
||||
mag01 = fixmul(mag01, (va == 0 || va == 2) ? Stretch_scale_x : Stretch_scale_y);
|
||||
mag01 = fixmul(mag01, (va == side_relative_vertnum::_0 || va == side_relative_vertnum::_2) ? Stretch_scale_x : Stretch_scale_y);
|
||||
|
||||
if (unlikely(mag01 < F1_0/1024))
|
||||
editor_status_fmt("U, V bogosity in segment #%hu, probably on side #%i. CLEAN UP YOUR MESS!", static_cast<uint16_t>(segp), sidenum);
|
||||
editor_status_fmt("U, V bogosity in segment #%hu, probably on side #%i. CLEAN UP YOUR MESS!", segp.get_unchecked_index(), sidenum);
|
||||
else {
|
||||
struct frvec {
|
||||
vms_vector fvec, rvec;
|
||||
|
@ -399,8 +408,8 @@ static void assign_uvs_to_side(fvcvertptr &vcvertptr, const vmsegptridx_t segp,
|
|||
uvi.l
|
||||
};
|
||||
};
|
||||
uvls[(vhi + 1) % 4] = build_uvl(vm_vec_sub(vcvertptr(v2), vcvertptr(v1)), *uvhi);
|
||||
uvls[(vhi + 2) % 4] = build_uvl(vv3v0, *uvlo);
|
||||
uvls[vhi1] = build_uvl(vm_vec_sub(vcvertptr(v2), vcvertptr(v1)), *uvhi);
|
||||
uvls[vhi2] = build_uvl(vv3v0, *uvlo);
|
||||
// For all faces in side, copy uv coordinates from uvs array to face.
|
||||
segp->unique_segment::sides[sidenum].uvls = uvls;
|
||||
}
|
||||
|
@ -429,9 +438,9 @@ void assign_default_uvs_to_side(const vmsegptridx_t segp, const sidenum_t side)
|
|||
auto &vp = Side_to_verts[side];
|
||||
uv1.u = 0;
|
||||
auto &vcvertptr = Vertices.vcptr;
|
||||
uv1.v = Num_tilings * fixmul(Vmag, vm_vec_dist(vcvertptr(segp->verts[vp[1]]), vcvertptr(segp->verts[vp[0]])));
|
||||
uv1.v = Num_tilings * fixmul(Vmag, vm_vec_dist(vcvertptr(segp->verts[vp[side_relative_vertnum::_1]]), vcvertptr(segp->verts[vp[side_relative_vertnum::_0]])));
|
||||
|
||||
assign_uvs_to_side(vcvertptr, segp, side, uv0, uv1, 0, 1);
|
||||
assign_uvs_to_side(vcvertptr, segp, side, uv0, uv1, side_relative_vertnum::_0, side_relative_vertnum::_1);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
@ -445,12 +454,11 @@ void stretch_uvs_from_curedge(const vmsegptridx_t segp, const sidenum_t side)
|
|||
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
||||
auto &Vertices = LevelSharedVertexState.get_vertices();
|
||||
uvl uv0,uv1;
|
||||
int v0, v1;
|
||||
|
||||
v0 = Curedge;
|
||||
v1 = (v0 + 1) % 4;
|
||||
const auto v0 = Curedge;
|
||||
const auto v1 = next_side_vertex(v0);
|
||||
|
||||
auto &uvls = segp->unique_segment::sides[side].uvls;
|
||||
const auto &uvls = segp->unique_segment::sides[side].uvls;
|
||||
uv0.u = uvls[v0].u;
|
||||
uv0.v = uvls[v0].v;
|
||||
|
||||
|
@ -570,7 +578,6 @@ static void med_assign_uvs_to_side(const vmsegptridx_t con_seg, const sidenum_t
|
|||
{
|
||||
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
||||
auto &Vertices = LevelSharedVertexState.get_vertices();
|
||||
int vv1, vv2;
|
||||
constexpr segment_relative_vertnum invalid_vertnum{0xff};
|
||||
segment_relative_vertnum cv1 = invalid_vertnum, cv2 = invalid_vertnum;
|
||||
segment_relative_vertnum bv1 = invalid_vertnum, bv2 = invalid_vertnum;
|
||||
|
@ -599,7 +606,7 @@ static void med_assign_uvs_to_side(const vmsegptridx_t con_seg, const sidenum_t
|
|||
// Now, scan 4 vertices in base side and 4 vertices in connected side.
|
||||
// Set uv1, uv2 to uv coordinates from base side which correspond to vertices bv1, bv2.
|
||||
// Set vv1, vv2 to relative vertex ids (in 0..3) in connecting side which correspond to cv1, cv2
|
||||
vv1 = -1; vv2 = -1;
|
||||
std::optional<side_relative_vertnum> vv1, vv2;
|
||||
auto &base_uvls = base_seg.u.sides[base_common_side].uvls;
|
||||
const uvl *uv1 = nullptr, *uv2 = nullptr;
|
||||
auto &svbase = Side_to_verts[base_common_side];
|
||||
|
@ -617,9 +624,9 @@ static void med_assign_uvs_to_side(const vmsegptridx_t con_seg, const sidenum_t
|
|||
}
|
||||
|
||||
assert(uv1->u != uv2->u || uv1->v != uv2->v);
|
||||
Assert( (vv1 != -1) && (vv2 != -1) );
|
||||
assert(vv1.has_value() && vv2.has_value());
|
||||
auto &vcvertptr = Vertices.vcptr;
|
||||
assign_uvs_to_side(vcvertptr, con_seg, con_common_side, *uv1, *uv2, vv1, vv2);
|
||||
assign_uvs_to_side(vcvertptr, con_seg, con_common_side, *uv1, *uv2, *vv1, *vv2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -640,11 +647,13 @@ static std::pair<sidenum_t, sidenum_t> get_side_ids(const shared_segment &base_s
|
|||
for (const auto &&[idx, base_vp] : enumerate(Side_to_verts))
|
||||
{
|
||||
if (idx != base_side) {
|
||||
for (const auto v0 : xrange(4u))
|
||||
for (const auto v0 : MAX_VERTICES_PER_SIDE)
|
||||
{
|
||||
auto &verts = base_seg.verts;
|
||||
if ((verts[base_vp[v0]] == abs_id1 && verts[base_vp[(v0+1) % 4]] == abs_id2) ||
|
||||
(verts[base_vp[v0]] == abs_id2 && verts[base_vp[ (v0+1) % 4]] == abs_id1))
|
||||
const auto candidate_abs_v0 = verts[base_vp[v0]];
|
||||
const auto candidate_abs_v1 = verts[base_vp[next_side_vertex(v0)]];
|
||||
if ((candidate_abs_v0 == abs_id1 && candidate_abs_v1 == abs_id2) ||
|
||||
(candidate_abs_v0 == abs_id2 && candidate_abs_v1 == abs_id1))
|
||||
{
|
||||
assert(!base_common_side); // This means two different sides shared the same edge with base_side == impossible!
|
||||
base_common_side = idx;
|
||||
|
@ -660,11 +669,13 @@ static std::pair<sidenum_t, sidenum_t> get_side_ids(const shared_segment &base_s
|
|||
for (const auto &&[idx, con_vp] : enumerate(Side_to_verts))
|
||||
{
|
||||
if (idx != con_side) {
|
||||
for (const auto v0 : xrange(4u))
|
||||
for (const auto v0 : MAX_VERTICES_PER_SIDE)
|
||||
{
|
||||
auto &verts = con_seg.verts;
|
||||
if ((verts[con_vp[(v0 + 1) % 4]] == abs_id1 && verts[con_vp[v0]] == abs_id2) ||
|
||||
(verts[con_vp[(v0 + 1) % 4]] == abs_id2 && verts[con_vp[v0]] == abs_id1))
|
||||
const auto candidate_abs_v0 = verts[con_vp[next_side_vertex(v0)]];
|
||||
const auto candidate_abs_v1 = verts[con_vp[v0]];
|
||||
if ((candidate_abs_v0 == abs_id1 && candidate_abs_v1 == abs_id2) ||
|
||||
(candidate_abs_v0 == abs_id2 && candidate_abs_v1 == abs_id1))
|
||||
{
|
||||
assert(!con_common_side); // This means two different sides shared the same edge with con_side == impossible!
|
||||
con_common_side = idx;
|
||||
|
@ -783,7 +794,7 @@ namespace {
|
|||
static void fix_bogus_uvs_on_side1(const vmsegptridx_t sp, const sidenum_t sidenum, const int uvonly_flag)
|
||||
{
|
||||
auto &uvls = sp->unique_segment::sides[sidenum].uvls;
|
||||
if (uvls[0].u == 0 && uvls[1].u == 0 && uvls[2].u == 0)
|
||||
if (uvls[side_relative_vertnum::_0].u == 0 && uvls[side_relative_vertnum::_1].u == 0 && uvls[side_relative_vertnum::_2].u == 0)
|
||||
{
|
||||
med_propagate_tmaps_to_back_side(sp, static_cast<sidenum_t>(sidenum), uvonly_flag);
|
||||
}
|
||||
|
@ -820,17 +831,15 @@ namespace {
|
|||
// segment to get the wall in the connected segment which shares the edge, and get tmap_num from there.
|
||||
static void propagate_tmaps_to_segment_sides(const vcsegptridx_t base_seg, const sidenum_t base_side, const vmsegptridx_t con_seg, const sidenum_t con_side, const int uv_only_flag)
|
||||
{
|
||||
int v;
|
||||
|
||||
auto &base_vp = Side_to_verts[base_side];
|
||||
|
||||
// Do for each edge on connecting face.
|
||||
for (v=0; v<4; v++) {
|
||||
for (const auto v : MAX_VERTICES_PER_SIDE)
|
||||
{
|
||||
const auto abs_id1 = base_seg->verts[base_vp[v]];
|
||||
const auto abs_id2 = base_seg->verts[base_vp[(v + 1) % 4]];
|
||||
const auto abs_id2 = base_seg->verts[base_vp[next_side_vertex(v)]];
|
||||
propagate_tmaps_to_segment_side(base_seg, base_side, con_seg, con_side, abs_id1, abs_id2, uv_only_flag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -961,7 +970,7 @@ static void cast_light_from_side(const vmsegptridx_t segp, const sidenum_t light
|
|||
auto &side_normalp = srside.normals[0]; // kinda stupid? always use vector 0.
|
||||
|
||||
auto &sv_side = Side_to_verts[static_cast<sidenum_t>(sidenum)];
|
||||
for (const auto vertnum : xrange(4u))
|
||||
for (const auto vertnum : MAX_VERTICES_PER_SIDE)
|
||||
{
|
||||
const auto segment_relative_vert = sv_side[vertnum];
|
||||
const auto abs_vertnum = rsegp->verts[segment_relative_vert];
|
||||
|
|
|
@ -87,13 +87,15 @@ static int DoTexSlideLeft(int value)
|
|||
auto &uvls = Cursegp->unique_segment::sides[Curside].uvls;
|
||||
|
||||
auto &vcvertptr = Vertices.vcptr;
|
||||
dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[3]]), vcvertptr(Cursegp->verts[vp[0]]));
|
||||
dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[side_relative_vertnum::_3]]), vcvertptr(Cursegp->verts[vp[side_relative_vertnum::_0]]));
|
||||
dist *= value;
|
||||
if (dist < F1_0/(64*value))
|
||||
dist = F1_0/(64*value);
|
||||
|
||||
duvl03.u = fixdiv(uvls[3].u - uvls[0].u,dist);
|
||||
duvl03.v = fixdiv(uvls[3].v - uvls[0].v,dist);
|
||||
auto &u3 = uvls[side_relative_vertnum::_3];
|
||||
auto &u0 = uvls[side_relative_vertnum::_0];
|
||||
duvl03.u = fixdiv(u3.u - u0.u, dist);
|
||||
duvl03.v = fixdiv(u3.v - u0.v, dist);
|
||||
|
||||
range_for (auto &v, uvls)
|
||||
{
|
||||
|
@ -127,14 +129,16 @@ static int DoTexSlideUp(int value)
|
|||
auto &uvls = Cursegp->unique_segment::sides[Curside].uvls;
|
||||
|
||||
auto &vcvertptr = Vertices.vcptr;
|
||||
dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[1]]), vcvertptr(Cursegp->verts[vp[0]]));
|
||||
dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[side_relative_vertnum::_1]]), vcvertptr(Cursegp->verts[vp[side_relative_vertnum::_0]]));
|
||||
dist *= value;
|
||||
|
||||
if (dist < F1_0/(64*value))
|
||||
dist = F1_0/(64*value);
|
||||
|
||||
duvl03.u = fixdiv(uvls[1].u - uvls[0].u,dist);
|
||||
duvl03.v = fixdiv(uvls[1].v - uvls[0].v,dist);
|
||||
auto &u1 = uvls[side_relative_vertnum::_1];
|
||||
auto &u0 = uvls[side_relative_vertnum::_0];
|
||||
duvl03.u = fixdiv(u1.u - u0.u, dist);
|
||||
duvl03.v = fixdiv(u1.v - u0.v, dist);
|
||||
|
||||
range_for (auto &v, uvls)
|
||||
{
|
||||
|
@ -169,13 +173,15 @@ static int DoTexSlideDown(int value)
|
|||
auto &uvls = Cursegp->unique_segment::sides[Curside].uvls;
|
||||
|
||||
auto &vcvertptr = Vertices.vcptr;
|
||||
dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[1]]), vcvertptr(Cursegp->verts[vp[0]]));
|
||||
dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[side_relative_vertnum::_1]]), vcvertptr(Cursegp->verts[vp[side_relative_vertnum::_0]]));
|
||||
dist *= value;
|
||||
if (dist < F1_0/(64*value))
|
||||
dist = F1_0/(64*value);
|
||||
|
||||
duvl03.u = fixdiv(uvls[1].u - uvls[0].u,dist);
|
||||
duvl03.v = fixdiv(uvls[1].v - uvls[0].v,dist);
|
||||
auto &u1 = uvls[side_relative_vertnum::_1];
|
||||
auto &u0 = uvls[side_relative_vertnum::_0];
|
||||
duvl03.u = fixdiv(u1.u - u0.u, dist);
|
||||
duvl03.v = fixdiv(u1.v - u0.v, dist);
|
||||
|
||||
range_for (auto &v, uvls)
|
||||
{
|
||||
|
@ -289,13 +295,15 @@ static int DoTexSlideRight(int value)
|
|||
auto &uvls = Cursegp->unique_segment::sides[Curside].uvls;
|
||||
|
||||
auto &vcvertptr = Vertices.vcptr;
|
||||
dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[3]]), vcvertptr(Cursegp->verts[vp[0]]));
|
||||
dist = vm_vec_dist(vcvertptr(Cursegp->verts[vp[side_relative_vertnum::_3]]), vcvertptr(Cursegp->verts[vp[side_relative_vertnum::_0]]));
|
||||
dist *= value;
|
||||
if (dist < F1_0/(64*value))
|
||||
dist = F1_0/(64*value);
|
||||
|
||||
duvl03.u = fixdiv(uvls[3].u - uvls[0].u,dist);
|
||||
duvl03.v = fixdiv(uvls[3].v - uvls[0].v,dist);
|
||||
auto &u3 = uvls[side_relative_vertnum::_3];
|
||||
auto &u0 = uvls[side_relative_vertnum::_0];
|
||||
duvl03.u = fixdiv(u3.u - u0.u, dist);
|
||||
duvl03.v = fixdiv(u3.v - u0.v, dist);
|
||||
|
||||
range_for (auto &v, uvls)
|
||||
{
|
||||
|
@ -406,12 +414,9 @@ int TexDecreaseTiling()
|
|||
// direction = -1 or 1 depending on direction
|
||||
static int TexStretchCommon(int direction)
|
||||
{
|
||||
fix *sptr;
|
||||
|
||||
if ((Curedge == 0) || (Curedge == 2))
|
||||
sptr = &Stretch_scale_x;
|
||||
else
|
||||
sptr = &Stretch_scale_y;
|
||||
const auto sptr = (Curedge == side_relative_vertnum::_0 || Curedge == side_relative_vertnum::_2)
|
||||
? &Stretch_scale_x
|
||||
: &Stretch_scale_y;
|
||||
|
||||
*sptr += direction*F1_0/64;
|
||||
|
||||
|
|
|
@ -66,13 +66,13 @@ struct segment_water_depth_array : std::array<uint8_t, MAX_SEGMENTS> {};
|
|||
class abs_vertex_lists_predicate
|
||||
{
|
||||
const enumerated_array<vertnum_t, MAX_VERTICES_PER_SEGMENT, segment_relative_vertnum> &m_vp;
|
||||
const std::array<segment_relative_vertnum, 4> &m_sv;
|
||||
const enumerated_array<segment_relative_vertnum, 4, side_relative_vertnum> &m_sv;
|
||||
public:
|
||||
abs_vertex_lists_predicate(const shared_segment &seg, const sidenum_t sidenum) :
|
||||
m_vp(seg.verts), m_sv(Side_to_verts[sidenum])
|
||||
{
|
||||
}
|
||||
vertnum_t operator()(const uint_fast32_t vv) const
|
||||
vertnum_t operator()(const side_relative_vertnum vv) const
|
||||
{
|
||||
return m_vp[m_sv[vv]];
|
||||
}
|
||||
|
@ -82,9 +82,9 @@ class all_vertnum_lists_predicate : public abs_vertex_lists_predicate
|
|||
{
|
||||
public:
|
||||
using abs_vertex_lists_predicate::abs_vertex_lists_predicate;
|
||||
vertex_vertnum_pair operator()(const uint_fast32_t vv) const
|
||||
vertex_vertnum_pair operator()(const side_relative_vertnum vv) const
|
||||
{
|
||||
return {this->abs_vertex_lists_predicate::operator()(vv), static_cast<unsigned>(vv)};
|
||||
return {this->abs_vertex_lists_predicate::operator()(vv), vv};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -237,7 +237,7 @@ static uint_fast32_t create_vertex_lists_from_values(T &va, const shared_segment
|
|||
template <typename T, typename F>
|
||||
static inline uint_fast32_t create_vertex_lists_by_predicate(T &va, const shared_segment &segp, const shared_side &sidep, const F &&f)
|
||||
{
|
||||
return create_vertex_lists_from_values(va, segp, sidep, f(0), f(1), f(2), f(3));
|
||||
return create_vertex_lists_from_values(va, segp, sidep, f(side_relative_vertnum::_0), f(side_relative_vertnum::_1), f(side_relative_vertnum::_2), f(side_relative_vertnum::_3));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ uint_fast32_t create_all_vertex_lists(vertex_array_list_t &vertices, const share
|
|||
{
|
||||
assert(Side_to_verts.valid_index(sidenum));
|
||||
auto &sv = Side_to_verts[sidenum];
|
||||
return create_vertex_lists_by_predicate(vertices, segp, sidep, [&sv](const uint_fast32_t vv) {
|
||||
return create_vertex_lists_by_predicate(vertices, segp, sidep, [&sv](const side_relative_vertnum vv) {
|
||||
return sv[vv];
|
||||
});
|
||||
}
|
||||
|
@ -1214,11 +1214,11 @@ static unsigned check_for_degenerate_side(fvcvertptr &vcvertptr, const shared_se
|
|||
//vm_vec_sub(&vec2, &Vertices[sp->verts[vp[2]]], &Vertices[sp->verts[vp[1]]]);
|
||||
//vm_vec_normalize(&vec1);
|
||||
//vm_vec_normalize(&vec2);
|
||||
const auto vp1 = vp[1];
|
||||
const auto vp2 = vp[2];
|
||||
const auto vp1 = vp[side_relative_vertnum::_1];
|
||||
const auto vp2 = vp[side_relative_vertnum::_2];
|
||||
auto &vert1 = *vcvertptr(sp.verts[vp1]);
|
||||
auto &vert2 = *vcvertptr(sp.verts[vp2]);
|
||||
vm_vec_normalized_dir(vec1, vert1, vcvertptr(sp.verts[vp[0]]));
|
||||
vm_vec_normalized_dir(vec1, vert1, vcvertptr(sp.verts[vp[side_relative_vertnum::_0]]));
|
||||
vm_vec_normalized_dir(vec2, vert2, vert1);
|
||||
const auto cross0 = vm_vec_cross(vec1, vec2);
|
||||
|
||||
|
@ -1231,7 +1231,7 @@ static unsigned check_for_degenerate_side(fvcvertptr &vcvertptr, const shared_se
|
|||
//vm_vec_normalize(&vec1);
|
||||
//vm_vec_normalize(&vec2);
|
||||
vm_vec_normalized_dir(vec1, vert2, vert1);
|
||||
vm_vec_normalized_dir(vec2, vcvertptr(sp.verts[vp[3]]), vert2);
|
||||
vm_vec_normalized_dir(vec2, vcvertptr(sp.verts[vp[side_relative_vertnum::_3]]), vert2);
|
||||
const auto cross1 = vm_vec_cross(vec1, vec2);
|
||||
|
||||
dot = vm_vec_dot(vec_to_center, cross1);
|
||||
|
@ -1356,10 +1356,10 @@ static void add_side_as_2_triangles(fvcvertptr &vcvertptr, shared_segment &sp, c
|
|||
if (!IS_CHILD(sp.children[sidenum]))
|
||||
{
|
||||
auto &verts = sp.verts;
|
||||
auto &vvs0 = *vcvertptr(verts[vs[0]]);
|
||||
auto &vvs1 = *vcvertptr(verts[vs[1]]);
|
||||
auto &vvs2 = *vcvertptr(verts[vs[2]]);
|
||||
auto &vvs3 = *vcvertptr(verts[vs[3]]);
|
||||
auto &vvs0 = *vcvertptr(verts[vs[side_relative_vertnum::_0]]);
|
||||
auto &vvs1 = *vcvertptr(verts[vs[side_relative_vertnum::_1]]);
|
||||
auto &vvs2 = *vcvertptr(verts[vs[side_relative_vertnum::_2]]);
|
||||
auto &vvs3 = *vcvertptr(verts[vs[side_relative_vertnum::_3]]);
|
||||
const auto &&norm = vm_vec_normal(vvs0, vvs1, vvs2);
|
||||
const auto &&vec_13 = vm_vec_sub(vvs3, vvs1); // vector from vertex 1 to vertex 3
|
||||
dot = vm_vec_dot(norm, vec_13);
|
||||
|
@ -1372,28 +1372,28 @@ static void add_side_as_2_triangles(fvcvertptr &vcvertptr, shared_segment &sp, c
|
|||
vm_vec_normal(sidep->normals[0], vvs0, vvs1, *n0v3);
|
||||
vm_vec_normal(sidep->normals[1], *n1v1, vvs2, vvs3);
|
||||
} else {
|
||||
std::array<vertnum_t, 4> v;
|
||||
enumerated_array<vertnum_t, 4, side_relative_vertnum> v;
|
||||
|
||||
range_for (const unsigned i, xrange(4u))
|
||||
for (const auto i : MAX_VERTICES_PER_SIDE)
|
||||
v[i] = sp.verts[vs[i]];
|
||||
|
||||
verts_for_normal vfn{v[0], v[1], v[2], v[3]};
|
||||
verts_for_normal vfn{v[side_relative_vertnum::_0], v[side_relative_vertnum::_1], v[side_relative_vertnum::_2], v[side_relative_vertnum::_3]};
|
||||
get_verts_for_normal(vfn);
|
||||
|
||||
vertnum_t s0v2, s1v0;
|
||||
if ((vfn.vsorted[0] == v[0]) || (vfn.vsorted[0] == v[2])) {
|
||||
if ((vfn.vsorted[0] == v[side_relative_vertnum::_0]) || (vfn.vsorted[0] == v[side_relative_vertnum::_2])) {
|
||||
sidep->set_type(side_type::tri_02);
|
||||
// Now, get vertices for normal for each triangle based on triangulation type.
|
||||
s0v2 = v[2];
|
||||
s1v0 = v[0];
|
||||
s0v2 = v[side_relative_vertnum::_2];
|
||||
s1v0 = v[side_relative_vertnum::_0];
|
||||
} else {
|
||||
sidep->set_type(side_type::tri_13);
|
||||
// Now, get vertices for normal for each triangle based on triangulation type.
|
||||
s0v2 = v[3];
|
||||
s1v0 = v[1];
|
||||
s0v2 = v[side_relative_vertnum::_3];
|
||||
s1v0 = v[side_relative_vertnum::_1];
|
||||
}
|
||||
assign_side_normal(vcvertptr, sidep->normals[0], v[0], v[1], s0v2);
|
||||
assign_side_normal(vcvertptr, sidep->normals[1], s1v0, v[2], v[3]);
|
||||
assign_side_normal(vcvertptr, sidep->normals[0], v[side_relative_vertnum::_0], v[side_relative_vertnum::_1], s0v2);
|
||||
assign_side_normal(vcvertptr, sidep->normals[1], s1v0, v[side_relative_vertnum::_2], v[side_relative_vertnum::_3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1427,10 +1427,10 @@ namespace {
|
|||
void create_walls_on_side(fvcvertptr &vcvertptr, shared_segment &sp, const sidenum_t sidenum)
|
||||
{
|
||||
auto &vs = Side_to_verts[sidenum];
|
||||
const auto v0 = sp.verts[vs[0]];
|
||||
const auto v1 = sp.verts[vs[1]];
|
||||
const auto v2 = sp.verts[vs[2]];
|
||||
const auto v3 = sp.verts[vs[3]];
|
||||
const auto v0 = sp.verts[vs[side_relative_vertnum::_0]];
|
||||
const auto v1 = sp.verts[vs[side_relative_vertnum::_1]];
|
||||
const auto v2 = sp.verts[vs[side_relative_vertnum::_2]];
|
||||
const auto v3 = sp.verts[vs[side_relative_vertnum::_3]];
|
||||
|
||||
verts_for_normal vfn{v0, v1, v2, v3};
|
||||
const auto negate_flag = get_verts_for_normal(vfn);
|
||||
|
@ -1758,7 +1758,8 @@ static void change_light(const d_level_shared_destructible_light_state &LevelSha
|
|||
assert(j.sidenum < MAX_SIDES_PER_SEGMENT);
|
||||
const auto &&segp = vmsegptr(j.segnum);
|
||||
auto &uvls = segp->unique_segment::sides[j.sidenum].uvls;
|
||||
range_for (const int k, xrange(4u)) {
|
||||
for (const auto k : MAX_VERTICES_PER_SIDE)
|
||||
{
|
||||
auto &l = uvls[k].l;
|
||||
const fix dl = ds * j.vert_light[k];
|
||||
if ((l += dl) < 0)
|
||||
|
|
|
@ -91,13 +91,13 @@ constexpr enumerated_array<sidenum_t, MAX_SIDES_PER_SEGMENT, sidenum_t> Side_opp
|
|||
|
||||
#define TOLOWER(c) ((((c)>='A') && ((c)<='Z'))?((c)+('a'-'A')):(c))
|
||||
|
||||
const enumerated_array<std::array<segment_relative_vertnum, 4>, MAX_SIDES_PER_SEGMENT, sidenum_t> Side_to_verts{{{
|
||||
{{segment_relative_vertnum::_7, segment_relative_vertnum::_6, segment_relative_vertnum::_2, segment_relative_vertnum::_3}}, // left
|
||||
{{segment_relative_vertnum::_0, segment_relative_vertnum::_4, segment_relative_vertnum::_7, segment_relative_vertnum::_3}}, // top
|
||||
{{segment_relative_vertnum::_0, segment_relative_vertnum::_1, segment_relative_vertnum::_5, segment_relative_vertnum::_4}}, // right
|
||||
{{segment_relative_vertnum::_2, segment_relative_vertnum::_6, segment_relative_vertnum::_5, segment_relative_vertnum::_1}}, // bottom
|
||||
{{segment_relative_vertnum::_4, segment_relative_vertnum::_5, segment_relative_vertnum::_6, segment_relative_vertnum::_7}}, // back
|
||||
{{segment_relative_vertnum::_3, segment_relative_vertnum::_2, segment_relative_vertnum::_1, segment_relative_vertnum::_0}}, // front
|
||||
const enumerated_array<enumerated_array<segment_relative_vertnum, 4, side_relative_vertnum>, MAX_SIDES_PER_SEGMENT, sidenum_t> Side_to_verts{{{
|
||||
{{{segment_relative_vertnum::_7, segment_relative_vertnum::_6, segment_relative_vertnum::_2, segment_relative_vertnum::_3}}}, // left
|
||||
{{{segment_relative_vertnum::_0, segment_relative_vertnum::_4, segment_relative_vertnum::_7, segment_relative_vertnum::_3}}}, // top
|
||||
{{{segment_relative_vertnum::_0, segment_relative_vertnum::_1, segment_relative_vertnum::_5, segment_relative_vertnum::_4}}}, // right
|
||||
{{{segment_relative_vertnum::_2, segment_relative_vertnum::_6, segment_relative_vertnum::_5, segment_relative_vertnum::_1}}}, // bottom
|
||||
{{{segment_relative_vertnum::_4, segment_relative_vertnum::_5, segment_relative_vertnum::_6, segment_relative_vertnum::_7}}}, // back
|
||||
{{{segment_relative_vertnum::_3, segment_relative_vertnum::_2, segment_relative_vertnum::_1, segment_relative_vertnum::_0}}}, // front
|
||||
}}};
|
||||
|
||||
// Texture map stuff
|
||||
|
|
|
@ -3217,10 +3217,10 @@ static int newdemo_read_frame_information(int rewrite)
|
|||
w.state = wall_state{state};
|
||||
w.cloak_value = cloak_value;
|
||||
auto &uvl = vmsegptr(w.segnum)->unique_segment::sides[w.sidenum].uvls;
|
||||
uvl[0].l = (static_cast<int>(l0)) << 8;
|
||||
uvl[1].l = (static_cast<int>(l1)) << 8;
|
||||
uvl[2].l = (static_cast<int>(l2)) << 8;
|
||||
uvl[3].l = (static_cast<int>(l3)) << 8;
|
||||
uvl[side_relative_vertnum::_0].l = (static_cast<int>(l0)) << 8;
|
||||
uvl[side_relative_vertnum::_1].l = (static_cast<int>(l1)) << 8;
|
||||
uvl[side_relative_vertnum::_2].l = (static_cast<int>(l2)) << 8;
|
||||
uvl[side_relative_vertnum::_3].l = (static_cast<int>(l3)) << 8;
|
||||
}
|
||||
{
|
||||
auto &w = *vmwallptr(back_wall_num);
|
||||
|
@ -3228,10 +3228,10 @@ static int newdemo_read_frame_information(int rewrite)
|
|||
w.state = wall_state{state};
|
||||
w.cloak_value = cloak_value;
|
||||
auto &uvl = vmsegptr(w.segnum)->unique_segment::sides[w.sidenum].uvls;
|
||||
uvl[0].l = (static_cast<int>(l0)) << 8;
|
||||
uvl[1].l = (static_cast<int>(l1)) << 8;
|
||||
uvl[2].l = (static_cast<int>(l2)) << 8;
|
||||
uvl[3].l = (static_cast<int>(l3)) << 8;
|
||||
uvl[side_relative_vertnum::_0].l = (static_cast<int>(l0)) << 8;
|
||||
uvl[side_relative_vertnum::_1].l = (static_cast<int>(l1)) << 8;
|
||||
uvl[side_relative_vertnum::_2].l = (static_cast<int>(l2)) << 8;
|
||||
uvl[side_relative_vertnum::_3].l = (static_cast<int>(l3)) << 8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -802,7 +802,7 @@ constexpr fix CROSS_WIDTH = i2f(8);
|
|||
constexpr fix CROSS_HEIGHT = i2f(8);
|
||||
|
||||
//draw outline for curside
|
||||
static void outline_seg_side(grs_canvas &canvas, const shared_segment &seg, const sidenum_t _side, const unsigned edge, const unsigned vert)
|
||||
static void outline_seg_side(grs_canvas &canvas, const shared_segment &seg, const sidenum_t _side, const side_relative_vertnum edge, const side_relative_vertnum vert)
|
||||
{
|
||||
auto &verts = seg.verts;
|
||||
auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
|
||||
|
@ -814,7 +814,7 @@ static void outline_seg_side(grs_canvas &canvas, const shared_segment &seg, cons
|
|||
|
||||
const uint8_t color = BM_XRGB(0, 63, 0);
|
||||
auto &sv = Side_to_verts[_side];
|
||||
g3_draw_line(canvas, Segment_points[verts[sv[edge]]], Segment_points[verts[sv[(edge + 1)%4]]], color);
|
||||
g3_draw_line(canvas, Segment_points[verts[sv[edge]]], Segment_points[verts[sv[next_side_vertex(edge)]]], color);
|
||||
|
||||
//draw a little cross at the current vert
|
||||
|
||||
|
@ -1002,7 +1002,7 @@ static std::optional<sidenum_t> find_seg_side(const shared_segment &seg, const s
|
|||
static bool compare_child(fvcvertptr &vcvertptr, const vms_vector &Viewer_eye, const shared_segment &seg, const shared_segment &cseg, const sidenum_t edgeside)
|
||||
{
|
||||
const auto &cside = cseg.sides[edgeside];
|
||||
const auto &sv = Side_to_verts[edgeside][cside.get_type() == side_type::tri_13 ? 1 : 0];
|
||||
const auto &sv = Side_to_verts[edgeside][cside.get_type() == side_type::tri_13 ? side_relative_vertnum::_1 : side_relative_vertnum::_0];
|
||||
const auto &temp = vm_vec_sub(Viewer_eye, vcvertptr(seg.verts[sv]));
|
||||
const auto &cnormal = cside.normals;
|
||||
return vm_vec_dot(cnormal[0], temp) < 0 || vm_vec_dot(cnormal[1], temp) < 0;
|
||||
|
|
|
@ -66,10 +66,10 @@ void delta_light_read(delta_light *dl, PHYSFS_File *fp)
|
|||
dl->segnum = PHYSFSX_readShort(fp);
|
||||
dl->sidenum = build_sidenum_from_untrusted(PHYSFSX_readByte(fp)).value_or(sidenum_t::WLEFT);
|
||||
PHYSFSX_readByte(fp);
|
||||
dl->vert_light[0] = PHYSFSX_readByte(fp);
|
||||
dl->vert_light[1] = PHYSFSX_readByte(fp);
|
||||
dl->vert_light[2] = PHYSFSX_readByte(fp);
|
||||
dl->vert_light[3] = PHYSFSX_readByte(fp);
|
||||
dl->vert_light[side_relative_vertnum::_0] = PHYSFSX_readByte(fp);
|
||||
dl->vert_light[side_relative_vertnum::_1] = PHYSFSX_readByte(fp);
|
||||
dl->vert_light[side_relative_vertnum::_2] = PHYSFSX_readByte(fp);
|
||||
dl->vert_light[side_relative_vertnum::_3] = PHYSFSX_readByte(fp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,10 +98,10 @@ void delta_light_write(const delta_light *dl, PHYSFS_File *fp)
|
|||
PHYSFS_writeSLE16(fp, dl->segnum);
|
||||
PHYSFSX_writeU8(fp, dl->sidenum);
|
||||
PHYSFSX_writeU8(fp, 0);
|
||||
PHYSFSX_writeU8(fp, dl->vert_light[0]);
|
||||
PHYSFSX_writeU8(fp, dl->vert_light[1]);
|
||||
PHYSFSX_writeU8(fp, dl->vert_light[2]);
|
||||
PHYSFSX_writeU8(fp, dl->vert_light[3]);
|
||||
PHYSFSX_writeU8(fp, dl->vert_light[side_relative_vertnum::_0]);
|
||||
PHYSFSX_writeU8(fp, dl->vert_light[side_relative_vertnum::_1]);
|
||||
PHYSFSX_writeU8(fp, dl->vert_light[side_relative_vertnum::_2]);
|
||||
PHYSFSX_writeU8(fp, dl->vert_light[side_relative_vertnum::_3]);
|
||||
}
|
||||
|
||||
void dl_index_write(const dl_index *di, PHYSFS_File *fp)
|
||||
|
|
Loading…
Reference in a new issue