Compare commits

...

2 Commits

3 changed files with 365 additions and 178 deletions

View File

@ -92,6 +92,8 @@ static ft0::data_transfer::data_format data[4];
uint8_t send_buf[1024] __attribute__((aligned(32))); uint8_t send_buf[1024] __attribute__((aligned(32)));
uint8_t recv_buf[1024] __attribute__((aligned(32))); uint8_t recv_buf[1024] __attribute__((aligned(32)));
constexpr void * bsp_start = &_binary_bsp_20kdm2_maps_20kdm2_bsp_start;
void do_get_condition() void do_get_condition()
{ {
auto writer = maple::host_command_writer(send_buf, recv_buf); auto writer = maple::host_command_writer(send_buf, recv_buf);
@ -181,6 +183,40 @@ void global_polygon_type_0(ta_parameter_writer& writer)
); );
} }
void global_polygon_type_0_textured(ta_parameter_writer& writer,
uint32_t obj_control_texture,
uint32_t texture_u_v_size,
uint32_t texture_control_word
)
{
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::opaque
| obj_control::col_type::floating_color
| obj_control::gouraud
| obj_control_texture
;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
| isp_tsp_instruction_word::culling_mode::cull_if_negative
;
const uint32_t tsp_instruction_word = tsp_instruction_word::fog_control::no_fog
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::filter_mode::bilinear_filter
| tsp_instruction_word::texture_shading_instruction::modulate
| texture_u_v_size
;
writer.append<ta_global_parameter::polygon_type_0>() =
ta_global_parameter::polygon_type_0(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
0,
0);
}
void global_polygon_type_1(ta_parameter_writer& writer, void global_polygon_type_1(ta_parameter_writer& writer,
uint32_t obj_control_texture, uint32_t obj_control_texture,
uint32_t texture_u_v_size, uint32_t texture_u_v_size,
@ -236,10 +272,10 @@ void global_texture(ta_parameter_writer& writer, int ix)
| texture_control_word::texture_address(texture_address / 8) | texture_control_word::texture_address(texture_address / 8)
; ;
global_polygon_type_1(writer, global_polygon_type_0_textured(writer,
obj_control::texture, obj_control::texture,
texture_u_v_size, texture_u_v_size,
texture_control_word); texture_control_word);
} }
void transform_vertices(uint8_t * buf, int length, const mat4x4& trans) void transform_vertices(uint8_t * buf, int length, const mat4x4& trans)
@ -283,53 +319,55 @@ static inline void render_tri_type_2(ta_parameter_writer& writer,
ci); ci);
} }
static int type7_tri_count = 0; static int type5_tri_count = 0;
static int vis_tri_count = 0; static int vis_tri_count = 0;
static int total_tri_count = 0; static int total_tri_count = 0;
static inline void render_tri_type_7(ta_parameter_writer& writer, static inline void render_tri_type_5(ta_parameter_writer& writer,
vec3 ap, vec3 ap,
vec3 bp, vec3 bp,
vec3 cp, vec3 cp,
vec2 at, vec2 at,
vec2 bt, vec2 bt,
vec2 ct, vec2 ct,
float ai, vec3 ac,
float bi, vec3 bc,
float ci) vec3 cc)
{ {
type7_tri_count += 1; type5_tri_count += 1;
writer.append<ta_vertex_parameter::polygon_type_7>() = writer.append<ta_vertex_parameter::polygon_type_5>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(false), ta_vertex_parameter::polygon_type_5(polygon_vertex_parameter_control_word(false),
ap.x, ap.y, ap.z, ap.x, ap.y, ap.z,
at.x, at.y, at.x, at.y,
ai, 1.0, ac.x, ac.y, ac.z,
0); 0, 0, 0, 0);
writer.append<ta_vertex_parameter::polygon_type_7>() = writer.append<ta_vertex_parameter::polygon_type_5>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(false), ta_vertex_parameter::polygon_type_5(polygon_vertex_parameter_control_word(false),
bp.x, bp.y, bp.z, bp.x, bp.y, bp.z,
bt.x, bt.y, bt.x, bt.y,
bi, 1.0, bc.x, bc.y, bc.z,
0); 0, 0, 0, 0);
writer.append<ta_vertex_parameter::polygon_type_7>() = writer.append<ta_vertex_parameter::polygon_type_5>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(true), ta_vertex_parameter::polygon_type_5(polygon_vertex_parameter_control_word(true),
cp.x, cp.y, cp.z, cp.x, cp.y, cp.z,
ct.x, ct.y, ct.x, ct.y,
ci, 1.0, cc.x, cc.y, cc.z,
0); 0, 0, 0, 0);
} }
static inline void render_clip_tri_type_7(ta_parameter_writer& writer, static inline void render_clip_tri_type_5(ta_parameter_writer& writer,
vec3 ap, vec3 ap,
vec3 bp, vec3 bp,
vec3 cp, vec3 cp,
vec2 at, vec2 at,
vec2 bt, vec2 bt,
vec2 ct, vec2 ct,
float li) vec3 ac,
vec3 bc,
vec3 cc)
{ {
//return; //return;
const vec3 plane_point = {0.f, 0.f, 1.f}; const vec3 plane_point = {0.f, 0.f, 1.f};
@ -337,15 +375,19 @@ static inline void render_clip_tri_type_7(ta_parameter_writer& writer,
vec3 preclip_position[] = {ap, bp, cp}; vec3 preclip_position[] = {ap, bp, cp};
vec2 preclip_texture[] = {at, bt, ct}; vec2 preclip_texture[] = {at, bt, ct};
vec3 preclip_color[] = {ac, bc, cc};
vec3 clip_position[4]; vec3 clip_position[4];
vec2 clip_texture[4]; vec2 clip_texture[4];
int output_length = geometry::clip_polygon_uv<3>(clip_position, vec3 clip_color[4];
clip_texture, int output_length = geometry::clip_polygon_3<3>(clip_position,
plane_point, clip_texture,
plane_normal, clip_color,
preclip_position, plane_point,
preclip_texture); plane_normal,
preclip_position,
preclip_texture,
preclip_color);
{ {
vec3 ap; vec3 ap;
@ -357,35 +399,40 @@ static inline void render_clip_tri_type_7(ta_parameter_writer& writer,
const vec2& bt = clip_texture[1]; const vec2& bt = clip_texture[1];
const vec2& ct = clip_texture[2]; const vec2& ct = clip_texture[2];
const vec2& dt = clip_texture[3]; const vec2& dt = clip_texture[3];
const vec3& ac = clip_color[0];
const vec3& bc = clip_color[1];
const vec3& cc = clip_color[2];
const vec3& dc = clip_color[3];
if (output_length >= 3) { if (output_length >= 3) {
ap = screen_transform(clip_position[0]); ap = screen_transform(clip_position[0]);
bp = screen_transform(clip_position[1]); bp = screen_transform(clip_position[1]);
cp = screen_transform(clip_position[2]); cp = screen_transform(clip_position[2]);
render_tri_type_7(writer, render_tri_type_5(writer,
ap, ap,
bp, bp,
cp, cp,
at, at,
bt, bt,
ct, ct,
li, ac,
li, bc,
li); cc);
} }
if (output_length >= 4) { if (output_length >= 4) {
dp = screen_transform(clip_position[3]); dp = screen_transform(clip_position[3]);
render_tri_type_7(writer, render_tri_type_5(writer,
ap, ap,
cp, cp,
dp, dp,
at, at,
ct, ct,
dt, dt,
li, ac,
li, cc,
li); dc);
} }
} }
} }
@ -413,7 +460,7 @@ static vec3 light_vec = {20, -20, -20};
static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * face, int * last_texture) static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * face, int * last_texture)
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
q3bsp_direntry * ve = &header->direntries[LUMP_VERTEXES]; q3bsp_direntry * ve = &header->direntries[LUMP_VERTEXES];
@ -462,6 +509,9 @@ static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * fac
vec3 n = vertex_cache[aix].normal; vec3 n = vertex_cache[aix].normal;
float li = light_intensity(light_vec, n); float li = light_intensity(light_vec, n);
vec3 ac = (vec3){1, 1, 1} * li;
vec3 bc = ac;
vec3 cc = ac;
if (has_texture) { if (has_texture) {
float v_mul = textures[face->texture].v_mul; float v_mul = textures[face->texture].v_mul;
@ -470,26 +520,28 @@ static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * fac
vec2 ct = {vert[cix].texcoord[0], vert[cix].texcoord[1] * v_mul}; vec2 ct = {vert[cix].texcoord[0], vert[cix].texcoord[1] * v_mul};
if (ap.z < 0 || bp.z < 0 || cp.z < 0) { if (ap.z < 0 || bp.z < 0 || cp.z < 0) {
render_clip_tri_type_7(writer, render_clip_tri_type_5(writer,
ap, ap,
bp, bp,
cp, cp,
at, at,
bt, bt,
ct, ct,
li); ac,
bc,
cc);
} else { } else {
render_tri_type_7(writer, render_tri_type_5(writer,
screen_transform(ap), screen_transform(ap),
screen_transform(bp), screen_transform(bp),
screen_transform(cp), screen_transform(cp),
at, at,
bt, bt,
ct, ct,
li, ac,
li, bc,
li); cc);
} }
} else { } else {
/* /*
@ -507,7 +559,7 @@ static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * fac
void transfer_faces(ta_parameter_writer& writer) void transfer_faces(ta_parameter_writer& writer)
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
q3bsp_direntry * fe = &header->direntries[LUMP_FACES]; q3bsp_direntry * fe = &header->direntries[LUMP_FACES];
@ -524,7 +576,7 @@ void transfer_faces(ta_parameter_writer& writer)
int count_face_triangles() int count_face_triangles()
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
q3bsp_direntry * fe = &header->direntries[LUMP_FACES]; q3bsp_direntry * fe = &header->direntries[LUMP_FACES];
@ -806,7 +858,7 @@ void render_ix(ta_parameter_writer& writer, int row, char * s, int ix)
void render_leaf_ix(ta_parameter_writer& writer) void render_leaf_ix(ta_parameter_writer& writer)
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
q3bsp_direntry * ne = &header->direntries[LUMP_NODES]; q3bsp_direntry * ne = &header->direntries[LUMP_NODES];
q3bsp_node_t * nodes = reinterpret_cast<q3bsp_node_t *>(&buf[ne->offset]); q3bsp_node_t * nodes = reinterpret_cast<q3bsp_node_t *>(&buf[ne->offset]);
@ -860,7 +912,7 @@ void render_tris_count(ta_parameter_writer& writer)
{ {
char s[32] = "rendered tris: "; char s[32] = "rendered tris: ";
int row = 2; int row = 2;
render_num(writer, row, s, type7_tri_count, offset); render_num(writer, row, s, type5_tri_count, offset);
} }
} }
@ -873,7 +925,7 @@ void render_bounding_box_mm(ta_parameter_writer& writer, const mat4x4& trans, in
void render_bounding_boxes(ta_parameter_writer& writer, const mat4x4& trans) void render_bounding_boxes(ta_parameter_writer& writer, const mat4x4& trans)
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
q3bsp_direntry * le = &header->direntries[LUMP_LEAFS]; q3bsp_direntry * le = &header->direntries[LUMP_LEAFS];
@ -921,7 +973,7 @@ bool vec3_in_bb(vec3 v, int mins[3], int maxs[3])
void render_leaf_faces(ta_parameter_writer& writer, const mat4x4& trans, q3bsp_leaf_t * leaf) void render_leaf_faces(ta_parameter_writer& writer, const mat4x4& trans, q3bsp_leaf_t * leaf)
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
//int leafface First leafface for leaf. //int leafface First leafface for leaf.
@ -948,7 +1000,7 @@ void render_leaf_faces(ta_parameter_writer& writer, const mat4x4& trans, q3bsp_l
void render_visible_faces(ta_parameter_writer& writer, const mat4x4& trans, const vec3 pos) void render_visible_faces(ta_parameter_writer& writer, const mat4x4& trans, const vec3 pos)
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
q3bsp_direntry * le = &header->direntries[LUMP_LEAFS]; q3bsp_direntry * le = &header->direntries[LUMP_LEAFS];
@ -1010,7 +1062,7 @@ void render_visible_faces(ta_parameter_writer& writer, const mat4x4& trans, cons
} }
assert(bb_leaf != NULL); assert(bb_leaf != NULL);
uint32_t color = 0x8000ff16; //uint32_t color = 0x8000ff16;
//render_bounding_box_mm(writer, trans, bb_leaf->maxs, bb_leaf->mins, color); //render_bounding_box_mm(writer, trans, bb_leaf->maxs, bb_leaf->mins, color);
render_leaf_faces(writer, trans, bb_leaf); render_leaf_faces(writer, trans, bb_leaf);
@ -1028,7 +1080,7 @@ void render_visible_faces(ta_parameter_writer& writer, const mat4x4& trans, cons
int x = leaf->cluster; int x = leaf->cluster;
bool visible = (visdata->vecs[x * visdata->sz_vecs + y / 8] & (1 << (y % 8))) != 0; bool visible = (visdata->vecs[x * visdata->sz_vecs + y / 8] & (1 << (y % 8))) != 0;
if (visible) { if (visible) {
uint32_t color = 0x40ff00e6; //uint32_t color = 0x40ff00e6;
//render_bounding_box_mm(writer, trans, leaf->maxs, leaf->mins, color); //render_bounding_box_mm(writer, trans, leaf->maxs, leaf->mins, color);
render_leaf_faces(writer, trans, leaf); render_leaf_faces(writer, trans, leaf);
} }
@ -1037,7 +1089,7 @@ void render_visible_faces(ta_parameter_writer& writer, const mat4x4& trans, cons
void transfer_scene(ta_parameter_writer& writer, const mat4x4& screen_trans, const mat4x4& screen_trans_inv) void transfer_scene(ta_parameter_writer& writer, const mat4x4& screen_trans, const mat4x4& screen_trans_inv)
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
const mat4x4 trans = screen_trans; const mat4x4 trans = screen_trans;
@ -1057,7 +1109,7 @@ void transfer_scene(ta_parameter_writer& writer, const mat4x4& screen_trans, con
//render_zero_position(writer, screen_trans_inv); //render_zero_position(writer, screen_trans_inv);
vec3 pos = screen_trans_inv * (vec3){0, 0, 0}; vec3 pos = screen_trans_inv * (vec3){0, 0, 0};
type7_tri_count = 0; type5_tri_count = 0;
vis_tri_count = 0; vis_tri_count = 0;
for (int i = 0; i < face_count; i++) face_cache[i] = 0; for (int i = 0; i < face_count; i++) face_cache[i] = 0;
render_visible_faces(writer, trans, pos); render_visible_faces(writer, trans, pos);
@ -1213,7 +1265,7 @@ mat4x4 update_analog(const mat4x4& screen)
0, 0, 0, 1, 0, 0, 0, 1,
}; };
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_bsp_20kdm2_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf); q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
//q3bsp_direntry * le = &header->direntries[LUMP_LEAFS]; //q3bsp_direntry * le = &header->direntries[LUMP_LEAFS];
//int num_leaves = le->length / (sizeof (struct q3bsp_leaf)); //int num_leaves = le->length / (sizeof (struct q3bsp_leaf));

View File

@ -4,7 +4,7 @@
namespace geometry { namespace geometry {
template <int L, typename T> template <typename T, int L>
constexpr inline constexpr inline
T line_plane_intersection_d(const vec<L, T>& plane_point, // p0 T line_plane_intersection_d(const vec<L, T>& plane_point, // p0
const vec<L, T>& plane_normal, // n const vec<L, T>& plane_normal, // n
@ -19,7 +19,7 @@ T line_plane_intersection_d(const vec<L, T>& plane_point, // p0
return intersection; return intersection;
} }
template <int L, typename T> template <typename T, int L>
constexpr inline constexpr inline
vec<L, T> line_plane_intersection(const vec<L, T>& plane_point, // p0 vec<L, T> line_plane_intersection(const vec<L, T>& plane_point, // p0
const vec<L, T>& plane_normal, // n const vec<L, T>& plane_normal, // n
@ -34,32 +34,19 @@ vec<L, T> line_plane_intersection(const vec<L, T>& plane_point, // p0
return line_start + line_vector * intersection; return line_start + line_vector * intersection;
} }
template <int L, typename T, int M> template <typename T, int L>
constexpr inline constexpr inline
std::tuple<vec<L, T>, vec<M, T>> line_plane_intersection_two_lines(const vec<L, T>& plane_point, // p0 vec<L, T> interpolate(const vec<L, T>& line_start,
const vec<L, T>& plane_normal, // n const vec<L, T>& line_end,
const vec<L, T>& line_start, // l0 T intersection
const vec<L, T>& line_end, )
const vec<M, T>& line2_start,
const vec<M, T>& line2_end
)
{ {
/* it is assumed that line and line2 are the same line, but in different
coordinates spaces. It is therefore possible to re-use the same
interpolation value on either line vector.
*/
const auto line_vector = line_end - line_start; // l const auto line_vector = line_end - line_start; // l
const auto line2_vector = line2_end - line2_start;
const T intersection = line_plane_intersection_d(plane_point, plane_normal, line_start, line_vector); // d return line_start + line_vector * intersection;
return { line_start + line_vector * intersection
, line2_start + line2_vector * intersection
};
} }
template <int L, typename T> template <typename T, int L>
T clip_boundary(const vec<L, T>& plane_point, // X T clip_boundary(const vec<L, T>& plane_point, // X
const vec<L, T>& plane_normal, // Nc const vec<L, T>& plane_normal, // Nc
const vec<L, T>& line_point const vec<L, T>& line_point
@ -74,7 +61,7 @@ inline T positive_modulo(T a, T b)
return (a % b + b) % b; return (a % b + b) % b;
} }
template <int polygon_len, int L, typename T> template <int polygon_len, typename T, int L>
inline int clip_polygon1(vec<L, T> * output, inline int clip_polygon1(vec<L, T> * output,
const vec<L, T> plane_point, const vec<L, T> plane_point,
const vec<L, T> plane_normal, const vec<L, T> plane_normal,
@ -86,7 +73,7 @@ inline int clip_polygon1(vec<L, T> * output,
const vec<L, T>& s = polygon[ix_s]; const vec<L, T>& s = polygon[ix_s];
const vec<L, T>& f = polygon[ix_f]; const vec<L, T>& f = polygon[ix_f];
bool this_inside = 0.f < clip_boundary<L, T>(plane_point, bool this_inside = 0.f < clip_boundary<T, L>(plane_point,
plane_normal, plane_normal,
f); f);
@ -98,7 +85,7 @@ inline int clip_polygon1(vec<L, T> * output,
case 0b01: // I, F case 0b01: // I, F
length = 2; length = 2;
{ {
const auto i = line_plane_intersection<L, T>(plane_point, plane_normal, s, f); const auto i = line_plane_intersection<T, L>(plane_point, plane_normal, s, f);
*output++ = i; *output++ = i;
*output++ = f; *output++ = f;
} }
@ -106,7 +93,7 @@ inline int clip_polygon1(vec<L, T> * output,
case 0b10: // I case 0b10: // I
length = 1; length = 1;
{ {
const auto i = line_plane_intersection<L, T>(plane_point, plane_normal, s, f); const auto i = line_plane_intersection<T, L>(plane_point, plane_normal, s, f);
*output++ = i; *output++ = i;
} }
break; break;
@ -119,7 +106,7 @@ inline int clip_polygon1(vec<L, T> * output,
bool end_of_polygon = ix_f == (polygon_len - 1); bool end_of_polygon = ix_f == (polygon_len - 1);
if (!end_of_polygon) { if (!end_of_polygon) {
return length + return length +
clip_polygon1<polygon_len, L, T>(output, clip_polygon1<polygon_len, T, L>(output,
plane_point, plane_point,
plane_normal, plane_normal,
polygon, polygon,
@ -142,11 +129,11 @@ int clip_polygon(vec<L, T> * output,
// It would be nice to remove the extra dot product, but the // It would be nice to remove the extra dot product, but the
// alternative seems likely uglier. // alternative seems likely uglier.
bool this_inside = 0.f < clip_boundary<L, T>(plane_point, bool this_inside = 0.f < clip_boundary<T, L>(plane_point,
plane_normal, plane_normal,
f); f);
return clip_polygon1<polygon_len, L, T>(output, return clip_polygon1<polygon_len, T, L>(output,
plane_point, plane_point,
plane_normal, plane_normal,
polygon, polygon,
@ -155,104 +142,219 @@ int clip_polygon(vec<L, T> * output,
this_inside); this_inside);
} }
template <int polygon_len, int L, typename T, int M> template <int polygon_len, typename T, int L, int M>
inline int clip_polygon1_uv(vec<L, T> * output, inline int clip_polygon1_2(vec<L, T> * output_1,
vec<M, T> * output_uv, vec<M, T> * output_2,
const vec<L, T> plane_point, const vec<L, T> plane_point,
const vec<L, T> plane_normal, const vec<L, T> plane_normal,
const vec<L, T> * polygon, const vec<L, T> * polygon_1,
const vec<M, T> * polygon_uv, const vec<M, T> * polygon_2,
const int ix_s, const int ix_s,
const int ix_f, const int ix_f,
const bool last_inside) const bool last_inside)
{ {
const vec<L, T>& s = polygon[ix_s]; const vec<L, T>& s_1 = polygon_1[ix_s];
const vec<L, T>& f = polygon[ix_f]; const vec<L, T>& f_1 = polygon_1[ix_f];
const vec<M, T>& s_uv = polygon_uv[ix_s]; const vec<M, T>& s_2 = polygon_2[ix_s];
const vec<M, T>& f_uv = polygon_uv[ix_f]; const vec<M, T>& f_2 = polygon_2[ix_f];
bool this_inside = 0.f < clip_boundary<L, T>(plane_point, bool this_inside = 0.f < clip_boundary<T, L>(plane_point,
plane_normal, plane_normal,
f); f_1);
int length = 0; int length = 0;
switch ((last_inside << 1) | (this_inside << 0)) { int control = (last_inside << 1) | (this_inside << 0);
switch (control) {
case 0b00: // no output case 0b00: // no output
length = 0;
break;
case 0b01: // I, F
length = 2;
{
auto [i, i_uv] = line_plane_intersection_two_lines<L, T, M>(plane_point, plane_normal,
s, f,
s_uv, f_uv);
*output++ = i;
*output_uv++ = i_uv;
*output++ = f;
*output_uv++ = f_uv;
}
break; break;
case 0b10: // I case 0b10: // I
length = 1; [[fallthrough]];
case 0b01: // I, F
{ {
auto [i, i_uv] = line_plane_intersection_two_lines<L, T, M>(plane_point, plane_normal, const auto& i_1_start = s_1;
s, f, const auto i_1_vector = f_1 - s_1; // l
s_uv, f_uv); const T intersection = line_plane_intersection_d<T, L>(plane_point, plane_normal,
*output++ = i; i_1_start, i_1_vector);
*output_uv++ = i_uv; const vec<L, T> i_1 = i_1_start + i_1_vector * intersection;
*output_1++ = i_1;
*output_2++ = interpolate(s_2, f_2, intersection);
if (control == 0b01) { // I, F
*output_1++ = f_1;
*output_2++ = f_2;
length = 2;
} else {
length = 1;
}
} }
break; break;
case 0b11: // F case 0b11: // F
*output_1++ = f_1;
*output_2++ = f_2;
length = 1; length = 1;
*output++ = f;
*output_uv++ = f_uv;
break; break;
} }
bool end_of_polygon = ix_f == (polygon_len - 1); bool end_of_polygon = ix_f == (polygon_len - 1);
if (!end_of_polygon) { if (!end_of_polygon) {
return length + return length +
clip_polygon1_uv<polygon_len, L, T, M>(output, clip_polygon1_2<polygon_len, T, L, M>(output_1,
output_uv, output_2,
plane_point, plane_point,
plane_normal, plane_normal,
polygon, polygon_1,
polygon_uv, polygon_2,
ix_f, ix_f,
ix_f + 1, ix_f + 1,
this_inside); this_inside);
} else { } else {
return length; return length;
} }
} }
template <int polygon_len, int L, typename T, int M> template <int polygon_len, typename T, int L, int M>
int clip_polygon_uv(vec<L, T> * output, int clip_polygon_2(vec<L, T> * output_1,
vec<M, T> * output_uv, vec<M, T> * output_2,
const vec<L, T>& plane_point, const vec<L, T>& plane_point,
const vec<L, T>& plane_normal, const vec<L, T>& plane_normal,
const vec<L, T> * polygon, const vec<L, T> * polygon_1,
const vec<M, T> * polygon_uv const vec<M, T> * polygon_2
) )
{ {
const vec<L, T> f = polygon[polygon_len - 1]; const vec<L, T> f = polygon_1[polygon_len - 1];
// It would be nice to remove the extra dot product, but the // It would be nice to remove the extra dot product, but the
// alternative seems likely uglier. // alternative seems likely uglier.
bool this_inside = 0.f < clip_boundary<L, T>(plane_point, bool this_inside = 0.f < clip_boundary<T, L>(plane_point,
plane_normal, plane_normal,
f); f);
return clip_polygon1_uv<polygon_len, L, T, M>(output, return clip_polygon1_2<polygon_len, T, L, M>(output_1,
output_uv, output_2,
plane_point, plane_point,
plane_normal, plane_normal,
polygon, polygon_1,
polygon_uv, polygon_2,
polygon_len - 1, // ix_s polygon_len - 1, // ix_s
0, // ix_f 0, // ix_f
this_inside); this_inside);
}
template <int polygon_len, typename T, int L, int M, int N>
inline int clip_polygon1_3(vec<L, T> * output_1,
vec<M, T> * output_2,
vec<N, T> * output_3,
const vec<L, T> plane_point,
const vec<L, T> plane_normal,
const vec<L, T> * polygon_1,
const vec<M, T> * polygon_2,
const vec<N, T> * polygon_3,
const int ix_s,
const int ix_f,
const bool last_inside)
{
const vec<L, T>& s_1 = polygon_1[ix_s];
const vec<L, T>& f_1 = polygon_1[ix_f];
const vec<M, T>& s_2 = polygon_2[ix_s];
const vec<M, T>& f_2 = polygon_2[ix_f];
const vec<N, T>& s_3 = polygon_3[ix_s];
const vec<N, T>& f_3 = polygon_3[ix_f];
bool this_inside = 0.f < clip_boundary<T, L>(plane_point,
plane_normal,
f_1);
int length = 0;
int control = (last_inside << 1) | (this_inside << 0);
switch (control) {
case 0b00: // no output
length = 0;
break;
case 0b10: // I
[[fallthrough]];
case 0b01: // I, F
{
const auto& i_1_start = s_1;
const auto i_1_vector = f_1 - s_1; // l
const T intersection = line_plane_intersection_d<T, L>(plane_point, plane_normal,
i_1_start, i_1_vector);
const vec<L, T> i_1 = i_1_start + i_1_vector * intersection;
*output_1++ = i_1;
*output_2++ = interpolate(s_2, f_2, intersection);
*output_3++ = interpolate(s_3, f_3, intersection);
if (control == 0b01) { // I, F
*output_1++ = f_1;
*output_2++ = f_2;
*output_3++ = f_3;
length = 2;
} else {
length = 1;
}
}
break;
case 0b11: // F
*output_1++ = f_1;
*output_2++ = f_2;
*output_3++ = f_3;
length = 1;
break;
}
bool end_of_polygon = ix_f == (polygon_len - 1);
if (!end_of_polygon) {
return length +
clip_polygon1_3<polygon_len, T, L, M, N>(output_1,
output_2,
output_3,
plane_point,
plane_normal,
polygon_1,
polygon_2,
polygon_3,
ix_f,
ix_f + 1,
this_inside);
} else {
return length;
}
}
template <int polygon_len, typename T, int L, int M, int N>
int clip_polygon_3(vec<L, T> * output_1,
vec<M, T> * output_2,
vec<N, T> * output_3,
const vec<L, T>& plane_point,
const vec<L, T>& plane_normal,
const vec<L, T> * polygon_1,
const vec<M, T> * polygon_2,
const vec<N, T> * polygon_3
)
{
const vec<L, T> f = polygon_1[polygon_len - 1];
// It would be nice to remove the extra dot product, but the
// alternative seems likely uglier.
bool this_inside = 0.f < clip_boundary<T, L>(plane_point,
plane_normal,
f);
return clip_polygon1_3<polygon_len, T, L, M>(output_1,
output_2,
output_3,
plane_point,
plane_normal,
polygon_1,
polygon_2,
polygon_3,
polygon_len - 1, // ix_s
0, // ix_f
this_inside);
} }
} }

View File

@ -36,10 +36,8 @@ void print_direntries(struct q3bsp_header * header)
} }
} }
void print_header(void * buf) void print_header(struct q3bsp_header * header)
{ {
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
printf("magic: "); printf("magic: ");
putchar(header->magic[0]); putchar(header->magic[0]);
putchar(header->magic[1]); putchar(header->magic[1]);
@ -51,27 +49,31 @@ void print_header(void * buf)
print_direntries(header); print_direntries(header);
} }
void print_textures(void * buf, int length) void print_textures(uint8_t * buf, struct q3bsp_header * header)
{ {
q3bsp_texture_t * texture = reinterpret_cast<q3bsp_texture_t *>(buf); q3bsp_direntry * te = &header->direntries[LUMP_TEXTURES];
q3bsp_texture_t * textures = reinterpret_cast<q3bsp_texture_t *>(&buf[te->offset]);
int count = length / (sizeof (struct q3bsp_texture)); int count = te->length / (sizeof (struct q3bsp_texture));
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
q3bsp_texture_t * texture = &textures[i];
printf("texture [%d]\n", i); printf("texture [%d]\n", i);
printf(" name=%s\n", texture[i].name); printf(" name=%s\n", texture->name);
printf(" flags=%x\n", texture[i].flags); printf(" flags=%x\n", texture->flags);
printf(" contents=%x\n", texture[i].contents); printf(" contents=%x\n", texture->contents);
} }
} }
void print_models(void * buf, int length) void print_models(uint8_t * buf, struct q3bsp_header * header)
{ {
q3bsp_model_t * model = reinterpret_cast<q3bsp_model_t *>(buf); q3bsp_direntry * me = &header->direntries[LUMP_MODELS];
q3bsp_model_t * models = reinterpret_cast<q3bsp_model_t *>(&buf[me->offset]);
int count = length / (sizeof (struct q3bsp_model)); int count = me->length / (sizeof (struct q3bsp_model));
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
q3bsp_model_t * model = &models[i];
printf("model [%d]\n", i); printf("model [%d]\n", i);
printf(" mins={%f, %f, %f}\n", model->mins[0], model->mins[2], model->mins[2]); printf(" mins={%f, %f, %f}\n", model->mins[0], model->mins[2], model->mins[2]);
printf(" maxs={%f, %f, %f}\n", model->maxs[0], model->maxs[2], model->maxs[2]); printf(" maxs={%f, %f, %f}\n", model->maxs[0], model->maxs[2], model->maxs[2]);
@ -82,40 +84,71 @@ void print_models(void * buf, int length)
} }
} }
void print_faces(void * buf, int length) void print_vertexes(uint8_t * buf, struct q3bsp_header * header)
{ {
q3bsp_face_t * face = reinterpret_cast<q3bsp_face_t *>(buf); q3bsp_direntry * ve = &header->direntries[LUMP_VERTEXES];
q3bsp_vertex_t * vertexes = reinterpret_cast<q3bsp_vertex_t *>(&buf[ve->offset]);
int count = length / (sizeof (struct q3bsp_face)); int count = ve->length / (sizeof (struct q3bsp_vertex));
printf("vertexes count: %d\n", count);
for (int i = 0; i < count; i++) {
q3bsp_vertex_t * vertex = &vertexes[i];
printf("vertex [%d]: lightmapcoord=(%f %f)\n", i, vertex->lightmapcoord[0], vertex->lightmapcoord[1]);
//assert(vertex->lightmapcoord[0] >= 0.0 && vertex->lightmapcoord[0] <= 1.0);
//assert(vertex->lightmapcoord[1] >= 0.0 && vertex->lightmapcoord[1] <= 1.0);
}
}
void print_faces(uint8_t * buf, struct q3bsp_header * header)
{
q3bsp_direntry * fe = &header->direntries[LUMP_FACES];
q3bsp_face_t * faces = reinterpret_cast<q3bsp_face_t *>(&buf[fe->offset]);
int count = fe->length / (sizeof (struct q3bsp_face));
printf("faces count: %d\n", count); printf("faces count: %d\n", count);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
q3bsp_face_t * face = &faces[i];
printf("face [%d]\n", i); printf("face [%d]\n", i);
printf(" type=%d n_vertexes=%d n_meshverts=%d texture=%d\n", face[i].type, face[i].n_vertexes, face[i].n_meshverts, face[i].texture); printf(" type=%d n_vertexes=%d n_meshverts=%d texture=%d lightmap=%d\n", face->type, face->n_vertexes, face->n_meshverts, face->texture, face->lm_index);
} }
} }
void print_lightmaps(uint8_t * buf, struct q3bsp_header * header)
{
q3bsp_direntry * lme = &header->direntries[LUMP_LIGHTMAPS];
q3bsp_lightmap_t * lightmaps = reinterpret_cast<q3bsp_lightmap_t *>(&buf[lme->offset]);
int count = lme->length / (sizeof (struct q3bsp_lightmap));
printf("lightmaps count: %d offset: %d\n", count, lme->offset);
}
void debug_print_q3bsp(uint8_t * buf, q3bsp_header_t * header) void debug_print_q3bsp(uint8_t * buf, q3bsp_header_t * header)
{ {
// header // header
//print_header(buf); //print_header(header);
if (0) { if (0) {
q3bsp_direntry * e = &header->direntries[LUMP_TEXTURES]; print_textures(buf, header);
print_textures(&buf[e->offset], e->length);
} }
if (0) { if (0) {
q3bsp_direntry * e = &header->direntries[LUMP_MODELS]; print_models(buf, header);
print_models(&buf[e->offset], e->length); }
if (1) {
print_vertexes(buf, header);
}
if (1) {
print_faces(buf, header);
}
if (1) {
print_lightmaps(buf, header);
} }
if (0) { if (0) {
q3bsp_direntry * e = &header->direntries[LUMP_FACES];
print_faces(&buf[e->offset], e->length);
}
{
q3bsp_direntry * fe = &header->direntries[LUMP_FACES]; q3bsp_direntry * fe = &header->direntries[LUMP_FACES];
q3bsp_face_t * faces = reinterpret_cast<q3bsp_face_t *>(&buf[fe->offset]); q3bsp_face_t * faces = reinterpret_cast<q3bsp_face_t *>(&buf[fe->offset]);
int face_count = fe->length / (sizeof (struct q3bsp_face)); int face_count = fe->length / (sizeof (struct q3bsp_face));