mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-07 06:18:14 +03:00
ReignEngine: Implement skeletal animation
This commit is contained in:
@@ -23,6 +23,12 @@
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
enum RE_motion_state {
|
||||
RE_MOTION_STATE_STOP = 0,
|
||||
RE_MOTION_STATE_NOLOOP = 1,
|
||||
RE_MOTION_STATE_LOOP = 2,
|
||||
};
|
||||
|
||||
struct RE_options {
|
||||
int anti_aliasing;
|
||||
int wait_vsync;
|
||||
@@ -71,14 +77,22 @@ struct RE_plugin {
|
||||
struct RE_instance {
|
||||
struct RE_plugin *plugin;
|
||||
struct model *model;
|
||||
struct motion *motion;
|
||||
struct motion *next_motion;
|
||||
|
||||
int type;
|
||||
vec3 pos;
|
||||
float pitch, roll, yaw; // in degrees
|
||||
vec3 vec;
|
||||
vec3 scale;
|
||||
bool draw;
|
||||
float fps;
|
||||
bool motion_blend;
|
||||
float motion_blend_rate;
|
||||
|
||||
bool local_transform_needs_update;
|
||||
mat4 local_transform;
|
||||
mat4 *bone_transforms; // model->nr_bones elements
|
||||
};
|
||||
|
||||
struct RE_plugin *RE_plugin_new(void);
|
||||
@@ -90,6 +104,16 @@ int RE_create_instance(struct RE_plugin *plugin);
|
||||
bool RE_release_instance(struct RE_plugin *plugin, int instance);
|
||||
|
||||
bool RE_instance_load(struct RE_instance *instance, const char *name);
|
||||
bool RE_instance_load_motion(struct RE_instance *instance, const char *name);
|
||||
bool RE_instance_load_next_motion(struct RE_instance *instance, const char *name);
|
||||
bool RE_instance_free_next_motion(struct RE_instance *instance);
|
||||
|
||||
int RE_motion_get_state(struct motion *motion);
|
||||
bool RE_motion_set_state(struct motion *motion, int state);
|
||||
float RE_motion_get_frame(struct motion *motion);
|
||||
bool RE_motion_set_frame(struct motion *motion, float frame);
|
||||
bool RE_motion_set_frame_range(struct motion *motion, float begin, float end);
|
||||
bool RE_motion_set_loop_frame_range(struct motion *motion, float begin, float end);
|
||||
|
||||
void RE_render(struct sact_sprite *sp);
|
||||
void RE_debug_print(struct RE_plugin *p);
|
||||
|
||||
+20
-2
@@ -18,12 +18,30 @@ uniform mat4 local_transform;
|
||||
uniform mat4 view_transform;
|
||||
uniform mat4 proj_transform;
|
||||
|
||||
const int MAX_BONES = 211; // see 3d_internal.h
|
||||
const int NR_WEIGHTS = 4;
|
||||
uniform bool has_bones;
|
||||
uniform mat4 bone_matrices[MAX_BONES];
|
||||
|
||||
in vec3 vertex_pos;
|
||||
in vec3 vertex_normal;
|
||||
in vec2 vertex_uv;
|
||||
in ivec4 vertex_bone_index;
|
||||
in vec4 vertex_bone_weight;
|
||||
|
||||
out vec2 tex_coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = proj_transform * view_transform * local_transform * vec4(vertex_pos, 1.0);
|
||||
tex_coord = vertex_uv;
|
||||
mat4 bone_transform = mat4(1.0f);
|
||||
if (has_bones) {
|
||||
bone_transform = mat4(0.f);
|
||||
for (int i = 0; i < NR_WEIGHTS; i++) {
|
||||
if (vertex_bone_index[i] >= 0) {
|
||||
bone_transform += bone_matrices[vertex_bone_index[i]] * vertex_bone_weight[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gl_Position = proj_transform * view_transform * local_transform * bone_transform * vec4(vertex_pos, 1.0);
|
||||
tex_coord = vertex_uv;
|
||||
}
|
||||
|
||||
+54
-1
@@ -24,12 +24,17 @@
|
||||
#include "gfx/gl.h"
|
||||
#include "gfx/gfx.h"
|
||||
|
||||
#define MAX_BONES 211 // Maximum in TT3
|
||||
|
||||
struct model {
|
||||
char *name;
|
||||
char *path;
|
||||
int nr_meshes;
|
||||
struct mesh *meshes;
|
||||
int nr_materials;
|
||||
struct material *materials;
|
||||
int nr_bones;
|
||||
struct bone *bones;
|
||||
struct hash_table *bone_map; // bone id in POL/MOT -> struct bone *
|
||||
};
|
||||
|
||||
struct mesh {
|
||||
@@ -44,6 +49,22 @@ struct material {
|
||||
bool opaque;
|
||||
};
|
||||
|
||||
struct bone {
|
||||
char *name;
|
||||
int index; // index on model->bones
|
||||
int parent; // index on model->bones, or -1
|
||||
mat4 inverse_bind_matrix;
|
||||
};
|
||||
|
||||
struct motion {
|
||||
struct mot *mot;
|
||||
char *name;
|
||||
int state;
|
||||
float current_frame;
|
||||
float frame_begin, frame_end;
|
||||
float loop_frame_begin, loop_frame_end;
|
||||
};
|
||||
|
||||
struct RE_renderer {
|
||||
struct shader shader;
|
||||
GLuint depth_buffer;
|
||||
@@ -51,10 +72,17 @@ struct RE_renderer {
|
||||
// Uniform variable locations
|
||||
GLint local_transform;
|
||||
GLint proj_transform;
|
||||
GLint has_bones;
|
||||
GLint bone_matrices;
|
||||
|
||||
// Attribute variable locations
|
||||
GLint vertex_normal;
|
||||
GLint vertex_uv;
|
||||
GLint vertex_bone_index;
|
||||
GLint vertex_bone_weight;
|
||||
|
||||
mat4 bone_transforms[MAX_BONES];
|
||||
uint32_t last_frame_timestamp;
|
||||
};
|
||||
|
||||
// model.c
|
||||
@@ -62,6 +90,9 @@ struct RE_renderer {
|
||||
struct model *model_load(struct archive *aar, const char *path, struct RE_renderer *renderer);
|
||||
void model_free(struct model *model);
|
||||
|
||||
struct motion *motion_load(const char *name, struct model *model, struct archive *aar);
|
||||
void motion_free(struct motion *motion);
|
||||
|
||||
// renderer.c
|
||||
|
||||
struct RE_renderer *RE_renderer_new(struct texture *texture);
|
||||
@@ -132,7 +163,29 @@ struct pol_bone {
|
||||
versor rotq;
|
||||
};
|
||||
|
||||
struct mot {
|
||||
uint32_t nr_frames;
|
||||
uint32_t nr_bones;
|
||||
struct mot_bone *motions[];
|
||||
};
|
||||
|
||||
struct mot_frame {
|
||||
vec3 pos;
|
||||
versor rotq;
|
||||
};
|
||||
|
||||
struct mot_bone {
|
||||
char *name;
|
||||
uint32_t id;
|
||||
uint32_t parent;
|
||||
struct mot_frame frames[];
|
||||
};
|
||||
|
||||
struct pol *pol_parse(uint8_t *data, size_t size);
|
||||
void pol_free(struct pol *pol);
|
||||
struct pol_bone *pol_find_bone(struct pol *pol, uint32_t id);
|
||||
|
||||
struct mot *mot_parse(uint8_t *data, size_t size);
|
||||
void mot_free(struct mot *mot);
|
||||
|
||||
#endif /* SYSTEM4_3D_3D_INTERNAL_H */
|
||||
|
||||
+151
-4
@@ -21,14 +21,19 @@
|
||||
#include "system4.h"
|
||||
#include "system4/aar.h"
|
||||
#include "system4/cg.h"
|
||||
#include "system4/hashtable.h"
|
||||
|
||||
#include "3d_internal.h"
|
||||
#include "reign.h"
|
||||
|
||||
#define NR_WEIGHTS 4
|
||||
|
||||
struct vertex {
|
||||
GLfloat pos[3];
|
||||
GLfloat normal[3];
|
||||
GLfloat uv[2];
|
||||
GLint bone_id[NR_WEIGHTS];
|
||||
GLfloat bone_weight[NR_WEIGHTS];
|
||||
};
|
||||
|
||||
static bool init_material(struct material *material, const struct pol_material *m, struct archive *aar, const char *path)
|
||||
@@ -75,6 +80,25 @@ static void destroy_material(struct material *material)
|
||||
glDeleteTextures(1, &material->color_map);
|
||||
}
|
||||
|
||||
static int cmp_by_bone_weight(const void *lhs, const void *rhs)
|
||||
{
|
||||
float l = ((struct pol_bone_weight *)lhs)->weight;
|
||||
float r = ((struct pol_bone_weight *)rhs)->weight;
|
||||
return (l < r) - (l > r); // descending order.
|
||||
}
|
||||
|
||||
static void sort_and_normalize_bone_weights(struct pol_vertex *v)
|
||||
{
|
||||
qsort(v->weights, v->nr_weights, sizeof(struct pol_bone_weight), cmp_by_bone_weight);
|
||||
float total = 0.0;
|
||||
for (uint32_t i = 0; i < v->nr_weights && i < NR_WEIGHTS; i++) {
|
||||
total += v->weights[i].weight;
|
||||
}
|
||||
for (uint32_t i = 0; i < v->nr_weights && i < NR_WEIGHTS; i++) {
|
||||
v->weights[i].weight /= total;
|
||||
}
|
||||
}
|
||||
|
||||
static void add_mesh(struct model *model, struct pol_mesh *m, int material_index, int material, struct RE_renderer *r)
|
||||
{
|
||||
struct vertex *buf = xmalloc(m->nr_triangles * 3 * sizeof(struct vertex));
|
||||
@@ -84,9 +108,23 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index
|
||||
if (material_index >= 0 && t->material != (uint32_t)material_index)
|
||||
continue;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
glm_vec3_copy(m->vertices[t->vert_index[j]].pos, buf[v].pos);
|
||||
struct pol_vertex *vert = &m->vertices[t->vert_index[j]];
|
||||
glm_vec3_copy(vert->pos, buf[v].pos);
|
||||
glm_vec3_copy(t->normals[j], buf[v].normal);
|
||||
glm_vec2_copy(m->uvs[t->uv_index[j]], buf[v].uv);
|
||||
sort_and_normalize_bone_weights(vert);
|
||||
for (uint32_t k = 0; k < NR_WEIGHTS; k++) {
|
||||
if (model->bone_map && k < vert->nr_weights) {
|
||||
struct bone *bone = ht_get_int(model->bone_map, vert->weights[k].bone, NULL);
|
||||
if (!bone)
|
||||
WARNING("%s: invalid bone id in vertex data", model->path);
|
||||
buf[v].bone_id[k] = bone ? bone->index : -1;
|
||||
buf[v].bone_weight[k] = vert->weights[k].weight;
|
||||
} else {
|
||||
buf[v].bone_id[k] = -1;
|
||||
buf[v].bone_weight[k] = 0.0;
|
||||
}
|
||||
}
|
||||
v++;
|
||||
}
|
||||
}
|
||||
@@ -107,9 +145,13 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index
|
||||
glEnableVertexAttribArray(r->shader.vertex);
|
||||
glVertexAttribPointer(r->shader.vertex, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (const void *)0);
|
||||
glEnableVertexAttribArray(r->vertex_normal);
|
||||
glVertexAttribPointer(r->vertex_normal, 3, GL_FLOAT, GL_TRUE, sizeof(struct vertex), (const void *)offsetof(struct vertex, normal));
|
||||
glVertexAttribPointer(r->vertex_normal, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (const void *)offsetof(struct vertex, normal));
|
||||
glEnableVertexAttribArray(r->vertex_uv);
|
||||
glVertexAttribPointer(r->vertex_uv, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (const void *)offsetof(struct vertex, uv));
|
||||
glEnableVertexAttribArray(r->vertex_bone_index);
|
||||
glVertexAttribIPointer(r->vertex_bone_index, NR_WEIGHTS, GL_INT, sizeof(struct vertex), (const void *)offsetof(struct vertex, bone_id));
|
||||
glEnableVertexAttribArray(r->vertex_bone_weight);
|
||||
glVertexAttribPointer(r->vertex_bone_weight, NR_WEIGHTS, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (const void *)offsetof(struct vertex, bone_weight));
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->nr_vertices * sizeof(struct vertex), buf, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(0);
|
||||
@@ -124,6 +166,39 @@ static void destroy_mesh(struct mesh *mesh)
|
||||
glDeleteBuffers(1, &mesh->attr_buffer);
|
||||
}
|
||||
|
||||
static struct bone *add_bone(struct model *model, struct pol *pol, struct pol_bone *pol_bone)
|
||||
{
|
||||
struct bone *bone = ht_get_int(model->bone_map, pol_bone->id, NULL);
|
||||
if (bone)
|
||||
return bone; // already added.
|
||||
|
||||
struct bone *parent = NULL;
|
||||
if (pol_bone->parent >= 0) {
|
||||
// Parent bone must appear before its children in model->bones.
|
||||
struct pol_bone *pol_parent = pol_find_bone(pol, pol_bone->parent);
|
||||
if (!pol_parent)
|
||||
ERROR("Parent bone of \"%s\" is not found", pol_bone->name);
|
||||
parent = add_bone(model, pol, pol_parent);
|
||||
}
|
||||
|
||||
bone = &model->bones[model->nr_bones];
|
||||
ht_put_int(model->bone_map, pol_bone->id, bone);
|
||||
bone->name = strdup(pol_bone->name);
|
||||
bone->index = model->nr_bones;
|
||||
bone->parent = parent ? parent->index : -1;
|
||||
|
||||
glm_quat_mat4(pol_bone->rotq, bone->inverse_bind_matrix);
|
||||
glm_translate(bone->inverse_bind_matrix, pol_bone->pos);
|
||||
|
||||
model->nr_bones++;
|
||||
return bone;
|
||||
}
|
||||
|
||||
static void destroy_bone(struct bone *bone)
|
||||
{
|
||||
free(bone->name);
|
||||
}
|
||||
|
||||
struct model *model_load(struct archive *aar, const char *path, struct RE_renderer *r)
|
||||
{
|
||||
if (path[0] == '\0')
|
||||
@@ -148,9 +223,23 @@ struct model *model_load(struct archive *aar, const char *path, struct RE_render
|
||||
free(polname);
|
||||
return NULL;
|
||||
}
|
||||
free(polname);
|
||||
|
||||
struct model *model = xcalloc(1, sizeof(struct model));
|
||||
model->name = polname;
|
||||
model->path = strdup(path);
|
||||
|
||||
// Bones
|
||||
if (pol->nr_bones > 0) {
|
||||
if (pol->nr_bones > MAX_BONES)
|
||||
ERROR("%s: Too many bones (%u)", model->path, pol->nr_bones);
|
||||
model->bone_map = ht_create(pol->nr_bones * 3 / 2);
|
||||
model->bones = xcalloc(pol->nr_bones, sizeof(struct bone));
|
||||
for (uint32_t i = 0; i < pol->nr_bones; i++) {
|
||||
add_bone(model, pol, &pol->bones[i]);
|
||||
}
|
||||
if (model->nr_bones != (int)pol->nr_bones)
|
||||
ERROR("%s: Broken bone data", model->path);
|
||||
}
|
||||
|
||||
// Materials
|
||||
int *material_offsets = xmalloc(pol->nr_materials * sizeof(int));
|
||||
@@ -204,6 +293,64 @@ void model_free(struct model *model)
|
||||
destroy_material(&model->materials[i]);
|
||||
free(model->materials);
|
||||
|
||||
free(model->name);
|
||||
for (int i = 0; i < model->nr_bones; i++)
|
||||
destroy_bone(&model->bones[i]);
|
||||
free(model->bones);
|
||||
if (model->bone_map)
|
||||
ht_free_int(model->bone_map);
|
||||
|
||||
free(model->path);
|
||||
free(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;
|
||||
}
|
||||
|
||||
struct motion *motion_load(const char *name, struct model *model, struct archive *aar)
|
||||
{
|
||||
char *motname = xmalloc(strlen(model->path) + strlen(name) + 6);
|
||||
sprintf(motname, "%s\\%s.MOT", model->path, name);
|
||||
|
||||
struct archive_data *dfile = archive_get_by_name(aar, motname);
|
||||
if (!dfile) {
|
||||
WARNING("%s: not found", motname);
|
||||
free(motname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mot *mot = mot_parse(dfile->data, dfile->size);
|
||||
archive_free_data(dfile);
|
||||
if (!mot) {
|
||||
WARNING("%s: parse error", motname);
|
||||
free(motname);
|
||||
return NULL;
|
||||
}
|
||||
free(motname);
|
||||
|
||||
if (model->nr_bones != (int)mot->nr_bones)
|
||||
ERROR("%s: wrong number of bones. Expected %d but got %d", name, model->nr_bones, mot->nr_bones);
|
||||
|
||||
// Reorder mot->motions so that motion for model->bones[i] can be
|
||||
// accessed by mot->motions[i].
|
||||
for (uint32_t i = 0; i < mot->nr_bones; i++) {
|
||||
struct bone *bone = ht_get_int(model->bone_map, mot->motions[i]->id, NULL);
|
||||
if (!bone)
|
||||
ERROR("%s: invalid bone id %d", name, mot->motions[i]->id);
|
||||
mot->motions[i]->id = bone->index;
|
||||
}
|
||||
qsort(mot->motions, mot->nr_bones, sizeof(struct mot_bone *), cmp_motions_by_bone_id);
|
||||
|
||||
struct motion *motion = xcalloc(1, sizeof(struct motion));
|
||||
motion->mot = mot;
|
||||
motion->name = strdup(name);
|
||||
return motion;
|
||||
}
|
||||
|
||||
void motion_free(struct motion *motion)
|
||||
{
|
||||
mot_free(motion->mot);
|
||||
free(motion->name);
|
||||
free(motion);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ static void read_quaternion(struct buffer *r, versor q)
|
||||
float y = -buffer_read_float(r);
|
||||
float z = buffer_read_float(r);
|
||||
glm_quat_init(q, x, y, z, w);
|
||||
glm_quat_normalize(q);
|
||||
}
|
||||
|
||||
static void parse_material(struct buffer *r, struct pol_material *m)
|
||||
@@ -284,3 +285,57 @@ void pol_free(struct pol *pol)
|
||||
free(pol->bones);
|
||||
free(pol);
|
||||
}
|
||||
|
||||
struct pol_bone *pol_find_bone(struct pol *pol, uint32_t id)
|
||||
{
|
||||
for (uint32_t i = 0; i < pol->nr_bones; i++) {
|
||||
if (pol->bones[i].id == id)
|
||||
return &pol->bones[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mot *mot_parse(uint8_t *data, size_t size)
|
||||
{
|
||||
struct buffer r;
|
||||
buffer_init(&r, data, size);
|
||||
if (memcmp(buffer_strdata(&r), "MOT\0", 4))
|
||||
return NULL;
|
||||
buffer_skip(&r, 4);
|
||||
uint32_t version = buffer_read_int32(&r);
|
||||
if (version != 0) {
|
||||
WARNING("unknown MOT version: %d", version);
|
||||
return NULL;
|
||||
}
|
||||
uint32_t nr_frames = buffer_read_int32(&r);
|
||||
uint32_t nr_bones = buffer_read_int32(&r);
|
||||
|
||||
struct mot *mot = xcalloc(1, sizeof(struct mot) + nr_bones * sizeof(struct mot_bone *));
|
||||
mot->nr_frames = nr_frames;
|
||||
mot->nr_bones = nr_bones;
|
||||
for (uint32_t i = 0; i < nr_bones; i++) {
|
||||
struct mot_bone *m = xcalloc(1, sizeof(struct mot_bone) + sizeof(struct mot_frame) * nr_frames);
|
||||
m->name = read_cstring(&r);
|
||||
m->id = buffer_read_int32(&r);
|
||||
m->parent = buffer_read_int32(&r);
|
||||
for (uint32_t j = 0; j < nr_frames; j++) {
|
||||
read_position(&r, m->frames[j].pos);
|
||||
read_quaternion(&r, m->frames[j].rotq);
|
||||
buffer_skip(&r, 16); // another quaternion?
|
||||
}
|
||||
mot->motions[i] = m;
|
||||
}
|
||||
if (buffer_remaining(&r) != 0) {
|
||||
WARNING("extra data at end");
|
||||
}
|
||||
return mot;
|
||||
}
|
||||
|
||||
void mot_free(struct mot *mot)
|
||||
{
|
||||
for (uint32_t i = 0; i < mot->nr_bones; i++) {
|
||||
free(mot->motions[i]->name);
|
||||
free(mot->motions[i]);
|
||||
}
|
||||
free(mot);
|
||||
}
|
||||
|
||||
+130
-15
@@ -35,14 +35,34 @@ static struct RE_instance *create_instance(struct RE_plugin *plugin)
|
||||
instance->scale[0] = 1.0;
|
||||
instance->scale[1] = 1.0;
|
||||
instance->scale[2] = 1.0;
|
||||
instance->fps = 30.0;
|
||||
glm_mat4_identity(instance->local_transform);
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void unload_instance(struct RE_instance *instance)
|
||||
{
|
||||
if (instance->motion) {
|
||||
motion_free(instance->motion);
|
||||
instance->motion = NULL;
|
||||
}
|
||||
if (instance->next_motion) {
|
||||
motion_free(instance->next_motion);
|
||||
instance->next_motion = NULL;
|
||||
}
|
||||
if (instance->model) {
|
||||
model_free(instance->model);
|
||||
instance->model = NULL;
|
||||
}
|
||||
if (instance->bone_transforms) {
|
||||
free(instance->bone_transforms);
|
||||
instance->bone_transforms = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_instance(struct RE_instance *instance)
|
||||
{
|
||||
if (instance->model)
|
||||
model_free(instance->model);
|
||||
unload_instance(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
@@ -138,29 +158,124 @@ bool RE_instance_load(struct RE_instance *instance, const char *name)
|
||||
{
|
||||
if (!instance)
|
||||
return false;
|
||||
if (instance->model)
|
||||
model_free(instance->model);
|
||||
unload_instance(instance);
|
||||
instance->model = model_load(instance->plugin->aar, name, instance->plugin->renderer);
|
||||
if (instance->model && instance->model->nr_bones > 0)
|
||||
instance->bone_transforms = xcalloc(instance->model->nr_bones, sizeof(mat4));
|
||||
return !!instance->model;
|
||||
}
|
||||
|
||||
bool RE_instance_load_motion(struct RE_instance *instance, const char *name)
|
||||
{
|
||||
if (!instance || !instance->model)
|
||||
return false;
|
||||
instance->motion = motion_load(name, instance->model, instance->plugin->aar);
|
||||
return !!instance->motion;
|
||||
}
|
||||
|
||||
bool RE_instance_load_next_motion(struct RE_instance *instance, const char *name)
|
||||
{
|
||||
if (!instance || !instance->model)
|
||||
return false;
|
||||
instance->next_motion = motion_load(name, instance->model, instance->plugin->aar);
|
||||
return !!instance->next_motion;
|
||||
}
|
||||
|
||||
bool RE_instance_free_next_motion(struct RE_instance *instance)
|
||||
{
|
||||
if (!instance || !instance->next_motion)
|
||||
return false;
|
||||
motion_free(instance->next_motion);
|
||||
instance->next_motion = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
int RE_motion_get_state(struct motion *motion)
|
||||
{
|
||||
return motion ? motion->state : RE_MOTION_STATE_STOP;
|
||||
}
|
||||
|
||||
bool RE_motion_set_state(struct motion *motion, int state)
|
||||
{
|
||||
if (!motion)
|
||||
return false;
|
||||
motion->state = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
float RE_motion_get_frame(struct motion *motion)
|
||||
{
|
||||
return motion ? motion->current_frame : 0.0;
|
||||
}
|
||||
|
||||
bool RE_motion_set_frame(struct motion *motion, float frame)
|
||||
{
|
||||
if (!motion)
|
||||
return false;
|
||||
motion->current_frame = frame;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_motion_set_frame_range(struct motion *motion, float begin, float end)
|
||||
{
|
||||
if (!motion)
|
||||
return false;
|
||||
motion->frame_begin = begin;
|
||||
motion->frame_end = end;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_motion_set_loop_frame_range(struct motion *motion, float begin, float end)
|
||||
{
|
||||
if (!motion)
|
||||
return false;
|
||||
motion->loop_frame_begin = begin;
|
||||
motion->loop_frame_end = end;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void print_motion(const char *name, struct motion *m, int indent)
|
||||
{
|
||||
const char *state;
|
||||
switch (m->state) {
|
||||
case RE_MOTION_STATE_STOP: state = "STOP"; break;
|
||||
case RE_MOTION_STATE_NOLOOP: state = "NOLOOP"; break;
|
||||
case RE_MOTION_STATE_LOOP: state = "LOOP"; break;
|
||||
default: state = "?"; break;
|
||||
}
|
||||
indent_printf(indent, "%s = {name=\"%s\", state=%s, frame=%f},\n",
|
||||
name, m->name, state, m->current_frame);
|
||||
}
|
||||
|
||||
void RE_debug_print(struct RE_plugin *p)
|
||||
{
|
||||
printf("camera = { x: %f, y: %f, z: %f, pitch: %f, roll: %f, yaw: %f }",
|
||||
p->camera.pos[0], p->camera.pos[1], p->camera.pos[2],
|
||||
p->camera.pitch, p->camera.roll, p->camera.yaw);
|
||||
int indent = 0;
|
||||
indent_printf(indent, "camera = {x=%f, y=%f, z=%f, pitch=%f, roll=%f, yaw=%f},\n",
|
||||
p->camera.pos[0], p->camera.pos[1], p->camera.pos[2],
|
||||
p->camera.pitch, p->camera.roll, p->camera.yaw);
|
||||
|
||||
for (int i = 0; i < RE_MAX_INSTANCES; i++) {
|
||||
struct RE_instance *inst = p->instances[i];
|
||||
if (!inst || !inst->model)
|
||||
continue;
|
||||
printf("[%d] = {", i);
|
||||
printf(" name: \"%s\",", inst->model->name);
|
||||
printf(" type: %d,", inst->type);
|
||||
printf(" draw: %d,", inst->draw);
|
||||
printf(" pos: { x: %f, y: %f, z: %f },", inst->pos[0], inst->pos[1], inst->pos[2]);
|
||||
printf(" vec: { x: %f, y: %f, z: %f },", inst->vec[0], inst->vec[1], inst->vec[2]);
|
||||
printf(" scale: { x: %f, y: %f, z: %f },", inst->scale[0], inst->scale[1], inst->scale[2]);
|
||||
printf("}");
|
||||
indent_printf(indent, "instance[%d] = {\n", i);
|
||||
indent++;
|
||||
|
||||
indent_printf(indent, "path = \"%s\",\n", inst->model->path);
|
||||
indent_printf(indent, "type = %d,\n", inst->type);
|
||||
indent_printf(indent, "draw = %d,\n", inst->draw);
|
||||
indent_printf(indent, "pos = {x=%f, y=%f, z=%f},\n", inst->pos[0], inst->pos[1], inst->pos[2]);
|
||||
indent_printf(indent, "vec = {x=%f, y=%f, z=%f},\n", inst->vec[0], inst->vec[1], inst->vec[2]);
|
||||
indent_printf(indent, "scale = {x=%f, y=%f, z=%f},\n", inst->scale[0], inst->scale[1], inst->scale[2]);
|
||||
if (inst->motion)
|
||||
print_motion("motion", inst->motion, indent);
|
||||
if (inst->next_motion)
|
||||
print_motion("next_motion", inst->next_motion, indent);
|
||||
indent_printf(indent, "fps = %f,\n", inst->fps);
|
||||
if (inst->motion_blend)
|
||||
indent_printf(indent, "motion_blend_rate = %f,\n", inst->motion_blend_rate);
|
||||
|
||||
indent--;
|
||||
indent_printf(indent, "},\n");
|
||||
}
|
||||
}
|
||||
|
||||
+91
-3
@@ -14,6 +14,7 @@
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <cglm/cglm.h>
|
||||
|
||||
#include "system4.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "3d_internal.h"
|
||||
#include "reign.h"
|
||||
#include "sact.h"
|
||||
#include "vm.h"
|
||||
|
||||
struct RE_renderer *RE_renderer_new(struct texture *texture)
|
||||
{
|
||||
@@ -29,14 +31,19 @@ struct RE_renderer *RE_renderer_new(struct texture *texture)
|
||||
gfx_load_shader(&r->shader, "shaders/reign.v.glsl", "shaders/reign.f.glsl");
|
||||
r->local_transform = glGetUniformLocation(r->shader.program, "local_transform");
|
||||
r->proj_transform = glGetUniformLocation(r->shader.program, "proj_transform");
|
||||
r->has_bones = glGetUniformLocation(r->shader.program, "has_bones");
|
||||
r->bone_matrices = glGetUniformLocation(r->shader.program, "bone_matrices");
|
||||
r->vertex_normal = glGetAttribLocation(r->shader.program, "vertex_normal");
|
||||
r->vertex_uv = glGetAttribLocation(r->shader.program, "vertex_uv");
|
||||
r->vertex_bone_index = glGetAttribLocation(r->shader.program, "vertex_bone_index");
|
||||
r->vertex_bone_weight = glGetAttribLocation(r->shader.program, "vertex_bone_weight");
|
||||
|
||||
glGenRenderbuffers(1, &r->depth_buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, r->depth_buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, texture->w, texture->h);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
r->last_frame_timestamp = SDL_GetTicks();
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -79,7 +86,71 @@ static void update_local_transform(struct RE_instance *inst)
|
||||
inst->local_transform_needs_update = false;
|
||||
}
|
||||
|
||||
static void render_instance(struct RE_instance *inst, struct RE_renderer *r, mat4 view_transform, mat4 proj_transform)
|
||||
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);
|
||||
|
||||
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_instance(struct RE_instance *inst, struct RE_renderer *r, mat4 view_transform, mat4 proj_transform, float delta_time)
|
||||
{
|
||||
if (!inst->draw || !inst->model)
|
||||
return;
|
||||
@@ -87,11 +158,20 @@ static void render_instance(struct RE_instance *inst, struct RE_renderer *r, mat
|
||||
if (inst->local_transform_needs_update)
|
||||
update_local_transform(inst);
|
||||
|
||||
animate(inst, r, delta_time);
|
||||
|
||||
glUseProgram(r->shader.program);
|
||||
glUniformMatrix4fv(r->shader.view_transform, 1, GL_FALSE, view_transform[0]);
|
||||
glUniformMatrix4fv(r->proj_transform, 1, GL_FALSE, proj_transform[0]);
|
||||
glUniformMatrix4fv(r->local_transform, 1, GL_FALSE, inst->local_transform[0]);
|
||||
|
||||
if (inst->model->nr_bones > 0) {
|
||||
glUniform1i(r->has_bones, GL_TRUE);
|
||||
glUniformMatrix4fv(r->bone_matrices, inst->model->nr_bones, GL_FALSE, r->bone_transforms[0][0]);
|
||||
} else {
|
||||
glUniform1i(r->has_bones, GL_FALSE);
|
||||
}
|
||||
|
||||
struct model *model = inst->model;
|
||||
for (int i = 0; i < model->nr_meshes; i++) {
|
||||
struct mesh *mesh = &model->meshes[i];
|
||||
@@ -110,13 +190,19 @@ static void render_instance(struct RE_instance *inst, struct RE_renderer *r, mat
|
||||
|
||||
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)
|
||||
if (!r) {
|
||||
r->last_frame_timestamp = timestamp;
|
||||
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)
|
||||
@@ -140,7 +226,7 @@ void RE_render(struct sact_sprite *sp)
|
||||
|
||||
for (int i = 0; i < RE_MAX_INSTANCES; i++) {
|
||||
if (plugin->instances[i])
|
||||
render_instance(plugin->instances[i], r, view_transform, plugin->proj_transform);
|
||||
render_instance(plugin->instances[i], r, view_transform, plugin->proj_transform, delta_time);
|
||||
}
|
||||
|
||||
plugin->proj_transform[1][1] *= -1;
|
||||
@@ -149,4 +235,6 @@ void RE_render(struct sact_sprite *sp)
|
||||
glDisable(GL_CULL_FACE);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
gfx_reset_framebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||
|
||||
r->last_frame_timestamp = timestamp;
|
||||
}
|
||||
|
||||
+143
-32
@@ -42,6 +42,18 @@ static struct RE_instance *get_instance(unsigned plugin, unsigned instance)
|
||||
return instance < RE_MAX_INSTANCES ? rp->instances[instance] : NULL;
|
||||
}
|
||||
|
||||
static struct motion *get_motion(unsigned plugin, unsigned instance)
|
||||
{
|
||||
struct RE_instance *inst = get_instance(plugin, instance);
|
||||
return inst ? inst->motion : NULL;
|
||||
}
|
||||
|
||||
static struct motion *get_next_motion(unsigned plugin, unsigned instance)
|
||||
{
|
||||
struct RE_instance *inst = get_instance(plugin, instance);
|
||||
return inst ? inst->next_motion : NULL;
|
||||
}
|
||||
|
||||
static int ReignEngine_CreatePlugin(void)
|
||||
{
|
||||
for (int i = 0; i < RE_MAX_PLUGINS; i++) {
|
||||
@@ -239,25 +251,110 @@ static bool ReignEngine_GetInstanceDraw(int plugin, int instance)
|
||||
//bool ReignEngine_GetInstanceDrawBump(int plugin, int instance);
|
||||
//int ReignEngine_GetInstanceDrawType(int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceDrawType, int plugin, int instance, int draw_type);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, LoadInstanceMotion, int plugin, int instance, struct string *name);
|
||||
HLL_WARN_UNIMPLEMENTED(0, int, ReignEngine, GetInstanceMotionState, int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(0.0, float, ReignEngine, GetInstanceMotionFrame, int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceMotionState, int plugin, int instance, int state);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceMotionFrame, int plugin, int instance, float frame);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceMotionFrameRange, int plugin, int instance, float begin_frame, float end_frame);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceMotionLoopFrameRange, int plugin, int instance, float begin_frame, float end_frame);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, LoadInstanceNextMotion, int plugin, int instance, struct string *name);
|
||||
//bool ReignEngine_SetInstanceNextMotionState(int plugin, int instance, int nState);
|
||||
//bool ReignEngine_SetInstanceNextMotionFrame(int plugin, int instance, float fFrame);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceNextMotionFrameRange, int plugin, int instance, float begin_frame, float end_frame);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceNextMotionLoopFrameRange, int plugin, int instance, float begin_frame, float end_frame);
|
||||
//bool ReignEngine_SetInstanceMotionBlendRate(int plugin, int instance, float fRate);
|
||||
//bool ReignEngine_SetInstanceMotionBlend(int plugin, int instance, bool bMotionBlend);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, IsInstanceMotionBlend, int plugin, int instance);
|
||||
|
||||
bool ReignEngine_LoadInstanceMotion(int plugin, int instance, struct string *name)
|
||||
{
|
||||
return RE_instance_load_motion(get_instance(plugin, instance), name->text);
|
||||
}
|
||||
|
||||
static int ReignEngine_GetInstanceMotionState(int plugin, int instance)
|
||||
{
|
||||
return RE_motion_get_state(get_motion(plugin, instance));
|
||||
}
|
||||
|
||||
static float ReignEngine_GetInstanceMotionFrame(int plugin, int instance)
|
||||
{
|
||||
return RE_motion_get_frame(get_motion(plugin, instance));
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceMotionState(int plugin, int instance, int state)
|
||||
{
|
||||
return RE_motion_set_state(get_motion(plugin, instance), state);
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceMotionFrame(int plugin, int instance, float frame)
|
||||
{
|
||||
return RE_motion_set_frame(get_motion(plugin, instance), frame);
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceMotionFrameRange(int plugin, int instance, float begin_frame, float end_frame)
|
||||
{
|
||||
return RE_motion_set_frame_range(get_motion(plugin, instance), begin_frame, end_frame);
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceMotionLoopFrameRange(int plugin, int instance, float begin_frame, float end_frame)
|
||||
{
|
||||
return RE_motion_set_loop_frame_range(get_motion(plugin, instance), begin_frame, end_frame);
|
||||
}
|
||||
|
||||
static bool ReignEngine_LoadInstanceNextMotion(int plugin, int instance, struct string *name)
|
||||
{
|
||||
return RE_instance_load_next_motion(get_instance(plugin, instance), name->text);
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceNextMotionState(int plugin, int instance, int state)
|
||||
{
|
||||
return RE_motion_set_state(get_next_motion(plugin, instance), state);
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceNextMotionFrame(int plugin, int instance, float frame)
|
||||
{
|
||||
return RE_motion_set_frame(get_next_motion(plugin, instance), frame);
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceNextMotionFrameRange(int plugin, int instance, float begin_frame, float end_frame)
|
||||
{
|
||||
return RE_motion_set_frame_range(get_next_motion(plugin, instance), begin_frame, end_frame);
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceNextMotionLoopFrameRange(int plugin, int instance, float begin_frame, float end_frame)
|
||||
{
|
||||
return RE_motion_set_loop_frame_range(get_next_motion(plugin, instance), begin_frame, end_frame);
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceMotionBlendRate(int plugin, int instance, float rate)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
ri->motion_blend_rate = rate;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceMotionBlend(int plugin, int instance, bool motion_blend)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
ri->motion_blend = motion_blend;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReignEngine_IsInstanceMotionBlend(int plugin, int instance)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
return ri ? ri->motion_blend : false;
|
||||
}
|
||||
|
||||
//bool ReignEngine_GetInstanceMotionBlendPutTime(int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceMotionBlendPutTime, int plugin, int instance, bool flag);
|
||||
//bool ReignEngine_SwapInstanceMotion(int plugin, int instance);
|
||||
//bool ReignEngine_FreeInstanceNextMotion(int plugin, int instance);
|
||||
|
||||
static bool ReignEngine_SwapInstanceMotion(int plugin, int instance)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
struct motion *tmp = ri->motion;
|
||||
ri->motion = ri->next_motion;
|
||||
ri->next_motion = tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReignEngine_FreeInstanceNextMotion(int plugin, int instance)
|
||||
{
|
||||
return RE_instance_free_next_motion(get_instance(plugin, instance));
|
||||
}
|
||||
|
||||
//int ReignEngine_GetInstanceNumofMaterial(int plugin, int instance);
|
||||
//bool ReignEngine_GetInstanceMaterialName(int plugin, int instance, int num, struct string **pIName);
|
||||
//float ReignEngine_GetInstanceMaterialParam(int plugin, int instance, int nMaterial, int type);
|
||||
@@ -281,8 +378,22 @@ HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceColumnAngle, int plu
|
||||
//bool ReignEngine_SetInstanceDrawColumn(int plugin, int instance, bool bDraw);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceTarget, int plugin, int instance, int index, int target);
|
||||
//int ReignEngine_GetInstanceTarget(int plugin, int instance, int index);
|
||||
//float ReignEngine_GetInstanceFPS(int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceFPS, int plugin, int instance, float fps);
|
||||
|
||||
static float ReignEngine_GetInstanceFPS(int plugin, int instance)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
return ri ? ri->fps : 0.0;
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceFPS(int plugin, int instance, float fps)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
ri->fps = fps;
|
||||
return true;
|
||||
}
|
||||
|
||||
HLL_WARN_UNIMPLEMENTED(0, int, ReignEngine, GetInstanceBoneIndex, int plugin, int instance, struct string *name);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, TransInstanceLocalPosToWorldPosByBone, int plugin, int instance, int bone, float offset_x, float offset_y, float offset_z, float *x, float *y, float *z);
|
||||
//int ReignEngine_GetInstanceNumofPolygon(int plugin, int instance);
|
||||
@@ -304,7 +415,7 @@ HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, GetEffectFrameRange, int plugin
|
||||
//float ReignEngine_GetEffectObjectMoveCurve(int plugin, int instance, int nObject);
|
||||
//void ReignEngine_GetEffectObjectFrame(int plugin, int instance, int nObject, int *pnBeginFrame, int *pnEndFrame);
|
||||
//int ReignEngine_GetEffectObjectStopFrame(int plugin, int instance, int nObject);
|
||||
//int ReignEngine_GetEffectNumofObject(int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(0, int, ReignEngine, GetEffectNumofObject, int plugin, int instance);
|
||||
//void ReignEngine_GetEffectObjectName(int plugin, int instance, int nObject, struct string **pIName);
|
||||
//int ReignEngine_GetEffectNumofObjectPos(int plugin, int instance, int nObject);
|
||||
//int ReignEngine_GetEffectNumofObjectPosUnit(int plugin, int instance, int nObject, int nPos);
|
||||
@@ -417,8 +528,8 @@ HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, GetEffectFrameRange, int plugin
|
||||
//float ReignEngine_GetEffectObjectOffsetY(int plugin, int instance, int nObject);
|
||||
//bool ReignEngine_SetEffectObjectOffsetX(int plugin, int instance, int nObject, float fOffsetX);
|
||||
//bool ReignEngine_SetEffectObjectOffsetY(int plugin, int instance, int nObject, float fOffsetY);
|
||||
//bool ReignEngine_GetCameraQuakeEffectFlag(int plugin, int instance);
|
||||
//bool ReignEngine_SetCameraQuakeEffectFlag(int plugin, int instance, bool flag);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, GetCameraQuakeEffectFlag, int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetCameraQuakeEffectFlag, int plugin, int instance, bool flag);
|
||||
|
||||
bool ReignEngine_SetCameraPos(int plugin, float x, float y, float z)
|
||||
{
|
||||
@@ -928,17 +1039,17 @@ HLL_LIBRARY(ReignEngine,
|
||||
HLL_EXPORT(SetInstanceMotionFrameRange, ReignEngine_SetInstanceMotionFrameRange),
|
||||
HLL_EXPORT(SetInstanceMotionLoopFrameRange, ReignEngine_SetInstanceMotionLoopFrameRange),
|
||||
HLL_EXPORT(LoadInstanceNextMotion, ReignEngine_LoadInstanceNextMotion),
|
||||
HLL_TODO_EXPORT(SetInstanceNextMotionState, ReignEngine_SetInstanceNextMotionState),
|
||||
HLL_TODO_EXPORT(SetInstanceNextMotionFrame, ReignEngine_SetInstanceNextMotionFrame),
|
||||
HLL_EXPORT(SetInstanceNextMotionState, ReignEngine_SetInstanceNextMotionState),
|
||||
HLL_EXPORT(SetInstanceNextMotionFrame, ReignEngine_SetInstanceNextMotionFrame),
|
||||
HLL_EXPORT(SetInstanceNextMotionFrameRange, ReignEngine_SetInstanceNextMotionFrameRange),
|
||||
HLL_EXPORT(SetInstanceNextMotionLoopFrameRange, ReignEngine_SetInstanceNextMotionLoopFrameRange),
|
||||
HLL_TODO_EXPORT(SetInstanceMotionBlendRate, ReignEngine_SetInstanceMotionBlendRate),
|
||||
HLL_TODO_EXPORT(SetInstanceMotionBlend, ReignEngine_SetInstanceMotionBlend),
|
||||
HLL_EXPORT(SetInstanceMotionBlendRate, ReignEngine_SetInstanceMotionBlendRate),
|
||||
HLL_EXPORT(SetInstanceMotionBlend, ReignEngine_SetInstanceMotionBlend),
|
||||
HLL_EXPORT(IsInstanceMotionBlend, ReignEngine_IsInstanceMotionBlend),
|
||||
HLL_TODO_EXPORT(GetInstanceMotionBlendPutTime, ReignEngine_GetInstanceMotionBlendPutTime),
|
||||
HLL_EXPORT(SetInstanceMotionBlendPutTime, ReignEngine_SetInstanceMotionBlendPutTime),
|
||||
HLL_TODO_EXPORT(SwapInstanceMotion, ReignEngine_SwapInstanceMotion),
|
||||
HLL_TODO_EXPORT(FreeInstanceNextMotion, ReignEngine_FreeInstanceNextMotion),
|
||||
HLL_EXPORT(SwapInstanceMotion, ReignEngine_SwapInstanceMotion),
|
||||
HLL_EXPORT(FreeInstanceNextMotion, ReignEngine_FreeInstanceNextMotion),
|
||||
HLL_TODO_EXPORT(GetInstanceNumofMaterial, ReignEngine_GetInstanceNumofMaterial),
|
||||
HLL_TODO_EXPORT(GetInstanceMaterialName, ReignEngine_GetInstanceMaterialName),
|
||||
HLL_TODO_EXPORT(GetInstanceMaterialParam, ReignEngine_GetInstanceMaterialParam),
|
||||
@@ -962,7 +1073,7 @@ HLL_LIBRARY(ReignEngine,
|
||||
HLL_TODO_EXPORT(SetInstanceDrawColumn, ReignEngine_SetInstanceDrawColumn),
|
||||
HLL_EXPORT(SetInstanceTarget, ReignEngine_SetInstanceTarget),
|
||||
HLL_TODO_EXPORT(GetInstanceTarget, ReignEngine_GetInstanceTarget),
|
||||
HLL_TODO_EXPORT(GetInstanceFPS, ReignEngine_GetInstanceFPS),
|
||||
HLL_EXPORT(GetInstanceFPS, ReignEngine_GetInstanceFPS),
|
||||
HLL_EXPORT(SetInstanceFPS, ReignEngine_SetInstanceFPS),
|
||||
HLL_EXPORT(GetInstanceBoneIndex, ReignEngine_GetInstanceBoneIndex),
|
||||
HLL_EXPORT(TransInstanceLocalPosToWorldPosByBone, ReignEngine_TransInstanceLocalPosToWorldPosByBone),
|
||||
@@ -985,7 +1096,7 @@ HLL_LIBRARY(ReignEngine,
|
||||
HLL_TODO_EXPORT(GetEffectObjectMoveCurve, ReignEngine_GetEffectObjectMoveCurve),
|
||||
HLL_TODO_EXPORT(GetEffectObjectFrame, ReignEngine_GetEffectObjectFrame),
|
||||
HLL_TODO_EXPORT(GetEffectObjectStopFrame, ReignEngine_GetEffectObjectStopFrame),
|
||||
HLL_TODO_EXPORT(GetEffectNumofObject, ReignEngine_GetEffectNumofObject),
|
||||
HLL_EXPORT(GetEffectNumofObject, ReignEngine_GetEffectNumofObject),
|
||||
HLL_TODO_EXPORT(GetEffectObjectName, ReignEngine_GetEffectObjectName),
|
||||
HLL_TODO_EXPORT(GetEffectNumofObjectPos, ReignEngine_GetEffectNumofObjectPos),
|
||||
HLL_TODO_EXPORT(GetEffectNumofObjectPosUnit, ReignEngine_GetEffectNumofObjectPosUnit),
|
||||
@@ -1098,8 +1209,8 @@ HLL_LIBRARY(ReignEngine,
|
||||
HLL_TODO_EXPORT(GetEffectObjectOffsetY, ReignEngine_GetEffectObjectOffsetY),
|
||||
HLL_TODO_EXPORT(SetEffectObjectOffsetX, ReignEngine_SetEffectObjectOffsetX),
|
||||
HLL_TODO_EXPORT(SetEffectObjectOffsetY, ReignEngine_SetEffectObjectOffsetY),
|
||||
HLL_TODO_EXPORT(GetCameraQuakeEffectFlag, ReignEngine_GetCameraQuakeEffectFlag),
|
||||
HLL_TODO_EXPORT(SetCameraQuakeEffectFlag, ReignEngine_SetCameraQuakeEffectFlag),
|
||||
HLL_EXPORT(GetCameraQuakeEffectFlag, ReignEngine_GetCameraQuakeEffectFlag),
|
||||
HLL_EXPORT(SetCameraQuakeEffectFlag, ReignEngine_SetCameraQuakeEffectFlag),
|
||||
HLL_EXPORT(SetCameraPos, ReignEngine_SetCameraPos),
|
||||
HLL_EXPORT(SetCameraAngle, ReignEngine_SetCameraAngle),
|
||||
HLL_EXPORT(SetCameraAngleP, ReignEngine_SetCameraAngleP),
|
||||
|
||||
Reference in New Issue
Block a user