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 "q3bsp/q3bsp.h"
|
||||
#include "q3bsp/q3bsp_patch.hpp"
|
||||
#include "bsp/20kdm2/maps/20kdm2.bsp.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
|
||||
| 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
|
||||
@ -601,7 +602,7 @@ float light_intensity(vec3 light_vec, vec3 n)
|
||||
|
||||
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);
|
||||
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 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++) {
|
||||
|
||||
int aix = mv[j * 3 + 0].offset + face->vertex;
|
||||
@ -657,15 +638,14 @@ static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * fac
|
||||
float li0 = light_intensity(light_vec, n);
|
||||
const float li1 = 2.0;
|
||||
|
||||
if (has_texture) {
|
||||
float v_mul = textures[face->texture].v_mul;
|
||||
vec2 at = {vert[aix].texcoord[0], vert[aix].texcoord[1] * v_mul};
|
||||
vec2 bt = {vert[bix].texcoord[0], vert[bix].texcoord[1] * v_mul};
|
||||
vec2 ct = {vert[cix].texcoord[0], vert[cix].texcoord[1] * v_mul};
|
||||
vec2 at = {vert[aix].texture[0], vert[aix].texture[1] * v_mul};
|
||||
vec2 bt = {vert[bix].texture[0], vert[bix].texture[1] * v_mul};
|
||||
vec2 ct = {vert[cix].texture[0], vert[cix].texture[1] * v_mul};
|
||||
|
||||
vec2 alm = {vert[aix].lightmapcoord[0], vert[aix].lightmapcoord[1]};
|
||||
vec2 blm = {vert[bix].lightmapcoord[0], vert[bix].lightmapcoord[1]};
|
||||
vec2 clm = {vert[cix].lightmapcoord[0], vert[cix].lightmapcoord[1]};
|
||||
vec2 alm = {vert[aix].lightmap[0], vert[aix].lightmap[1]};
|
||||
vec2 blm = {vert[bix].lightmap[0], vert[bix].lightmap[1]};
|
||||
vec2 clm = {vert[cix].lightmap[0], vert[cix].lightmap[1]};
|
||||
|
||||
if (ap.z < 0 || bp.z < 0 || cp.z < 0) {
|
||||
render_clip_tri_type_13(writer,
|
||||
@ -698,19 +678,93 @@ static inline void transfer_face(ta_parameter_writer& writer, q3bsp_face_t * fac
|
||||
li0,
|
||||
li1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
render_tri_type_2(writer,
|
||||
screen_transform(ap),
|
||||
screen_transform(bp),
|
||||
screen_transform(cp),
|
||||
li);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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_lm_index = -1;
|
||||
|
||||
const int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
vec2 at = {vert[aix].texcoord[0], vert[aix].texcoord[1]};
|
||||
vec2 bt = {vert[bix].texcoord[0], vert[bix].texcoord[1]};
|
||||
vec2 ct = {vert[cix].texcoord[0], vert[cix].texcoord[1]};
|
||||
vec2 at = {vert[aix].texture[0], vert[aix].texture[1]};
|
||||
vec2 bt = {vert[bix].texture[0], vert[bix].texture[1]};
|
||||
vec2 ct = {vert[cix].texture[0], vert[cix].texture[1]};
|
||||
|
||||
render_tri_type_7(writer,
|
||||
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_lm_index = -1;
|
||||
|
||||
const int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
|
||||
|
||||
for (int i = 0; i < leaf->n_leaffaces; i++) {
|
||||
int face_ix = lf[i].face;
|
||||
if (face_cache[face_ix] != 0)
|
||||
continue;
|
||||
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];
|
||||
int face_count = fe->length / (sizeof (struct q3bsp_face));
|
||||
|
||||
//transfer_faces(writer);
|
||||
//transfer_faces(writer, trans);
|
||||
//transfer_icosphere(writer, trans);
|
||||
|
||||
//render_matrix(writer, screen_trans);
|
||||
@ -1548,7 +1647,8 @@ void transfer_textures()
|
||||
|
||||
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++) {
|
||||
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]);
|
||||
@ -1805,6 +1905,8 @@ int main()
|
||||
| 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
|
||||
| istnrm::v_blank_in
|
||||
| istnrm::end_of_transferring_opaque_modifier_volume_list;
|
||||
@ -1838,9 +1940,10 @@ int main()
|
||||
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) {
|
||||
maple::dma_wait_complete();
|
||||
|
@ -13,6 +13,7 @@ BSP_20KDM2_OBJ = \
|
||||
maple/maple.o \
|
||||
font/font_bitmap.o \
|
||||
font/verite_8x16/verite_8x16.data.o \
|
||||
q3bsp/q3bsp_patch.o \
|
||||
bsp/20kdm2/maps/20kdm2.bsp.o \
|
||||
bsp/20kdm2/textures/e7/e7walldesign01b.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"
|
||||
|
||||
namespace geometry {
|
||||
|
@ -105,15 +105,32 @@ 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]);
|
||||
|
||||
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));
|
||||
|
||||
printf("faces count: %d\n", count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
q3bsp_face_t * face = &faces[i];
|
||||
if (face->texture == 23 || face->texture == 24 || face->type == 4){
|
||||
printf("face [%d]\n", i);
|
||||
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("faces count: %d\n", count);
|
||||
for (int face_ix = 0; face_ix < count; face_ix++) {
|
||||
q3bsp_face_t * face = &faces[face_ix];
|
||||
if (face->type != 2)
|
||||
continue;
|
||||
//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>
|
||||
|
||||
typedef struct q3bsp_direntry {
|
||||
@ -29,7 +31,7 @@ enum q3bsp_lumps {
|
||||
LUMP_LIGHTMAPS = 14,
|
||||
LUMP_LIGHTVOLS = 15,
|
||||
LUMP_VISDATA = 16,
|
||||
} q3bsp_lumps;
|
||||
};
|
||||
|
||||
/*
|
||||
typedef struct q3bsp_entity {
|
||||
@ -96,8 +98,8 @@ typedef struct q3bsp_brushside {
|
||||
|
||||
typedef struct q3bsp_vertex {
|
||||
float position[3];
|
||||
float texcoord[2];
|
||||
float lightmapcoord[2];
|
||||
float texture[2];
|
||||
float lightmap[2];
|
||||
float normal[3];
|
||||
uint8_t color[4];
|
||||
} q3bsp_vertex_t;
|
||||
@ -112,10 +114,17 @@ typedef struct q3bsp_effect {
|
||||
int unknown;
|
||||
} 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 {
|
||||
int texture;
|
||||
int effect;
|
||||
int type;
|
||||
int type; // enum q3bsp_face_type
|
||||
int vertex;
|
||||
int n_vertexes;
|
||||
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