diff --git a/include/reign.h b/include/reign.h
index dea70c4..5325ed7 100644
--- a/include/reign.h
+++ b/include/reign.h
@@ -131,6 +131,7 @@ struct RE_plugin *RE_plugin_new(void);
void RE_plugin_free(struct RE_plugin *plugin);
bool RE_plugin_bind(struct RE_plugin *plugin, int sprite);
bool RE_plugin_unbind(struct RE_plugin *plugin);
+bool RE_build_model(struct RE_plugin *plugin, int elapsed_ms);
bool RE_set_projection(struct RE_plugin *plugin, float width, float height, float near, float far, float deg);
int RE_create_instance(struct RE_plugin *plugin);
bool RE_release_instance(struct RE_plugin *plugin, int instance);
diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h
index f06be1f..4215f73 100644
--- a/src/3d/3d_internal.h
+++ b/src/3d/3d_internal.h
@@ -112,11 +112,9 @@ struct RE_renderer {
GLint vertex_bone_index;
GLint vertex_bone_weight;
- mat4 bone_transforms[MAX_BONES];
GLuint billboard_vao;
GLuint billboard_attr_buffer;
struct hash_table *billboard_textures; // cg_no -> struct billboard_texture*
- uint32_t last_frame_timestamp;
};
struct billboard_texture {
diff --git a/src/3d/reign.c b/src/3d/reign.c
index 32b8000..8c9e5a2 100644
--- a/src/3d/reign.c
+++ b/src/3d/reign.c
@@ -30,6 +30,7 @@
#include "asset_manager.h"
#include "reign.h"
#include "sact.h"
+#include "vm.h"
#include "xsystem4.h"
static struct RE_instance *create_instance(struct RE_plugin *plugin)
@@ -86,6 +87,74 @@ static void RE_back_cg_destroy(struct RE_back_cg *bcg)
free_string(bcg->name);
}
+static void interpolate_motion_frame(struct mot_frame *m1, struct mot_frame *m2, float t, struct mot_frame *out)
+{
+ glm_vec3_lerp(m1->pos, m2->pos, t, out->pos);
+ glm_quat_nlerp(m1->rotq, m2->rotq, t, out->rotq);
+}
+
+static void update_motion(struct motion *m, float delta_frame)
+{
+ if (!m || m->state == RE_MOTION_STATE_STOP)
+ return;
+ m->current_frame += delta_frame;
+ switch (m->state) {
+ case RE_MOTION_STATE_NOLOOP:
+ if (m->current_frame > m->frame_end) {
+ m->current_frame = m->frame_end;
+ m->state = RE_MOTION_STATE_STOP;
+ }
+ break;
+ case RE_MOTION_STATE_LOOP:
+ if (m->current_frame > m->loop_frame_end)
+ m->current_frame = m->loop_frame_begin + fmodf(m->current_frame - m->loop_frame_begin, m->loop_frame_end - m->loop_frame_begin);
+ break;
+ default:
+ VM_ERROR("Invalid motion state %d", m->state);
+ }
+}
+
+static void calc_motion_frame(struct motion *m, int bone, struct mot_frame *out)
+{
+ int cur_frame = m->current_frame;
+ int next_frame = ceilf(m->current_frame);
+ float t = m->current_frame - cur_frame;
+ struct mot_frame *frames = m->mot->motions[bone]->frames;
+ interpolate_motion_frame(&frames[cur_frame], &frames[next_frame], t, out);
+}
+
+static void animate(struct RE_instance *inst, int elapsed_ms)
+{
+ float delta_frame = inst->fps * elapsed_ms / 1000.0;
+ update_motion(inst->motion, delta_frame);
+ update_motion(inst->next_motion, delta_frame);
+
+ if (inst->type != RE_ITYPE_SKINNED || !inst->motion)
+ return;
+
+ mat4 parent_transforms[MAX_BONES];
+ for (int i = 0; i < inst->model->nr_bones; i++) {
+ struct mot_frame mf;
+ calc_motion_frame(inst->motion, i, &mf);
+ if (inst->motion_blend && inst->next_motion) {
+ struct mot_frame next_mf;
+ calc_motion_frame(inst->next_motion, i, &next_mf);
+ interpolate_motion_frame(&mf, &next_mf, inst->motion_blend_rate, &mf);
+ }
+ mat4 bone_transform;
+ glm_translate_make(bone_transform, mf.pos);
+ glm_quat_rotate(bone_transform, mf.rotq, bone_transform);
+
+ if (inst->model->bones[i].parent >= 0) {
+ assert(inst->model->bones[i].parent < i);
+ glm_mat4_mul(parent_transforms[inst->model->bones[i].parent], bone_transform, bone_transform);
+ }
+ glm_mat4_copy(bone_transform, parent_transforms[i]);
+
+ glm_mat4_mul(bone_transform, inst->model->bones[i].inverse_bind_matrix, inst->bone_transforms[i]);
+ }
+}
+
struct RE_plugin *RE_plugin_new(void)
{
char *aar_path = gamedir_path("Data/ReignData.red");
@@ -148,6 +217,20 @@ bool RE_plugin_unbind(struct RE_plugin *plugin)
return true;
}
+bool RE_build_model(struct RE_plugin *plugin, int elapsed_ms)
+{
+ if (!plugin)
+ return false;
+ if (elapsed_ms <= 0)
+ return true;
+
+ for (int i = 0; i < RE_MAX_INSTANCES; i++) {
+ if (plugin->instances[i])
+ animate(plugin->instances[i], elapsed_ms);
+ }
+ return true;
+}
+
bool RE_set_projection(struct RE_plugin *plugin, float width, float height, float near, float far, float deg)
{
if (!plugin)
diff --git a/src/3d/renderer.c b/src/3d/renderer.c
index b630197..39b3e6e 100644
--- a/src/3d/renderer.c
+++ b/src/3d/renderer.c
@@ -14,7 +14,6 @@
* along with this program; if not, see .
*/
-#include
#include
#include "system4.h"
@@ -25,7 +24,6 @@
#include "asset_manager.h"
#include "reign.h"
#include "sact.h"
-#include "vm.h"
enum {
COLOR_TEXTURE_UNIT,
@@ -116,7 +114,6 @@ struct RE_renderer *RE_renderer_new(struct texture *texture)
init_billboard_mesh(r);
r->billboard_textures = ht_create(256);
- r->last_frame_timestamp = SDL_GetTicks();
return r;
}
@@ -200,73 +197,6 @@ static void update_local_transform(struct RE_instance *inst)
inst->local_transform_needs_update = false;
}
-static void interpolate_motion_frame(struct mot_frame *m1, struct mot_frame *m2, float t, struct mot_frame *out)
-{
- glm_vec3_lerp(m1->pos, m2->pos, t, out->pos);
- glm_quat_nlerp(m1->rotq, m2->rotq, t, out->rotq);
-}
-
-static void update_motion(struct motion *m, float delta_frame)
-{
- if (!m || m->state == RE_MOTION_STATE_STOP)
- return;
- m->current_frame += delta_frame;
- switch (m->state) {
- case RE_MOTION_STATE_NOLOOP:
- if (m->current_frame > m->frame_end) {
- m->current_frame = m->frame_end;
- m->state = RE_MOTION_STATE_STOP;
- }
- break;
- case RE_MOTION_STATE_LOOP:
- if (m->current_frame > m->loop_frame_end)
- m->current_frame = m->loop_frame_begin + fmodf(m->current_frame - m->loop_frame_begin, m->loop_frame_end - m->loop_frame_begin);
- break;
- default:
- VM_ERROR("Invalid motion state %d", m->state);
- }
-}
-
-static void calc_motion_frame(struct motion *m, int bone, struct mot_frame *out)
-{
- int cur_frame = m->current_frame;
- int next_frame = ceilf(m->current_frame);
- float t = m->current_frame - cur_frame;
- struct mot_frame *frames = m->mot->motions[bone]->frames;
- interpolate_motion_frame(&frames[cur_frame], &frames[next_frame], t, out);
-}
-
-static void animate(struct RE_instance *inst, struct RE_renderer *r, float delta_time)
-{
- float delta_frame = delta_time * inst->fps;
- update_motion(inst->motion, delta_frame);
- update_motion(inst->next_motion, delta_frame);
-
- if (inst->type == RE_ITYPE_BILLBOARD)
- return;
-
- for (int i = 0; i < inst->model->nr_bones; i++) {
- struct mot_frame mf;
- calc_motion_frame(inst->motion, i, &mf);
- if (inst->motion_blend && inst->next_motion) {
- struct mot_frame next_mf;
- calc_motion_frame(inst->next_motion, i, &next_mf);
- interpolate_motion_frame(&mf, &next_mf, inst->motion_blend_rate, &mf);
- }
- mat4 bone_transform;
- glm_translate_make(bone_transform, mf.pos);
- glm_quat_rotate(bone_transform, mf.rotq, bone_transform);
-
- if (inst->model->bones[i].parent >= 0) {
- assert(inst->model->bones[i].parent < i);
- glm_mat4_mul(inst->bone_transforms[inst->model->bones[i].parent], bone_transform, bone_transform);
- }
- glm_mat4_copy(bone_transform, inst->bone_transforms[i]);
-
- glm_mat4_mul(bone_transform, inst->model->bones[i].inverse_bind_matrix, r->bone_transforms[i]);
- }
-}
-
static void render_model(struct RE_instance *inst, struct RE_renderer *r)
{
struct model *model = inst->model;
@@ -341,26 +271,23 @@ static void render_static_model(struct RE_instance *inst, struct RE_renderer *r)
render_model(inst, r);
}
-static void render_skinned_model(struct RE_instance *inst, struct RE_renderer *r, float delta_time)
+static void render_skinned_model(struct RE_instance *inst, struct RE_renderer *r)
{
struct model *model = inst->model;
if (!model)
return;
- animate(inst, r, delta_time);
-
if (model->nr_bones > 0) {
glUniform1i(r->has_bones, GL_TRUE);
- glUniformMatrix4fv(r->bone_matrices, model->nr_bones, GL_FALSE, r->bone_transforms[0][0]);
+ glUniformMatrix4fv(r->bone_matrices, model->nr_bones, GL_FALSE, inst->bone_transforms[0][0]);
} else {
glUniform1i(r->has_bones, GL_FALSE);
}
render_model(inst, r);
}
-static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, mat4 view_mat, float delta_time)
+static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, mat4 view_mat)
{
- animate(inst, r, delta_time);
int cg_no = inst->motion->current_frame;
struct billboard_texture *bt = ht_get_int(r->billboard_textures, cg_no, NULL);
if (!bt)
@@ -448,19 +375,13 @@ static void setup_lights(struct RE_plugin *plugin)
void RE_render(struct sact_sprite *sp)
{
- uint32_t timestamp = SDL_GetTicks();
-
struct RE_plugin *plugin = (struct RE_plugin *)sp->plugin;
struct RE_renderer *r = plugin->renderer;
- if (!r) {
- r->last_frame_timestamp = timestamp;
+ if (!r)
return;
- }
sprite_dirty(sp);
struct texture *texture = sprite_get_texture(sp);
- float delta_time = (timestamp - r->last_frame_timestamp) / 1000.0;
-
GLuint fbo = gfx_set_framebuffer(GL_DRAW_FRAMEBUFFER, texture, 0, 0, texture->w, texture->h);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, r->depth_buffer);
if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
@@ -507,10 +428,10 @@ void RE_render(struct sact_sprite *sp)
render_static_model(inst, r);
break;
case RE_ITYPE_SKINNED:
- render_skinned_model(inst, r, delta_time);
+ render_skinned_model(inst, r);
break;
case RE_ITYPE_BILLBOARD:
- render_billboard(inst, r, view_transform, delta_time);
+ render_billboard(inst, r, view_transform);
break;
default:
break;
@@ -524,6 +445,4 @@ void RE_render(struct sact_sprite *sp)
glUseProgram(0);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
gfx_reset_framebuffer(GL_DRAW_FRAMEBUFFER, fbo);
-
- r->last_frame_timestamp = timestamp;
}
diff --git a/src/hll/ReignEngine.c b/src/hll/ReignEngine.c
index 41ae03d..ea503cc 100644
--- a/src/hll/ReignEngine.c
+++ b/src/hll/ReignEngine.c
@@ -94,7 +94,10 @@ static bool ReignEngine_UnbindPlugin(int handle)
return RE_plugin_unbind(get_plugin(handle));
}
-HLL_QUIET_UNIMPLEMENTED(true, bool, ReignEngine, BuildModel, int plugin, int pass_time);
+static bool ReignEngine_BuildModel(int plugin, int pass_time)
+{
+ return RE_build_model(get_plugin(plugin), pass_time);
+}
static int ReignEngine_CreateInstance(int plugin)
{