20kdm2: add bezier patch rendering
This commit is contained in:
parent
bbb3b8f8a3
commit
f7abfa14cf
@ -71,6 +71,7 @@
|
|||||||
#include "bsp/20kdm2/textures/sfx/flame8.data.h"
|
#include "bsp/20kdm2/textures/sfx/flame8.data.h"
|
||||||
|
|
||||||
#include "q3bsp/q3bsp.h"
|
#include "q3bsp/q3bsp.h"
|
||||||
|
#include "q3bsp/q3bsp_patch.hpp"
|
||||||
#include "bsp/20kdm2/maps/20kdm2.bsp.h"
|
#include "bsp/20kdm2/maps/20kdm2.bsp.h"
|
||||||
#include "bsp/20kdm2/texture.h"
|
#include "bsp/20kdm2/texture.h"
|
||||||
|
|
||||||
@ -252,7 +253,7 @@ void global_polygon_type_4(ta_parameter_writer& writer,
|
|||||||
;
|
;
|
||||||
|
|
||||||
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
|
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
|
||||||
| isp_tsp_instruction_word::culling_mode::cull_if_negative
|
| isp_tsp_instruction_word::culling_mode::no_culling // cull_if_negative
|
||||||
;
|
;
|
||||||
|
|
||||||
const uint32_t tsp_instruction_word = tsp_instruction_word::fog_control::no_fog
|
const uint32_t tsp_instruction_word = tsp_instruction_word::fog_control::no_fog
|
||||||
@ -601,7 +602,7 @@ float light_intensity(vec3 light_vec, vec3 n)
|
|||||||
|
|
||||||
static vec3 light_vec = {20, -20, -20};
|
static vec3 light_vec = {20, -20, -20};
|
||||||
|
|
||||||
static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * face, int * last_texture, int * last_lm_index)
|
static inline void transfer_face_meshverts(ta_parameter_writer& writer, q3bsp_face_t * face)
|
||||||
{
|
{
|
||||||
uint8_t * buf = reinterpret_cast<uint8_t *>(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);
|
||||||
@ -617,26 +618,6 @@ static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * fac
|
|||||||
|
|
||||||
int triangles = face->n_meshverts / 3;
|
int triangles = face->n_meshverts / 3;
|
||||||
|
|
||||||
int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
|
|
||||||
|
|
||||||
bool has_texture = 1 &&
|
|
||||||
(face->texture >= 0) &&
|
|
||||||
(face->texture < textures_length) &&
|
|
||||||
(textures[face->texture].size != 0);
|
|
||||||
|
|
||||||
if (!has_texture)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (face->texture != *last_texture || face->lm_index != *last_lm_index) {
|
|
||||||
*last_texture = face->texture;
|
|
||||||
*last_lm_index = face->lm_index;
|
|
||||||
if (has_texture) {
|
|
||||||
global_texture_lightmap(writer, face->texture, face->lm_index);
|
|
||||||
} else {
|
|
||||||
//global_polygon_type_1(writer, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < triangles; j++) {
|
for (int j = 0; j < triangles; j++) {
|
||||||
|
|
||||||
int aix = mv[j * 3 + 0].offset + face->vertex;
|
int aix = mv[j * 3 + 0].offset + face->vertex;
|
||||||
@ -657,60 +638,133 @@ static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * fac
|
|||||||
float li0 = light_intensity(light_vec, n);
|
float li0 = light_intensity(light_vec, n);
|
||||||
const float li1 = 2.0;
|
const float li1 = 2.0;
|
||||||
|
|
||||||
if (has_texture) {
|
float v_mul = textures[face->texture].v_mul;
|
||||||
float v_mul = textures[face->texture].v_mul;
|
vec2 at = {vert[aix].texture[0], vert[aix].texture[1] * v_mul};
|
||||||
vec2 at = {vert[aix].texcoord[0], vert[aix].texcoord[1] * v_mul};
|
vec2 bt = {vert[bix].texture[0], vert[bix].texture[1] * v_mul};
|
||||||
vec2 bt = {vert[bix].texcoord[0], vert[bix].texcoord[1] * v_mul};
|
vec2 ct = {vert[cix].texture[0], vert[cix].texture[1] * v_mul};
|
||||||
vec2 ct = {vert[cix].texcoord[0], vert[cix].texcoord[1] * v_mul};
|
|
||||||
|
|
||||||
vec2 alm = {vert[aix].lightmapcoord[0], vert[aix].lightmapcoord[1]};
|
vec2 alm = {vert[aix].lightmap[0], vert[aix].lightmap[1]};
|
||||||
vec2 blm = {vert[bix].lightmapcoord[0], vert[bix].lightmapcoord[1]};
|
vec2 blm = {vert[bix].lightmap[0], vert[bix].lightmap[1]};
|
||||||
vec2 clm = {vert[cix].lightmapcoord[0], vert[cix].lightmapcoord[1]};
|
vec2 clm = {vert[cix].lightmap[0], vert[cix].lightmap[1]};
|
||||||
|
|
||||||
if (ap.z < 0 || bp.z < 0 || cp.z < 0) {
|
if (ap.z < 0 || bp.z < 0 || cp.z < 0) {
|
||||||
render_clip_tri_type_13(writer,
|
render_clip_tri_type_13(writer,
|
||||||
ap,
|
ap,
|
||||||
bp,
|
bp,
|
||||||
cp,
|
cp,
|
||||||
at,
|
at,
|
||||||
bt,
|
bt,
|
||||||
ct,
|
ct,
|
||||||
alm,
|
alm,
|
||||||
blm,
|
blm,
|
||||||
clm,
|
clm,
|
||||||
li0,
|
li0,
|
||||||
li1);
|
li1);
|
||||||
} else {
|
|
||||||
vec3 aps = screen_transform(ap);
|
|
||||||
vec3 bps = screen_transform(bp);
|
|
||||||
vec3 cps = screen_transform(cp);
|
|
||||||
|
|
||||||
render_tri_type_13(writer,
|
|
||||||
aps,
|
|
||||||
bps,
|
|
||||||
cps,
|
|
||||||
at,
|
|
||||||
bt,
|
|
||||||
ct,
|
|
||||||
alm,
|
|
||||||
blm,
|
|
||||||
clm,
|
|
||||||
li0,
|
|
||||||
li1);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
vec3 aps = screen_transform(ap);
|
||||||
render_tri_type_2(writer,
|
vec3 bps = screen_transform(bp);
|
||||||
screen_transform(ap),
|
vec3 cps = screen_transform(cp);
|
||||||
screen_transform(bp),
|
|
||||||
screen_transform(cp),
|
render_tri_type_13(writer,
|
||||||
li);
|
aps,
|
||||||
*/
|
bps,
|
||||||
|
cps,
|
||||||
|
at,
|
||||||
|
bt,
|
||||||
|
ct,
|
||||||
|
alm,
|
||||||
|
blm,
|
||||||
|
clm,
|
||||||
|
li0,
|
||||||
|
li1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void transfer_faces(ta_parameter_writer& writer)
|
static inline void transfer_face_patch_surfaces(ta_parameter_writer& writer, const mat4x4& trans, q3bsp_face_t * face, int face_ix)
|
||||||
|
{
|
||||||
|
using namespace q3bsp_patch;
|
||||||
|
|
||||||
|
patch * patch = NULL;
|
||||||
|
for (int i = 0; i < patch_count; i++) {
|
||||||
|
if (patches[i].face_ix == face_ix) {
|
||||||
|
patch = &patches[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(patch != nullptr);
|
||||||
|
|
||||||
|
const int width = face->size[0];
|
||||||
|
const int height = face->size[1];
|
||||||
|
const int h_surfaces = (width - 1) / 2;
|
||||||
|
const int v_surfaces = (height - 1) / 2;
|
||||||
|
const int surface_count = h_surfaces * v_surfaces;
|
||||||
|
assert(surface_count > 0);
|
||||||
|
|
||||||
|
const vertex_plm * vertices = &patch_vertices[patch->vertex_ix];
|
||||||
|
const bezier::triangle * triangles = &patch_triangles[patch->triangle_ix];
|
||||||
|
|
||||||
|
const int triangle_count = surface_count * triangles_per_surface;
|
||||||
|
for (int i = 0; i < triangle_count; i++) {
|
||||||
|
vis_tri_count += 1;
|
||||||
|
|
||||||
|
const bezier::triangle * triangle = &triangles[i];
|
||||||
|
assert(triangle->a >= 0 && triangle->b >= 0 && triangle->c >= 0);
|
||||||
|
if (triangle->a == triangle->b && triangle->b == triangle->c) {
|
||||||
|
printf("face_ix %d %d\n", face_ix, i);
|
||||||
|
printf(" %d %d %d\n", triangle->a, triangle->b, triangle->c);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vertex_plm * av = &vertices[triangle->a];
|
||||||
|
const vertex_plm * bv = &vertices[triangle->b];
|
||||||
|
const vertex_plm * cv = &vertices[triangle->c];
|
||||||
|
|
||||||
|
vec3 ap = trans * av->l;
|
||||||
|
vec3 bp = trans * bv->l;
|
||||||
|
vec3 cp = trans * cv->l;
|
||||||
|
|
||||||
|
if (ap.z < 0 || bp.z < 0 || cp.z < 0) {
|
||||||
|
continue;
|
||||||
|
//printf("cont %f %f %f\n", ap.x, ap.y, ap.z);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
printf("%f %f %f\n", ap.x, ap.y, ap.z);
|
||||||
|
printf("%f %f %f\n", bp.x, bp.y, bp.z);
|
||||||
|
printf("%f %f %f\n", cp.x, cp.y, cp.z);
|
||||||
|
*/
|
||||||
|
|
||||||
|
vec3 aps = screen_transform(ap);
|
||||||
|
vec3 bps = screen_transform(bp);
|
||||||
|
vec3 cps = screen_transform(cp);
|
||||||
|
|
||||||
|
const vec2& at = av->m;
|
||||||
|
const vec2& bt = bv->m;
|
||||||
|
const vec2& ct = cv->m;
|
||||||
|
|
||||||
|
const vec2& alm = av->n;
|
||||||
|
const vec2& blm = bv->n;
|
||||||
|
const vec2& clm = cv->n;
|
||||||
|
|
||||||
|
float li0 = 1.0;
|
||||||
|
float li1 = 2.0;
|
||||||
|
|
||||||
|
render_tri_type_13(writer,
|
||||||
|
aps,
|
||||||
|
bps,
|
||||||
|
cps,
|
||||||
|
at,
|
||||||
|
bt,
|
||||||
|
ct,
|
||||||
|
alm,
|
||||||
|
blm,
|
||||||
|
clm,
|
||||||
|
li0,
|
||||||
|
li1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer_faces(ta_parameter_writer& writer, const mat4x4& trans)
|
||||||
{
|
{
|
||||||
uint8_t * buf = reinterpret_cast<uint8_t *>(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);
|
||||||
@ -723,8 +777,30 @@ void transfer_faces(ta_parameter_writer& writer)
|
|||||||
int last_texture = -1;
|
int last_texture = -1;
|
||||||
int last_lm_index = -1;
|
int last_lm_index = -1;
|
||||||
|
|
||||||
|
const int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
|
||||||
|
|
||||||
for (int i = 0; i < face_count; i++) {
|
for (int i = 0; i < face_count; i++) {
|
||||||
transfer_face(writer, &faces[i], &last_texture, &last_lm_index);
|
q3bsp_face_t * face = &faces[i];
|
||||||
|
|
||||||
|
bool has_texture =
|
||||||
|
(face->texture >= 0) &&
|
||||||
|
(face->texture < textures_length) &&
|
||||||
|
(textures[face->texture].size != 0);
|
||||||
|
|
||||||
|
if (!has_texture)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (face->texture != last_texture || face->lm_index != last_lm_index) {
|
||||||
|
last_texture = face->texture;
|
||||||
|
last_lm_index = face->lm_index;
|
||||||
|
|
||||||
|
global_texture_lightmap(writer, face->texture, face->lm_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (face->type == FACE_TYPE_POLYGON || face->type == FACE_TYPE_MESH)
|
||||||
|
transfer_face_meshverts(writer, face);
|
||||||
|
if (face->type == FACE_TYPE_PATCH)
|
||||||
|
transfer_face_patch_surfaces(writer, trans, face, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,9 +879,9 @@ static inline void transfer_face_billboard(ta_parameter_writer& writer, q3bsp_fa
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 at = {vert[aix].texcoord[0], vert[aix].texcoord[1]};
|
vec2 at = {vert[aix].texture[0], vert[aix].texture[1]};
|
||||||
vec2 bt = {vert[bix].texcoord[0], vert[bix].texcoord[1]};
|
vec2 bt = {vert[bix].texture[0], vert[bix].texture[1]};
|
||||||
vec2 ct = {vert[cix].texcoord[0], vert[cix].texcoord[1]};
|
vec2 ct = {vert[cix].texture[0], vert[cix].texture[1]};
|
||||||
|
|
||||||
render_tri_type_7(writer,
|
render_tri_type_7(writer,
|
||||||
screen_transform(ap),
|
screen_transform(ap),
|
||||||
@ -1250,12 +1326,35 @@ void render_leaf_faces(ta_parameter_writer& writer, const mat4x4& trans, q3bsp_l
|
|||||||
int last_texture = -1;
|
int last_texture = -1;
|
||||||
int last_lm_index = -1;
|
int last_lm_index = -1;
|
||||||
|
|
||||||
|
const int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
|
||||||
|
|
||||||
for (int i = 0; i < leaf->n_leaffaces; i++) {
|
for (int i = 0; i < leaf->n_leaffaces; i++) {
|
||||||
int face_ix = lf[i].face;
|
int face_ix = lf[i].face;
|
||||||
if (face_cache[face_ix] != 0)
|
if (face_cache[face_ix] != 0)
|
||||||
continue;
|
continue;
|
||||||
face_cache[face_ix] = 1;
|
face_cache[face_ix] = 1;
|
||||||
transfer_face(writer, &faces[face_ix], &last_texture, &last_lm_index);
|
|
||||||
|
q3bsp_face_t * face = &faces[face_ix];
|
||||||
|
|
||||||
|
bool has_texture =
|
||||||
|
(face->texture >= 0) &&
|
||||||
|
(face->texture < textures_length) &&
|
||||||
|
(textures[face->texture].size != 0);
|
||||||
|
|
||||||
|
if (!has_texture)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (face->texture != last_texture || face->lm_index != last_lm_index) {
|
||||||
|
last_texture = face->texture;
|
||||||
|
last_lm_index = face->lm_index;
|
||||||
|
|
||||||
|
global_texture_lightmap(writer, face->texture, face->lm_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (face->type == FACE_TYPE_POLYGON || face->type == FACE_TYPE_MESH)
|
||||||
|
transfer_face_meshverts(writer, face);
|
||||||
|
if (face->type == FACE_TYPE_PATCH)
|
||||||
|
transfer_face_patch_surfaces(writer, trans, face, face_ix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1398,7 +1497,7 @@ void transfer_scene(ta_parameter_writer& writer, const mat4x4& screen_trans, con
|
|||||||
q3bsp_direntry * fe = &header->direntries[LUMP_FACES];
|
q3bsp_direntry * fe = &header->direntries[LUMP_FACES];
|
||||||
int face_count = fe->length / (sizeof (struct q3bsp_face));
|
int face_count = fe->length / (sizeof (struct q3bsp_face));
|
||||||
|
|
||||||
//transfer_faces(writer);
|
//transfer_faces(writer, trans);
|
||||||
//transfer_icosphere(writer, trans);
|
//transfer_icosphere(writer, trans);
|
||||||
|
|
||||||
//render_matrix(writer, screen_trans);
|
//render_matrix(writer, screen_trans);
|
||||||
@ -1548,7 +1647,8 @@ void transfer_textures()
|
|||||||
|
|
||||||
printf("lightmap base: %d\n", lightmap_base);
|
printf("lightmap base: %d\n", lightmap_base);
|
||||||
|
|
||||||
int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
|
const int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
|
||||||
|
|
||||||
for (int i = 0; i < textures_length; i++) {
|
for (int i = 0; i < textures_length; i++) {
|
||||||
uint32_t offset = texture_memory_alloc.texture.start + font_base + lightmap_base + textures[i].offset;
|
uint32_t offset = texture_memory_alloc.texture.start + font_base + lightmap_base + textures[i].offset;
|
||||||
void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]);
|
void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]);
|
||||||
@ -1805,6 +1905,8 @@ int main()
|
|||||||
| isp_feed_cfg::pre_sort_mode
|
| isp_feed_cfg::pre_sort_mode
|
||||||
;
|
;
|
||||||
|
|
||||||
|
holly.FPU_SHAD_SCALE = fpu_shad_scale::simple_shadow_enable::parameter_selection_volume_mode;
|
||||||
|
|
||||||
system.IML6NRM = istnrm::end_of_render_tsp
|
system.IML6NRM = istnrm::end_of_render_tsp
|
||||||
| istnrm::v_blank_in
|
| istnrm::v_blank_in
|
||||||
| istnrm::end_of_transferring_opaque_modifier_volume_list;
|
| istnrm::end_of_transferring_opaque_modifier_volume_list;
|
||||||
@ -1838,9 +1940,10 @@ int main()
|
|||||||
0.0, 0.0, 0.0, 1.0,
|
0.0, 0.0, 0.0, 1.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
do_get_condition();
|
q3bsp_patch::triangulate_patches(bsp_start);
|
||||||
|
printf("patch_count %d\n", q3bsp_patch::patch_count);
|
||||||
|
|
||||||
holly.FPU_SHAD_SCALE = fpu_shad_scale::simple_shadow_enable::parameter_selection_volume_mode;
|
do_get_condition();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
maple::dma_wait_complete();
|
maple::dma_wait_complete();
|
||||||
|
@ -13,6 +13,7 @@ BSP_20KDM2_OBJ = \
|
|||||||
maple/maple.o \
|
maple/maple.o \
|
||||||
font/font_bitmap.o \
|
font/font_bitmap.o \
|
||||||
font/verite_8x16/verite_8x16.data.o \
|
font/verite_8x16/verite_8x16.data.o \
|
||||||
|
q3bsp/q3bsp_patch.o \
|
||||||
bsp/20kdm2/maps/20kdm2.bsp.o \
|
bsp/20kdm2/maps/20kdm2.bsp.o \
|
||||||
bsp/20kdm2/textures/e7/e7walldesign01b.data.o \
|
bsp/20kdm2/textures/e7/e7walldesign01b.data.o \
|
||||||
bsp/20kdm2/textures/e7/e7steptop2.data.o \
|
bsp/20kdm2/textures/e7/e7steptop2.data.o \
|
||||||
|
104
math/bezier.hpp
Normal file
104
math/bezier.hpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "math/vec.hpp"
|
||||||
|
|
||||||
|
namespace bezier {
|
||||||
|
|
||||||
|
template <typename T, int L, int M, int N>
|
||||||
|
struct vec_lmn {
|
||||||
|
vec<L, T> l;
|
||||||
|
vec<M, T> m;
|
||||||
|
vec<N, T> n;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct triangle {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
int c;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, int L, int M, int N>
|
||||||
|
constexpr inline
|
||||||
|
vec_lmn<T, L, M, N>
|
||||||
|
interpolate_quadratic(const T d,
|
||||||
|
const vec<L, T>& l1, const vec<M, T>& m1, const vec<N, T>& n1,
|
||||||
|
const vec<L, T>& l2, const vec<M, T>& m2, const vec<N, T>& n2,
|
||||||
|
const vec<L, T>& l3, const vec<M, T>& m3, const vec<N, T>& n3)
|
||||||
|
{
|
||||||
|
T invd = 1.0 - d;
|
||||||
|
T d1 = invd * invd;
|
||||||
|
T d2 = 2.0 * d * invd;
|
||||||
|
T d3 = d * d;
|
||||||
|
|
||||||
|
vec<L, T> l;
|
||||||
|
for (int i = 0; i < L; i++) {
|
||||||
|
l[i] = l1[i] * d1 + l2[i] * d2 + l3[i] * d3;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec<M, T> m;
|
||||||
|
for (int i = 0; i < M; i++) {
|
||||||
|
m[i] = m1[i] * d1 + m2[i] * d2 + m3[i] * d3;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec<N, T> n;
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
n[i] = n1[i] * d1 + n2[i] * d2 + n3[i] * d3;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {l, m, n};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int L, int M, int N>
|
||||||
|
constexpr inline
|
||||||
|
vec_lmn<T, L, M, N>
|
||||||
|
interpolate_quadratic(const T d,
|
||||||
|
const vec_lmn<T, L, M, N>& va,
|
||||||
|
const vec_lmn<T, L, M, N>& vb,
|
||||||
|
const vec_lmn<T, L, M, N>& vc)
|
||||||
|
{
|
||||||
|
return interpolate_quadratic<T>(d,
|
||||||
|
va.l, va.m, va.n,
|
||||||
|
vb.l, vb.m, vb.n,
|
||||||
|
vc.l, vc.m, vc.n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int L, int M, int N>
|
||||||
|
constexpr inline
|
||||||
|
void
|
||||||
|
tessellate(const int level,
|
||||||
|
const vec_lmn<T, L, M, N> * control, // [9]
|
||||||
|
vec_lmn<T, L, M, N> * vertices, // [2 * level * level]
|
||||||
|
triangle * triangles,
|
||||||
|
int vertex_base = 0)
|
||||||
|
{
|
||||||
|
vec_lmn<T, L, M, N> column[3][level + 1];
|
||||||
|
|
||||||
|
T inv_level = 1.0 / level;
|
||||||
|
for (int i = 0; i <= level; i++) {
|
||||||
|
T d = inv_level * i;
|
||||||
|
column[0][i] = interpolate_quadratic(d, control[0], control[3], control[6]);
|
||||||
|
column[1][i] = interpolate_quadratic(d, control[1], control[4], control[7]);
|
||||||
|
column[2][i] = interpolate_quadratic(d, control[2], control[5], control[8]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i <= level; i++) {
|
||||||
|
for (int j = 0; j <= level; j++) {
|
||||||
|
T d = inv_level * j;
|
||||||
|
*vertices++ = interpolate_quadratic(d, column[0][i], column[1][i], column[2][i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < level; i++) {
|
||||||
|
for (int j = 0; j < level; j++) {
|
||||||
|
int ix = vertex_base + j * (level + 1) + i;
|
||||||
|
*triangles++ = {ix + 0,
|
||||||
|
ix + (level + 1) + 0,
|
||||||
|
ix + (level + 1) + 1};
|
||||||
|
*triangles++ = {ix + 0,
|
||||||
|
ix + (level + 1) + 1,
|
||||||
|
ix + 1};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
#include <tuple>
|
|
||||||
|
|
||||||
#include "vec.hpp"
|
#include "vec.hpp"
|
||||||
|
|
||||||
namespace geometry {
|
namespace geometry {
|
||||||
|
@ -105,15 +105,32 @@ void print_faces(uint8_t * buf, struct q3bsp_header * header)
|
|||||||
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]);
|
||||||
|
|
||||||
|
q3bsp_direntry * ve = &header->direntries[LUMP_VERTEXES];
|
||||||
|
q3bsp_vertex_t * vertexes = reinterpret_cast<q3bsp_vertex_t *>(&buf[ve->offset]);
|
||||||
|
|
||||||
int count = fe->length / (sizeof (struct q3bsp_face));
|
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 face_ix = 0; face_ix < count; face_ix++) {
|
||||||
q3bsp_face_t * face = &faces[i];
|
q3bsp_face_t * face = &faces[face_ix];
|
||||||
if (face->texture == 23 || face->texture == 24 || face->type == 4){
|
if (face->type != 2)
|
||||||
printf("face [%d]\n", i);
|
continue;
|
||||||
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);
|
//printf("face [%d]\n", face_ix);
|
||||||
|
//printf(" type=%d n_vertexes=%d n_meshverts=%d texture=%d lightmap=%d size=(%d,%d)\n", face->type, face->n_vertexes, face->n_meshverts, face->texture, face->lm_index, face->size[0], face->size[1]);
|
||||||
|
|
||||||
|
|
||||||
|
//printf("[");
|
||||||
|
printf("(%d, %d)", face->size[0], face->size[1]);
|
||||||
|
/*
|
||||||
|
for (int i = 0 ; i < face->n_vertexes; i++) {
|
||||||
|
q3bsp_vertex_t * vertex = &vertexes[face->vertex + i];
|
||||||
|
printf("(%.00f,%.00f,%.00f)", (vertex->position[0]), (vertex->position[1]), (vertex->position[2]));
|
||||||
|
if (i < face->n_vertexes - 1)
|
||||||
|
printf(",");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
//printf("],");
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct q3bsp_direntry {
|
typedef struct q3bsp_direntry {
|
||||||
@ -29,7 +31,7 @@ enum q3bsp_lumps {
|
|||||||
LUMP_LIGHTMAPS = 14,
|
LUMP_LIGHTMAPS = 14,
|
||||||
LUMP_LIGHTVOLS = 15,
|
LUMP_LIGHTVOLS = 15,
|
||||||
LUMP_VISDATA = 16,
|
LUMP_VISDATA = 16,
|
||||||
} q3bsp_lumps;
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
typedef struct q3bsp_entity {
|
typedef struct q3bsp_entity {
|
||||||
@ -96,8 +98,8 @@ typedef struct q3bsp_brushside {
|
|||||||
|
|
||||||
typedef struct q3bsp_vertex {
|
typedef struct q3bsp_vertex {
|
||||||
float position[3];
|
float position[3];
|
||||||
float texcoord[2];
|
float texture[2];
|
||||||
float lightmapcoord[2];
|
float lightmap[2];
|
||||||
float normal[3];
|
float normal[3];
|
||||||
uint8_t color[4];
|
uint8_t color[4];
|
||||||
} q3bsp_vertex_t;
|
} q3bsp_vertex_t;
|
||||||
@ -112,10 +114,17 @@ typedef struct q3bsp_effect {
|
|||||||
int unknown;
|
int unknown;
|
||||||
} q3bsp_effect_t;
|
} q3bsp_effect_t;
|
||||||
|
|
||||||
|
enum q3bsp_face_type {
|
||||||
|
FACE_TYPE_POLYGON = 1,
|
||||||
|
FACE_TYPE_PATCH = 2,
|
||||||
|
FACE_TYPE_MESH = 3,
|
||||||
|
FACE_TYPE_BILLBOARD = 4,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct q3bsp_face {
|
typedef struct q3bsp_face {
|
||||||
int texture;
|
int texture;
|
||||||
int effect;
|
int effect;
|
||||||
int type;
|
int type; // enum q3bsp_face_type
|
||||||
int vertex;
|
int vertex;
|
||||||
int n_vertexes;
|
int n_vertexes;
|
||||||
int meshvert;
|
int meshvert;
|
||||||
|
138
q3bsp/q3bsp_patch.cpp
Normal file
138
q3bsp/q3bsp_patch.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include "math/vec2.hpp"
|
||||||
|
#include "math/vec3.hpp"
|
||||||
|
|
||||||
|
#include "q3bsp/q3bsp.h"
|
||||||
|
#include "q3bsp/q3bsp_patch.hpp"
|
||||||
|
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
|
namespace q3bsp_patch {
|
||||||
|
|
||||||
|
using vec2 = vec<2, float>;
|
||||||
|
using vec3 = vec<3, float>;
|
||||||
|
|
||||||
|
vertex_plm patch_vertices[max_surface_count * max_vertices_per_surface];
|
||||||
|
constexpr int max_patch_vertices = (sizeof (patch_vertices)) / (sizeof (vertex_plm));
|
||||||
|
|
||||||
|
bezier::triangle patch_triangles[max_surface_count * max_triangles_per_surface];
|
||||||
|
constexpr int max_patch_triangles = (sizeof (patch_triangles)) / ((sizeof (int)) * 3);
|
||||||
|
|
||||||
|
patch patches[max_patch_count];
|
||||||
|
int patch_count = 0;
|
||||||
|
|
||||||
|
static int triangulate_patch(const q3bsp_vertex_t * vertexes,
|
||||||
|
const int width,
|
||||||
|
const int height,
|
||||||
|
vertex_plm * p_vtx,
|
||||||
|
bezier::triangle * p_tri)
|
||||||
|
{
|
||||||
|
const int h_surfaces = (width - 1) / 2;
|
||||||
|
const int v_surfaces = (height - 1) / 2;
|
||||||
|
|
||||||
|
int vertex_base = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < v_surfaces; j++) {
|
||||||
|
for (int k = 0; k < h_surfaces; k++) {
|
||||||
|
int ix = j * width * 2 + k * 2;
|
||||||
|
const q3bsp_vertex_t * a = &vertexes[ix + width * 0 + 0];
|
||||||
|
const q3bsp_vertex_t * b = &vertexes[ix + width * 0 + 1];
|
||||||
|
const q3bsp_vertex_t * c = &vertexes[ix + width * 0 + 2];
|
||||||
|
const q3bsp_vertex_t * d = &vertexes[ix + width * 1 + 0];
|
||||||
|
const q3bsp_vertex_t * e = &vertexes[ix + width * 1 + 1];
|
||||||
|
const q3bsp_vertex_t * f = &vertexes[ix + width * 1 + 2];
|
||||||
|
const q3bsp_vertex_t * g = &vertexes[ix + width * 2 + 0];
|
||||||
|
const q3bsp_vertex_t * h = &vertexes[ix + width * 2 + 1];
|
||||||
|
const q3bsp_vertex_t * i = &vertexes[ix + width * 2 + 2];
|
||||||
|
|
||||||
|
const vec3 a_p = {a->position[0], a->position[1], a->position[2]};
|
||||||
|
const vec3 b_p = {b->position[0], b->position[1], b->position[2]};
|
||||||
|
const vec3 c_p = {c->position[0], c->position[1], c->position[2]};
|
||||||
|
const vec3 d_p = {d->position[0], d->position[1], d->position[2]};
|
||||||
|
const vec3 e_p = {e->position[0], e->position[1], e->position[2]};
|
||||||
|
const vec3 f_p = {f->position[0], f->position[1], f->position[2]};
|
||||||
|
const vec3 g_p = {g->position[0], g->position[1], g->position[2]};
|
||||||
|
const vec3 h_p = {h->position[0], h->position[1], h->position[2]};
|
||||||
|
const vec3 i_p = {i->position[0], i->position[1], i->position[2]};
|
||||||
|
|
||||||
|
const vec2 a_t = {a->texture[0], a->texture[1]};
|
||||||
|
const vec2 b_t = {b->texture[0], b->texture[1]};
|
||||||
|
const vec2 c_t = {c->texture[0], c->texture[1]};
|
||||||
|
const vec2 d_t = {d->texture[0], d->texture[1]};
|
||||||
|
const vec2 e_t = {e->texture[0], e->texture[1]};
|
||||||
|
const vec2 f_t = {f->texture[0], f->texture[1]};
|
||||||
|
const vec2 g_t = {g->texture[0], g->texture[1]};
|
||||||
|
const vec2 h_t = {h->texture[0], h->texture[1]};
|
||||||
|
const vec2 i_t = {i->texture[0], i->texture[1]};
|
||||||
|
|
||||||
|
const vec2 a_l = {a->lightmap[0], a->lightmap[1]};
|
||||||
|
const vec2 b_l = {b->lightmap[0], b->lightmap[1]};
|
||||||
|
const vec2 c_l = {c->lightmap[0], c->lightmap[1]};
|
||||||
|
const vec2 d_l = {d->lightmap[0], d->lightmap[1]};
|
||||||
|
const vec2 e_l = {e->lightmap[0], e->lightmap[1]};
|
||||||
|
const vec2 f_l = {f->lightmap[0], f->lightmap[1]};
|
||||||
|
const vec2 g_l = {g->lightmap[0], g->lightmap[1]};
|
||||||
|
const vec2 h_l = {h->lightmap[0], h->lightmap[1]};
|
||||||
|
const vec2 i_l = {i->lightmap[0], i->lightmap[1]};
|
||||||
|
|
||||||
|
const vertex_plm control[9] = {
|
||||||
|
{a_p, a_t, a_l}, {b_p, b_t, b_l}, {c_p, c_t, c_l},
|
||||||
|
{d_p, d_t, d_l}, {e_p, e_t, e_l}, {f_p, f_t, f_l},
|
||||||
|
{g_p, g_t, g_l}, {h_p, h_t, h_l}, {i_p, i_t, i_l},
|
||||||
|
};
|
||||||
|
|
||||||
|
bezier::tessellate<float, 3, 2, 2>(level,
|
||||||
|
control,
|
||||||
|
p_vtx,
|
||||||
|
p_tri,
|
||||||
|
vertex_base);
|
||||||
|
p_vtx += vertices_per_surface;
|
||||||
|
p_tri += triangles_per_surface;
|
||||||
|
vertex_base += vertices_per_surface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return h_surfaces * v_surfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
void triangulate_patches(const void * bsp)
|
||||||
|
{
|
||||||
|
const uint8_t * buf = reinterpret_cast<const uint8_t *>(bsp);
|
||||||
|
const q3bsp_header_t * header = reinterpret_cast<const q3bsp_header_t *>(buf);
|
||||||
|
|
||||||
|
const q3bsp_direntry * fe = &header->direntries[LUMP_FACES];
|
||||||
|
const q3bsp_face_t * faces = reinterpret_cast<const q3bsp_face_t *>(&buf[fe->offset]);
|
||||||
|
|
||||||
|
const q3bsp_direntry * ve = &header->direntries[LUMP_VERTEXES];
|
||||||
|
const q3bsp_vertex_t * vertexes = reinterpret_cast<const q3bsp_vertex_t *>(&buf[ve->offset]);
|
||||||
|
|
||||||
|
int face_count = fe->length / (sizeof (struct q3bsp_face));
|
||||||
|
|
||||||
|
int vertex_ix = 0;
|
||||||
|
int triangle_ix = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < face_count; i++) {
|
||||||
|
const q3bsp_face_t * face = &faces[i];
|
||||||
|
if (face->type == FACE_TYPE_PATCH) {
|
||||||
|
assert(vertex_ix < max_patch_vertices);
|
||||||
|
assert(triangle_ix < max_patch_triangles);
|
||||||
|
|
||||||
|
int surface_count = triangulate_patch(&vertexes[face->vertex],
|
||||||
|
face->size[0],
|
||||||
|
face->size[1],
|
||||||
|
&patch_vertices[vertex_ix],
|
||||||
|
&patch_triangles[triangle_ix]);
|
||||||
|
assert(patch_count < max_patch_count);
|
||||||
|
patches[patch_count].face_ix = i;
|
||||||
|
patches[patch_count].vertex_ix = vertex_ix;
|
||||||
|
patches[patch_count].triangle_ix = triangle_ix;
|
||||||
|
patch_count += 1;
|
||||||
|
|
||||||
|
vertex_ix += vertices_per_surface * surface_count;
|
||||||
|
triangle_ix += triangles_per_surface * surface_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(vertex_ix <= max_patch_vertices);
|
||||||
|
assert(triangle_ix <= max_patch_triangles);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
q3bsp/q3bsp_patch.hpp
Normal file
31
q3bsp/q3bsp_patch.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "math/bezier.hpp"
|
||||||
|
|
||||||
|
namespace q3bsp_patch {
|
||||||
|
constexpr int max_patch_count = 16; // 12
|
||||||
|
constexpr int max_surface_count = 32; // 20
|
||||||
|
constexpr int max_level = 3;
|
||||||
|
constexpr int level = 3;
|
||||||
|
|
||||||
|
constexpr int max_vertices_per_surface = (max_level + 1) * (max_level + 1);
|
||||||
|
constexpr int max_triangles_per_surface = max_level * max_level * 2;
|
||||||
|
|
||||||
|
constexpr int vertices_per_surface = (level + 1) * (level + 1);
|
||||||
|
constexpr int triangles_per_surface = level * level * 2;
|
||||||
|
|
||||||
|
void triangulate_patches(const void * bsp);
|
||||||
|
extern int patch_count;
|
||||||
|
|
||||||
|
using vertex_plm = bezier::vec_lmn<float, 3, 2, 2>;
|
||||||
|
|
||||||
|
struct patch {
|
||||||
|
int face_ix;
|
||||||
|
int vertex_ix;
|
||||||
|
int triangle_ix;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern vertex_plm patch_vertices[];
|
||||||
|
extern bezier::triangle patch_triangles[];
|
||||||
|
extern patch patches[];
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user