mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-30 19:08:12 +03:00
Implement ReignEngine.SetInstanceDebugDrawShadowVolume
It visualizes the bounding sphere of the instance. Although it is only called from dead code in Toushin Toshi 3, it's useful for debugging shadow mapping.
This commit is contained in:
@@ -166,6 +166,7 @@ struct RE_instance {
|
||||
mat3 normal_transform;
|
||||
mat4 *bone_transforms; // model->nr_bones elements
|
||||
vec4 bounding_sphere;
|
||||
struct RE_instance *shadow_volume_instance;
|
||||
float z_from_camera;
|
||||
};
|
||||
|
||||
@@ -187,6 +188,7 @@ bool RE_instance_set_vertex_pos(struct RE_instance *instance, int index, float x
|
||||
int RE_instance_get_bone_index(struct RE_instance *instance, const char *name);
|
||||
bool RE_instance_trans_local_pos_to_world_pos_by_bone(struct RE_instance *instance, int bone, vec3 offset, vec3 out);
|
||||
float RE_instance_calc_height(struct RE_instance *instance, float x, float z);
|
||||
bool RE_instance_set_debug_draw_shadow_volume(struct RE_instance *instance, bool draw);
|
||||
|
||||
int RE_motion_get_state(struct motion *motion);
|
||||
bool RE_motion_set_state(struct motion *motion, int state);
|
||||
|
||||
@@ -51,7 +51,9 @@ struct mesh {
|
||||
uint32_t flags;
|
||||
GLuint vao;
|
||||
GLuint attr_buffer;
|
||||
GLuint index_buffer;
|
||||
int nr_vertices;
|
||||
int nr_indices;
|
||||
int material;
|
||||
};
|
||||
|
||||
@@ -176,6 +178,7 @@ void RE_instance_update_local_transform(struct RE_instance *inst);
|
||||
|
||||
struct model *model_load(struct archive *aar, const char *path);
|
||||
void model_free(struct model *model);
|
||||
struct model *model_create_sphere(int r, int g, int b, int a);
|
||||
|
||||
struct motion *motion_load(const char *name, struct RE_instance *instance, struct archive *aar);
|
||||
void motion_free(struct motion *motion);
|
||||
|
||||
@@ -336,6 +336,8 @@ static void destroy_mesh(struct mesh *mesh)
|
||||
{
|
||||
glDeleteVertexArrays(1, &mesh->vao);
|
||||
glDeleteBuffers(1, &mesh->attr_buffer);
|
||||
if (mesh->index_buffer)
|
||||
glDeleteBuffers(1, &mesh->index_buffer);
|
||||
}
|
||||
|
||||
static struct bone *add_bone(struct model *model, struct pol *pol, struct pol_bone *pol_bone)
|
||||
@@ -499,6 +501,101 @@ void model_free(struct model *model)
|
||||
free(model);
|
||||
}
|
||||
|
||||
static void init_sphere_mesh(struct mesh *mesh)
|
||||
{
|
||||
const int w_segments = 16;
|
||||
const int h_segments = 16;
|
||||
const int nr_vertices = (w_segments + 1) * (h_segments + 1);
|
||||
struct vertex_common *vertices = xcalloc(nr_vertices, sizeof(struct vertex_common));
|
||||
struct vertex_common *v = vertices;
|
||||
for (int y = 0; y <= h_segments; y++) {
|
||||
float theta = GLM_PIf * y / h_segments;
|
||||
for (int x = 0; x <= w_segments; x++, v++) {
|
||||
float phi = 2.0f * GLM_PIf * x / w_segments;
|
||||
v->pos[0] = -cosf(phi) * sinf(theta);
|
||||
v->pos[1] = cosf(theta);
|
||||
v->pos[2] = sinf(phi) * sinf(theta);
|
||||
glm_vec3_copy(v->pos, v->normal);
|
||||
v->uv[0] = v->uv[1] = 0.0f;
|
||||
}
|
||||
}
|
||||
assert(v == vertices + nr_vertices);
|
||||
|
||||
const int nr_indices = 3 * 2 * w_segments * (h_segments - 1);
|
||||
GLushort *indices = xcalloc(nr_indices, sizeof(GLushort));
|
||||
GLushort *pi = indices;
|
||||
for (int y = 0; y < h_segments; y++) {
|
||||
for (int x = 0; x < w_segments; x++) {
|
||||
GLushort a = y * w_segments + x + 1;
|
||||
GLushort b = y * w_segments + x;
|
||||
GLushort c = (y + 1) * w_segments + x;
|
||||
GLushort d = (y + 1) * w_segments + x + 1;
|
||||
if (y > 0) {
|
||||
*pi++ = a;
|
||||
*pi++ = b;
|
||||
*pi++ = d;
|
||||
}
|
||||
if (y < h_segments - 1) {
|
||||
*pi++ = b;
|
||||
*pi++ = c;
|
||||
*pi++ = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pi == indices + nr_indices);
|
||||
|
||||
mesh->flags = MESH_NOLIGHTING;
|
||||
mesh->nr_vertices = nr_vertices;
|
||||
mesh->nr_indices = nr_indices;
|
||||
glGenVertexArrays(1, &mesh->vao);
|
||||
glBindVertexArray(mesh->vao);
|
||||
glGenBuffers(1, &mesh->attr_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->attr_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, nr_vertices * sizeof(struct vertex_common), vertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(VATTR_POS);
|
||||
glVertexAttribPointer(VATTR_POS, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex_common), (void*)offsetof(struct vertex_common, pos));
|
||||
glEnableVertexAttribArray(VATTR_NORMAL);
|
||||
glVertexAttribPointer(VATTR_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex_common), (void*)offsetof(struct vertex_common, normal));
|
||||
glEnableVertexAttribArray(VATTR_UV);
|
||||
glVertexAttribPointer(VATTR_UV, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex_common), (void*)offsetof(struct vertex_common, uv));
|
||||
|
||||
glGenBuffers(1, &mesh->index_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, nr_indices * sizeof(GLushort), indices, GL_STATIC_DRAW);
|
||||
glBindVertexArray(0);
|
||||
|
||||
free(vertices);
|
||||
free(indices);
|
||||
}
|
||||
|
||||
struct model *model_create_sphere(int r, int g, int b, int a)
|
||||
{
|
||||
struct model *model = xcalloc(1, sizeof(struct model));
|
||||
|
||||
model->nr_meshes = 1;
|
||||
model->meshes = xcalloc(1, sizeof(struct mesh));
|
||||
init_sphere_mesh(&model->meshes[0]);
|
||||
model->aabb[0][0] = -1.0f;
|
||||
model->aabb[0][1] = -1.0f;
|
||||
model->aabb[0][2] = -1.0f;
|
||||
model->aabb[1][0] = 1.0f;
|
||||
model->aabb[1][1] = 1.0f;
|
||||
model->aabb[1][2] = 1.0f;
|
||||
|
||||
model->nr_materials = 1;
|
||||
model->materials = xcalloc(1, sizeof(struct material));
|
||||
struct material *material = &model->materials[0];
|
||||
material->is_transparent = true;
|
||||
glGenTextures(1, &material->color_map);
|
||||
glBindTexture(GL_TEXTURE_2D, material->color_map);
|
||||
uint8_t pixel[4] = {r, g, b, a};
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
model->has_transparent_material = true;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
static int cmp_motions_by_bone_id(const void *lhs, const void *rhs)
|
||||
{
|
||||
return (*(struct mot_bone **)lhs)->id - (*(struct mot_bone **)rhs)->id;
|
||||
|
||||
@@ -53,6 +53,8 @@ static struct RE_instance *create_instance(struct RE_plugin *plugin)
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void free_instance(struct RE_instance *instance);
|
||||
|
||||
static void unload_instance(struct RE_instance *instance)
|
||||
{
|
||||
if (instance->motion) {
|
||||
@@ -79,6 +81,10 @@ static void unload_instance(struct RE_instance *instance)
|
||||
RE_renderer_free_height_detector(instance->height_detector);
|
||||
instance->height_detector = NULL;
|
||||
}
|
||||
if (instance->shadow_volume_instance) {
|
||||
free_instance(instance->shadow_volume_instance);
|
||||
instance->shadow_volume_instance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_instance(struct RE_instance *instance)
|
||||
@@ -179,6 +185,13 @@ static void update_bones(struct RE_instance *inst)
|
||||
RE_instance_update_local_transform(inst);
|
||||
glm_mat4_mulv3(inst->local_transform, center, 1.0f, inst->bounding_sphere);
|
||||
inst->bounding_sphere[3] = glm_aabb_radius(aabb) * inst->scale[0] + inst->shadow_volume_bone_radius;
|
||||
|
||||
struct RE_instance *shvol = inst->shadow_volume_instance;
|
||||
if (shvol) {
|
||||
glm_vec3_copy(inst->bounding_sphere, shvol->pos);
|
||||
glm_vec3_broadcast(inst->bounding_sphere[3], shvol->scale);
|
||||
RE_instance_update_local_transform(shvol);
|
||||
}
|
||||
}
|
||||
|
||||
struct RE_plugin *RE_plugin_new(void)
|
||||
@@ -459,6 +472,19 @@ float RE_instance_calc_height(struct RE_instance *instance, float x, float z)
|
||||
return y;
|
||||
}
|
||||
|
||||
bool RE_instance_set_debug_draw_shadow_volume(struct RE_instance *inst, bool draw)
|
||||
{
|
||||
if (!inst)
|
||||
return false;
|
||||
if (draw && !inst->shadow_volume_instance) {
|
||||
inst->shadow_volume_instance = create_instance(inst->plugin);
|
||||
inst->shadow_volume_instance->model = model_create_sphere(255, 0, 0, 64);
|
||||
}
|
||||
if (inst->shadow_volume_instance)
|
||||
inst->shadow_volume_instance->draw = draw;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RE_instance_update_local_transform(struct RE_instance *inst)
|
||||
{
|
||||
vec3 euler = {
|
||||
|
||||
+9
-1
@@ -383,7 +383,12 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
|
||||
}
|
||||
|
||||
glBindVertexArray(mesh->vao);
|
||||
glDrawArrays(GL_TRIANGLES, 0, mesh->nr_vertices);
|
||||
|
||||
if (mesh->nr_indices)
|
||||
glDrawElements(GL_TRIANGLES, mesh->nr_indices, GL_UNSIGNED_SHORT, NULL);
|
||||
else
|
||||
glDrawArrays(GL_TRIANGLES, 0, mesh->nr_vertices);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
@@ -412,6 +417,9 @@ static void render_skinned_model(struct RE_instance *inst, struct RE_renderer *r
|
||||
glUniform1i(r->has_bones, GL_FALSE);
|
||||
}
|
||||
render_model(inst, r, phase);
|
||||
|
||||
if (inst->shadow_volume_instance && phase == DRAW_TRANSPARENT)
|
||||
render_static_model(inst->shadow_volume_instance, r, phase);
|
||||
}
|
||||
|
||||
static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, mat4 view_mat, enum draw_phase phase)
|
||||
|
||||
+13
-4
@@ -651,8 +651,17 @@ static bool ReignEngine_SetInstanceShadowVolumeBoneRadius(int plugin, int instan
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool ReignEngine_GetInstanceDebugDrawShadowVolume(int plugin, int instance);
|
||||
//bool ReignEngine_SetInstanceDebugDrawShadowVolume(int plugin, int instance, bool flag);
|
||||
static bool ReignEngine_GetInstanceDebugDrawShadowVolume(int plugin, int instance)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
return ri && ri->shadow_volume_instance && ri->shadow_volume_instance->draw;
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceDebugDrawShadowVolume(int plugin, int instance, bool flag)
|
||||
{
|
||||
return RE_instance_set_debug_draw_shadow_volume(get_instance(plugin, instance), flag);
|
||||
}
|
||||
|
||||
//bool ReignEngine_SaveEffect(int plugin, int instance);
|
||||
|
||||
static bool ReignEngine_GetEffectFrameRange(int plugin, int instance, int *begin_frame, int *end_frame)
|
||||
@@ -1899,8 +1908,8 @@ HLL_LIBRARY(ReignEngine,
|
||||
HLL_EXPORT(SetInstanceSoftFogEdgeLength, ReignEngine_SetInstanceSoftFogEdgeLength),
|
||||
HLL_EXPORT(GetInstanceShadowVolumeBoneRadius, ReignEngine_GetInstanceShadowVolumeBoneRadius),
|
||||
HLL_EXPORT(SetInstanceShadowVolumeBoneRadius, ReignEngine_SetInstanceShadowVolumeBoneRadius),
|
||||
HLL_TODO_EXPORT(GetInstanceDebugDrawShadowVolume, ReignEngine_GetInstanceDebugDrawShadowVolume),
|
||||
HLL_TODO_EXPORT(SetInstanceDebugDrawShadowVolume, ReignEngine_SetInstanceDebugDrawShadowVolume),
|
||||
HLL_EXPORT(GetInstanceDebugDrawShadowVolume, ReignEngine_GetInstanceDebugDrawShadowVolume),
|
||||
HLL_EXPORT(SetInstanceDebugDrawShadowVolume, ReignEngine_SetInstanceDebugDrawShadowVolume),
|
||||
HLL_TODO_EXPORT(SaveEffect, ReignEngine_SaveEffect),
|
||||
HLL_EXPORT(GetEffectFrameRange, ReignEngine_GetEffectFrameRange),
|
||||
HLL_EXPORT(GetEffectObjectType, ReignEngine_GetEffectObjectType),
|
||||
|
||||
Reference in New Issue
Block a user