mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-30 19:08:12 +03:00
Merge pull request #67 from kichikuou/height
ReignEngine: Implement CalcInstanceHeightDetection
This commit is contained in:
@@ -105,6 +105,7 @@ struct RE_instance {
|
||||
struct model *model;
|
||||
struct motion *motion;
|
||||
struct motion *next_motion;
|
||||
struct height_detector *height_detector;
|
||||
|
||||
enum RE_instance_type type;
|
||||
vec3 pos;
|
||||
@@ -150,6 +151,7 @@ bool RE_instance_free_next_motion(struct RE_instance *instance);
|
||||
bool RE_instance_set_vertex_pos(struct RE_instance *instance, int index, float x, float y, float z);
|
||||
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);
|
||||
|
||||
int RE_motion_get_state(struct motion *motion);
|
||||
bool RE_motion_set_state(struct motion *motion, int state);
|
||||
|
||||
@@ -14,5 +14,8 @@
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
out uvec4 frag_color;
|
||||
|
||||
void main() {
|
||||
frag_color.r = uint(gl_FragCoord.z * 65535.0);
|
||||
}
|
||||
|
||||
@@ -163,6 +163,9 @@ void motion_free(struct motion *motion);
|
||||
struct RE_renderer *RE_renderer_new(struct texture *texture);
|
||||
void RE_renderer_free(struct RE_renderer *r);
|
||||
bool RE_renderer_load_billboard_texture(struct RE_renderer *r, int cg_no);
|
||||
struct height_detector *RE_renderer_create_height_detector(struct RE_renderer *r, struct model *model);
|
||||
void RE_renderer_free_height_detector(struct height_detector *hd);
|
||||
float RE_renderer_detect_height(struct height_detector *hd, float x, float z);
|
||||
|
||||
// parser.c
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ static void unload_instance(struct RE_instance *instance)
|
||||
free(instance->bone_transforms);
|
||||
instance->bone_transforms = NULL;
|
||||
}
|
||||
if (instance->height_detector) {
|
||||
RE_renderer_free_height_detector(instance->height_detector);
|
||||
instance->height_detector = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_instance(struct RE_instance *instance)
|
||||
@@ -374,6 +378,17 @@ bool RE_instance_trans_local_pos_to_world_pos_by_bone(struct RE_instance *instan
|
||||
return true;
|
||||
}
|
||||
|
||||
float RE_instance_calc_height(struct RE_instance *instance, float x, float z)
|
||||
{
|
||||
if (!instance || !instance->model)
|
||||
return 0.0;
|
||||
if (!instance->height_detector) {
|
||||
instance->height_detector = RE_renderer_create_height_detector(instance->plugin->renderer, instance->model);
|
||||
}
|
||||
float y = RE_renderer_detect_height(instance->height_detector, x, z);
|
||||
return y;
|
||||
}
|
||||
|
||||
void RE_instance_update_local_transform(struct RE_instance *inst)
|
||||
{
|
||||
vec3 euler = {
|
||||
|
||||
@@ -620,3 +620,97 @@ void RE_render(struct sact_sprite *sp)
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
gfx_reset_framebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
struct height_detector {
|
||||
GLushort *buf;
|
||||
vec3 aabb[2];
|
||||
};
|
||||
|
||||
struct height_detector *RE_renderer_create_height_detector(struct RE_renderer *r, struct model *model)
|
||||
{
|
||||
struct height_detector *hd = xcalloc(1, sizeof(struct height_detector));
|
||||
vec3 aabb[2];
|
||||
memcpy(aabb, model->aabb, sizeof(aabb));
|
||||
// Add some Y padding.
|
||||
aabb[0][1] -= 1.0;
|
||||
aabb[1][1] += 1.0;
|
||||
memcpy(hd->aabb, aabb, sizeof(aabb));
|
||||
|
||||
// Set up an orthographic projection matrix looking down the instance from
|
||||
// right above.
|
||||
mat4 view_matrix, proj_matrix;
|
||||
glm_mat4_identity(view_matrix);
|
||||
glm_rotate_x(view_matrix, glm_rad(90.0), view_matrix);
|
||||
glm_aabb_transform(aabb, view_matrix, aabb);
|
||||
glm_ortho_aabb(aabb, proj_matrix);
|
||||
|
||||
GLint orig_fbo, orig_viewport[4];
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &orig_fbo);
|
||||
glGetIntegerv(GL_VIEWPORT, orig_viewport);
|
||||
|
||||
// Since OpenGL ES does not allow reading from depth textures, create a
|
||||
// color texture and render depth values into it.
|
||||
GLuint color_texture;
|
||||
glGenTextures(1, &color_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, color_texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, r->shadow.fbo);
|
||||
GLenum draw_buffers[1] = { GL_COLOR_ATTACHMENT0 };
|
||||
glDrawBuffers(1, draw_buffers);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture, 0);
|
||||
|
||||
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glUseProgram(r->shadow.program);
|
||||
glUniformMatrix4fv(r->shadow.world_transform, 1, GL_FALSE, view_matrix[0]);
|
||||
glUniformMatrix4fv(r->shadow.view_transform, 1, GL_FALSE, proj_matrix[0]);
|
||||
glUniform1i(r->shadow.has_bones, GL_FALSE);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Render the model.
|
||||
for (int i = 0; i < model->nr_meshes; i++) {
|
||||
struct mesh *mesh = &model->meshes[i];
|
||||
glBindVertexArray(mesh->vao);
|
||||
glDrawArrays(GL_TRIANGLES, 0, mesh->nr_vertices);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
glFinish();
|
||||
|
||||
hd->buf = xmalloc(SHADOW_WIDTH * SHADOW_HEIGHT * sizeof(GLushort));
|
||||
glReadPixels(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT, GL_RED_INTEGER, GL_UNSIGNED_SHORT, hd->buf);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDrawBuffers(0, NULL);
|
||||
glReadBuffer(GL_NONE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, orig_fbo);
|
||||
glViewport(orig_viewport[0], orig_viewport[1], orig_viewport[2], orig_viewport[3]);
|
||||
|
||||
glDeleteTextures(1, &color_texture);
|
||||
return hd;
|
||||
}
|
||||
|
||||
void RE_renderer_free_height_detector(struct height_detector *hd)
|
||||
{
|
||||
free(hd->buf);
|
||||
free(hd);
|
||||
}
|
||||
|
||||
float RE_renderer_detect_height(struct height_detector *hd, float x, float z)
|
||||
{
|
||||
float minx = hd->aabb[0][0];
|
||||
float maxx = hd->aabb[1][0];
|
||||
float miny = hd->aabb[0][1];
|
||||
float maxy = hd->aabb[1][1];
|
||||
float minz = hd->aabb[0][2];
|
||||
float maxz = hd->aabb[1][2];
|
||||
if (x < minx || x > maxx || z < minz || z > maxz)
|
||||
return 0.0;
|
||||
int px = glm_percent(minx, maxx, x) * SHADOW_WIDTH;
|
||||
int pz = glm_percent(maxz, minz, z) * SHADOW_HEIGHT;
|
||||
float py = hd->buf[pz * SHADOW_WIDTH + px] / 65535.0;
|
||||
return glm_lerp(maxy, miny, py);
|
||||
}
|
||||
|
||||
@@ -523,7 +523,12 @@ static bool ReignEngine_TransInstanceLocalPosToWorldPosByBone(int plugin, int in
|
||||
//int ReignEngine_GetInstanceTextureMemorySize(int plugin, int instance);
|
||||
//void ReignEngine_GetInstanceInfoText(int plugin, int instance, struct string **pIText);
|
||||
//void ReignEngine_GetInstanceMaterialInfoText(int plugin, int instance, struct string **pIText);
|
||||
HLL_WARN_UNIMPLEMENTED(0.0, float, ReignEngine, CalcInstanceHeightDetection, int plugin, int instance, float x, float z);
|
||||
|
||||
static float ReignEngine_CalcInstanceHeightDetection(int plugin, int instance, float x, float z)
|
||||
{
|
||||
return RE_instance_calc_height(get_instance(plugin, instance), x, -z);
|
||||
}
|
||||
|
||||
//float ReignEngine_GetInstanceSoftFogEdgeLength(int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceSoftFogEdgeLength, int plugin, int instance, float length);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user