mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-22 23:18:01 +03:00
Merge pull request #92 from kichikuou/reign
Improve ReignEngine, update game compatibility table
This commit is contained in:
@@ -57,7 +57,7 @@ issues, please let me know or open a pull request to update this table.
|
||||
| Sengoku Rance -Three for the Slash! Thrust! Burn!- (EN) | Unknown | |
|
||||
| AliveZ | Unknown | |
|
||||
| エドランゼ ~Come on!水戸姫様~ | Unknown | |
|
||||
| 闘神都市III | Unsupported | |
|
||||
| 闘神都市III | Supported | |
|
||||
| ばにしゅ!~おっぱいの消えた王国~ | Unknown | |
|
||||
| 僕だけの保健室 | Unknown | |
|
||||
| ももいろガーディアン | Unknown | |
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "gfx/gfx.h"
|
||||
#include "plugin.h"
|
||||
|
||||
struct hash_table;
|
||||
|
||||
enum RE_instance_type {
|
||||
RE_ITYPE_UNINITIALIZED = 0,
|
||||
RE_ITYPE_STATIC = 1,
|
||||
@@ -82,6 +84,8 @@ struct RE_plugin {
|
||||
int nr_instances;
|
||||
struct RE_instance **instances;
|
||||
struct archive *aar;
|
||||
struct hash_table *model_cache;
|
||||
struct hash_table *pae_cache;
|
||||
struct RE_renderer *renderer;
|
||||
struct RE_camera camera;
|
||||
mat4 proj_transform;
|
||||
|
||||
+28
-16
@@ -43,6 +43,7 @@ struct model {
|
||||
struct bone *bones;
|
||||
struct hash_table *bone_map; // bone id in POL/MOT -> struct bone *
|
||||
struct hash_table *bone_name_map; // bone name -> (struct bone * | NULL)
|
||||
struct hash_table *mot_cache; // name -> struct mot *
|
||||
vec3 aabb[2]; // axis-aligned bounding box
|
||||
bool has_transparent_material;
|
||||
};
|
||||
@@ -82,7 +83,6 @@ struct bone {
|
||||
struct motion {
|
||||
struct RE_instance *instance;
|
||||
struct mot *mot;
|
||||
char *name;
|
||||
int state;
|
||||
float current_frame;
|
||||
float frame_begin, frame_end;
|
||||
@@ -193,7 +193,7 @@ 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);
|
||||
bool RE_renderer_detect_height(struct height_detector *hd, float x, float z, float *y_out);
|
||||
void RE_calc_view_matrix(struct RE_camera *camera, vec3 up, mat4 out);
|
||||
|
||||
// particle.c
|
||||
@@ -272,7 +272,14 @@ struct particle_position {
|
||||
struct particle_position_unit units[NR_PARTICLE_POSITION_UNITS];
|
||||
};
|
||||
|
||||
struct particle_object {
|
||||
struct pae {
|
||||
char *path;
|
||||
struct hash_table *textures; // name -> struct billboard_texture*
|
||||
int nr_objects;
|
||||
struct pae_object *objects;
|
||||
};
|
||||
|
||||
struct pae_object {
|
||||
char *name;
|
||||
enum particle_type type;
|
||||
enum particle_move_type move_type;
|
||||
@@ -325,9 +332,18 @@ struct particle_object {
|
||||
float offset_x;
|
||||
float offset_y;
|
||||
|
||||
// Runtime data
|
||||
struct model *model;
|
||||
struct particle_instance *instances;
|
||||
};
|
||||
|
||||
struct particle_effect {
|
||||
struct pae *pae;
|
||||
struct particle_object *objects; // pae->nr_objects elements
|
||||
bool camera_quake_enabled;
|
||||
};
|
||||
|
||||
struct particle_object {
|
||||
struct pae_object *pae_obj;
|
||||
struct particle_instance *instances; // pae_obj->nr_particles elements
|
||||
vec3_range pos;
|
||||
vec3 move_vec, move_ortho;
|
||||
};
|
||||
@@ -340,20 +356,15 @@ struct particle_instance {
|
||||
float pitch_angle;
|
||||
};
|
||||
|
||||
struct particle_effect {
|
||||
char *path;
|
||||
struct hash_table *textures; // name -> struct billboard_texture*
|
||||
int nr_objects;
|
||||
struct particle_object *objects;
|
||||
bool camera_quake_enabled;
|
||||
};
|
||||
struct pae *pae_load(struct archive *aar, const char *path);
|
||||
void pae_free(struct pae *pae);
|
||||
void pae_calc_frame_range(struct pae *pae, struct motion *motion);
|
||||
float pae_object_calc_alpha(struct pae_object *po, struct particle_instance *pi, float frame);
|
||||
|
||||
struct particle_effect *particle_effect_load(struct archive *aar, const char *path);
|
||||
struct particle_effect *particle_effect_create(struct pae *pae);
|
||||
void particle_effect_free(struct particle_effect *effect);
|
||||
void particle_effect_calc_frame_range(struct particle_effect *effect, struct motion *motion);
|
||||
void particle_effect_update(struct RE_instance *inst);
|
||||
void particle_object_calc_local_transform(struct RE_instance *inst, struct particle_object *po, struct particle_instance *pi, float frame, mat4 dest);
|
||||
float particle_object_calc_alpha(struct particle_object *po, struct particle_instance *pi, float frame);
|
||||
|
||||
// parser.c
|
||||
|
||||
@@ -442,6 +453,7 @@ struct pol_bone {
|
||||
};
|
||||
|
||||
struct mot {
|
||||
char *name;
|
||||
uint32_t nr_frames;
|
||||
uint32_t nr_bones;
|
||||
struct mot_bone *motions[];
|
||||
@@ -487,7 +499,7 @@ void pol_free(struct pol *pol);
|
||||
void pol_compute_aabb(struct pol *model, vec3 dest[2]);
|
||||
struct pol_bone *pol_find_bone(struct pol *pol, uint32_t id);
|
||||
|
||||
struct mot *mot_parse(uint8_t *data, size_t size);
|
||||
struct mot *mot_parse(uint8_t *data, size_t size, const char *name);
|
||||
void mot_free(struct mot *mot);
|
||||
|
||||
struct amt *amt_parse(uint8_t *data, size_t size);
|
||||
|
||||
+3
-3
@@ -63,9 +63,9 @@ static void print_motion(const char *name, struct motion *m, int indent)
|
||||
indent_printf(indent, "%s = {state=%s, frame=%f, range=(%d,%d), loop_range=(%d,%d)},\n",
|
||||
name, motion_state_name(m->state), m->current_frame,
|
||||
(int)m->frame_begin, (int)m->frame_end, (int)m->loop_frame_begin, (int)m->loop_frame_end);
|
||||
} else {
|
||||
} else if (m->mot) {
|
||||
indent_printf(indent, "%s = {name=\"%s\", state=%s, frame=%f},\n",
|
||||
name, m->name, motion_state_name(m->state), m->current_frame);
|
||||
name, m->mot->name, motion_state_name(m->state), m->current_frame);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ static void print_instance(struct RE_instance *inst, int index, int indent)
|
||||
if (inst->motion_blend)
|
||||
indent_printf(indent, "motion_blend_rate = %f,\n", inst->motion_blend_rate);
|
||||
if (inst->effect)
|
||||
indent_printf(indent, "path = \"%s\",\n", inst->effect->path);
|
||||
indent_printf(indent, "path = \"%s\",\n", inst->effect->pae->path);
|
||||
|
||||
indent--;
|
||||
indent_printf(indent, "},\n");
|
||||
|
||||
+22
-11
@@ -422,6 +422,7 @@ struct model *model_load(struct archive *aar, const char *path)
|
||||
ERROR("%s: Too many bones (%u)", model->path, pol->nr_bones);
|
||||
model->bone_map = ht_create(pol->nr_bones * 3 / 2);
|
||||
model->bone_name_map = ht_create(pol->nr_bones * 3 / 2);
|
||||
model->mot_cache = ht_create(16);
|
||||
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]);
|
||||
@@ -499,6 +500,10 @@ void model_free(struct model *model)
|
||||
ht_free_int(model->bone_map);
|
||||
if (model->bone_name_map)
|
||||
ht_free(model->bone_name_map);
|
||||
if (model->mot_cache) {
|
||||
ht_foreach_value(model->mot_cache, (void(*)(void*))mot_free);
|
||||
ht_free(model->mot_cache);
|
||||
}
|
||||
|
||||
free(model->path);
|
||||
free(model);
|
||||
@@ -604,18 +609,14 @@ 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 RE_instance *instance, struct archive *aar)
|
||||
static struct mot *mot_load(const char *name, struct model *model, struct archive *aar)
|
||||
{
|
||||
struct model *model = instance->model;
|
||||
if (!model)
|
||||
return NULL;
|
||||
|
||||
struct archive_data *dfile = RE_get_aar_entry(aar, model->path, name, ".MOT");
|
||||
if (!dfile) {
|
||||
WARNING("%s\\%s.MOT: not found", model->path, name);
|
||||
return NULL;
|
||||
}
|
||||
struct mot *mot = mot_parse(dfile->data, dfile->size);
|
||||
struct mot *mot = mot_parse(dfile->data, dfile->size, name);
|
||||
if (!mot) {
|
||||
WARNING("%s: parse error", dfile->name);
|
||||
archive_free_data(dfile);
|
||||
@@ -640,18 +641,28 @@ struct motion *motion_load(const char *name, struct RE_instance *instance, struc
|
||||
}
|
||||
qsort(mot->motions, mot->nr_bones, sizeof(struct mot_bone *), cmp_motions_by_bone_id);
|
||||
|
||||
return mot;
|
||||
}
|
||||
|
||||
struct motion *motion_load(const char *name, struct RE_instance *instance, struct archive *aar)
|
||||
{
|
||||
struct model *model = instance->model;
|
||||
if (!model || !model->mot_cache)
|
||||
return NULL;
|
||||
struct mot *mot = ht_get(model->mot_cache, name, NULL);
|
||||
if (!mot) {
|
||||
mot = mot_load(name, model, aar);
|
||||
if (!mot)
|
||||
return NULL;
|
||||
ht_put(model->mot_cache, name, mot);
|
||||
}
|
||||
struct motion *motion = xcalloc(1, sizeof(struct motion));
|
||||
motion->instance = instance;
|
||||
motion->mot = mot;
|
||||
motion->name = strdup(name);
|
||||
return motion;
|
||||
}
|
||||
|
||||
void motion_free(struct motion *motion)
|
||||
{
|
||||
if (motion->mot)
|
||||
mot_free(motion->mot);
|
||||
if (motion->name)
|
||||
free(motion->name);
|
||||
free(motion);
|
||||
}
|
||||
|
||||
+3
-1
@@ -353,7 +353,7 @@ struct pol_bone *pol_find_bone(struct pol *pol, uint32_t id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mot *mot_parse(uint8_t *data, size_t size)
|
||||
struct mot *mot_parse(uint8_t *data, size_t size, const char *name)
|
||||
{
|
||||
struct buffer r;
|
||||
buffer_init(&r, data, size);
|
||||
@@ -369,6 +369,7 @@ struct mot *mot_parse(uint8_t *data, size_t size)
|
||||
uint32_t nr_bones = buffer_read_int32(&r);
|
||||
|
||||
struct mot *mot = xcalloc(1, sizeof(struct mot) + nr_bones * sizeof(struct mot_bone *));
|
||||
mot->name = strdup(name);
|
||||
mot->nr_frames = nr_frames;
|
||||
mot->nr_bones = nr_bones;
|
||||
for (uint32_t i = 0; i < nr_bones; i++) {
|
||||
@@ -391,6 +392,7 @@ struct mot *mot_parse(uint8_t *data, size_t size)
|
||||
|
||||
void mot_free(struct mot *mot)
|
||||
{
|
||||
free(mot->name);
|
||||
for (uint32_t i = 0; i < mot->nr_bones; i++) {
|
||||
free(mot->motions[i]->name);
|
||||
free(mot->motions[i]);
|
||||
|
||||
+97
-72
@@ -239,10 +239,10 @@ static struct particle_position *parse_position(char **ptext)
|
||||
return epos;
|
||||
}
|
||||
|
||||
static struct particle_effect *parse_pae(char *text)
|
||||
static struct pae *parse_pae(char *text)
|
||||
{
|
||||
struct particle_effect *pae = xcalloc(1, sizeof(struct particle_effect));
|
||||
struct particle_object *current_object = NULL;
|
||||
struct pae *pae = xcalloc(1, sizeof(struct pae));
|
||||
struct pae_object *current_object = NULL;
|
||||
|
||||
for (;;) {
|
||||
// Skip whitespaces and comments
|
||||
@@ -269,7 +269,7 @@ static struct particle_effect *parse_pae(char *text)
|
||||
if (!*text) { // EOF
|
||||
return pae;
|
||||
} else if (MATCH("オブジェクト " QUOTED_STRING " = {", string_buf)) {
|
||||
pae->objects = xrealloc_array(pae->objects, pae->nr_objects, pae->nr_objects + 1, sizeof(struct particle_object));
|
||||
pae->objects = xrealloc_array(pae->objects, pae->nr_objects, pae->nr_objects + 1, sizeof(struct pae_object));
|
||||
current_object = &pae->objects[pae->nr_objects++];
|
||||
current_object->name = utf2sjis(string_buf, 0);
|
||||
// Default values.
|
||||
@@ -449,15 +449,15 @@ static struct particle_effect *parse_pae(char *text)
|
||||
}
|
||||
}
|
||||
err:
|
||||
particle_effect_free(pae);
|
||||
pae_free(pae);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void load_textures(struct particle_effect *effect, struct archive *aar)
|
||||
static void load_textures(struct pae *effect, struct archive *aar)
|
||||
{
|
||||
effect->textures = ht_create(16);
|
||||
for (int i = 0; i < effect->nr_objects; i++) {
|
||||
struct particle_object *po = &effect->objects[i];
|
||||
struct pae_object *po = &effect->objects[i];
|
||||
for (int j = 0; j < po->nr_textures; j++) {
|
||||
const char *name = po->textures[j];
|
||||
if (ht_get(effect->textures, name, NULL))
|
||||
@@ -587,7 +587,7 @@ static void eval_pos_for_instance(struct particle_position *pp, vec3 dest)
|
||||
}
|
||||
}
|
||||
|
||||
static float eval_child_slope(struct particle_object *po)
|
||||
static float eval_child_slope(struct pae_object *po)
|
||||
{
|
||||
float slope = glm_lerp(po->child_begin_slope, po->child_end_slope, randf());
|
||||
if (slope > 1.0)
|
||||
@@ -607,29 +607,30 @@ static void interpolate_pos(vec3 begin, vec3 end, float move_curve, float t, vec
|
||||
|
||||
static void init_particle_instances(struct particle_object *po)
|
||||
{
|
||||
po->instances = xcalloc(po->nr_particles, sizeof(struct particle_instance));
|
||||
struct pae_object *pae_obj = po->pae_obj;
|
||||
po->instances = xcalloc(pae_obj->nr_particles, sizeof(struct particle_instance));
|
||||
|
||||
for (int i = 0; i < po->nr_particles; i++) {
|
||||
for (int i = 0; i < pae_obj->nr_particles; i++) {
|
||||
struct particle_instance *pi = &po->instances[i];
|
||||
switch (po->move_type) {
|
||||
switch (pae_obj->move_type) {
|
||||
case PARTICLE_MOVE_FIXED:
|
||||
case PARTICLE_MOVE_LINEAR:
|
||||
pi->begin_frame = po->begin_frame;
|
||||
pi->end_frame = po->end_frame;
|
||||
pi->begin_frame = pae_obj->begin_frame;
|
||||
pi->end_frame = pae_obj->end_frame;
|
||||
break;
|
||||
case PARTICLE_MOVE_EMITTER:
|
||||
pi->begin_frame = glm_lerp(po->child_create_begin_frame, po->child_create_end_frame, (float)i / po->nr_particles);
|
||||
pi->end_frame = pi->begin_frame + po->child_frame;
|
||||
pi->roll_angle = eval_child_slope(po);
|
||||
pi->begin_frame = glm_lerp(pae_obj->child_create_begin_frame, pae_obj->child_create_end_frame, (float)i / pae_obj->nr_particles);
|
||||
pi->end_frame = pi->begin_frame + pae_obj->child_frame;
|
||||
pi->roll_angle = eval_child_slope(pae_obj);
|
||||
pi->pitch_angle = randf() * (2.0f * GLM_PIf);
|
||||
break;
|
||||
}
|
||||
eval_pos_for_instance(po->position[0], pi->random_offset.begin);
|
||||
eval_pos_for_instance(po->position[1], pi->random_offset.end);
|
||||
eval_pos_for_instance(pae_obj->position[0], pi->random_offset.begin);
|
||||
eval_pos_for_instance(pae_obj->position[1], pi->random_offset.end);
|
||||
}
|
||||
}
|
||||
|
||||
struct particle_effect *particle_effect_load(struct archive *aar, const char *path)
|
||||
struct pae *pae_load(struct archive *aar, const char *path)
|
||||
{
|
||||
const char *basename = strrchr(path, '\\');
|
||||
basename = basename ? basename + 1 : path;
|
||||
@@ -653,20 +654,19 @@ struct particle_effect *particle_effect_load(struct archive *aar, const char *pa
|
||||
// clarity.
|
||||
char *text = sjis2utf(sjis_text, dfile->size);
|
||||
free(sjis_text);
|
||||
struct particle_effect *effect = parse_pae(text);
|
||||
struct pae *pae = parse_pae(text);
|
||||
free(text);
|
||||
if (!effect) {
|
||||
if (!pae) {
|
||||
WARNING("could not parse %s", dfile->name);
|
||||
archive_free_data(dfile);
|
||||
return NULL;
|
||||
}
|
||||
archive_free_data(dfile);
|
||||
|
||||
effect->path = strdup(path);
|
||||
effect->camera_quake_enabled = true;
|
||||
load_textures(effect, aar);
|
||||
for (int i = 0; i < effect->nr_objects; i++) {
|
||||
struct particle_object *po = &effect->objects[i];
|
||||
pae->path = strdup(path);
|
||||
load_textures(pae, aar);
|
||||
for (int i = 0; i < pae->nr_objects; i++) {
|
||||
struct pae_object *po = &pae->objects[i];
|
||||
|
||||
if (po->polygon_name && *po->polygon_name) {
|
||||
char *pol_path = xmalloc(strlen(path) + strlen(po->polygon_name) + 2);
|
||||
@@ -674,10 +674,22 @@ struct particle_effect *particle_effect_load(struct archive *aar, const char *pa
|
||||
po->model = model_load(aar, pol_path);
|
||||
free(pol_path);
|
||||
}
|
||||
|
||||
init_particle_instances(po);
|
||||
}
|
||||
|
||||
return pae;
|
||||
}
|
||||
|
||||
struct particle_effect *particle_effect_create(struct pae *pae)
|
||||
{
|
||||
struct particle_effect *effect = xcalloc(1, sizeof(struct particle_effect));
|
||||
effect->pae = pae;
|
||||
effect->objects = xcalloc(pae->nr_objects, sizeof(struct particle_object));
|
||||
effect->camera_quake_enabled = true;
|
||||
for (int i = 0; i < pae->nr_objects; i++) {
|
||||
struct particle_object *po = &effect->objects[i];
|
||||
po->pae_obj = &pae->objects[i];
|
||||
init_particle_instances(po);
|
||||
}
|
||||
return effect;
|
||||
}
|
||||
|
||||
@@ -699,10 +711,10 @@ static void particle_position_free(struct particle_position *pos)
|
||||
free(pos);
|
||||
}
|
||||
|
||||
void particle_effect_free(struct particle_effect *effect)
|
||||
void pae_free(struct pae *pae)
|
||||
{
|
||||
for (int i = 0; i < effect->nr_objects; i++) {
|
||||
struct particle_object *po = &effect->objects[i];
|
||||
for (int i = 0; i < pae->nr_objects; i++) {
|
||||
struct pae_object *po = &pae->objects[i];
|
||||
free(po->name);
|
||||
for (int j = 0; j < NR_PARTICLE_POSITIONS; j++)
|
||||
particle_position_free(po->position[j]);
|
||||
@@ -719,21 +731,30 @@ void particle_effect_free(struct particle_effect *effect)
|
||||
free(po->damages);
|
||||
if (po->model)
|
||||
model_free(po->model);
|
||||
free(po->instances);
|
||||
}
|
||||
ht_foreach_value(effect->textures, free_billboard_texture);
|
||||
ht_free(effect->textures);
|
||||
ht_foreach_value(pae->textures, free_billboard_texture);
|
||||
ht_free(pae->textures);
|
||||
free(pae->objects);
|
||||
free(pae->path);
|
||||
free(pae);
|
||||
}
|
||||
|
||||
void particle_effect_free(struct particle_effect *effect)
|
||||
{
|
||||
for (int i = 0; i < effect->pae->nr_objects; i++) {
|
||||
struct particle_object *obj = &effect->objects[i];
|
||||
free(obj->instances);
|
||||
}
|
||||
free(effect->objects);
|
||||
free(effect->path);
|
||||
free(effect);
|
||||
}
|
||||
|
||||
void particle_effect_calc_frame_range(struct particle_effect *effect, struct motion *motion)
|
||||
void pae_calc_frame_range(struct pae *pae, struct motion *motion)
|
||||
{
|
||||
int begin_frame = INT_MAX;
|
||||
int end_frame = INT_MIN;
|
||||
for (int i = 0; i < effect->nr_objects; i++) {
|
||||
struct particle_object *po = &effect->objects[i];
|
||||
for (int i = 0; i < pae->nr_objects; i++) {
|
||||
struct pae_object *po = &pae->objects[i];
|
||||
int obj_begin = po->begin_frame;
|
||||
int obj_end = max(po->end_frame, po->child_create_end_frame + po->child_frame);
|
||||
if (begin_frame > obj_begin)
|
||||
@@ -745,7 +766,7 @@ void particle_effect_calc_frame_range(struct particle_effect *effect, struct mot
|
||||
motion->frame_end = motion->loop_frame_end = end_frame;
|
||||
}
|
||||
|
||||
static void update_camera_quake(struct RE_instance *inst, struct particle_object *po)
|
||||
static void update_camera_quake(struct RE_instance *inst, struct pae_object *po)
|
||||
{
|
||||
float frame = inst->motion->current_frame - po->begin_frame;
|
||||
float total_frames = po->end_frame - po->begin_frame;
|
||||
@@ -769,19 +790,20 @@ void particle_effect_update(struct RE_instance *inst)
|
||||
struct particle_effect *effect = inst->effect;
|
||||
if (!effect)
|
||||
return;
|
||||
for (int i = 0; i < effect->nr_objects; i++) {
|
||||
for (int i = 0; i < effect->pae->nr_objects; i++) {
|
||||
struct particle_object *po = &effect->objects[i];
|
||||
if (po->type == PARTICLE_TYPE_CAMERA_QUAKE) {
|
||||
struct pae_object *pae_obj = po->pae_obj;
|
||||
if (pae_obj->type == PARTICLE_TYPE_CAMERA_QUAKE) {
|
||||
if (effect->camera_quake_enabled)
|
||||
update_camera_quake(inst, po);
|
||||
update_camera_quake(inst, pae_obj);
|
||||
continue;
|
||||
}
|
||||
// These cannot be precomputed, because they may depend on the target's
|
||||
// *current* bone matrix.
|
||||
eval_pos_for_object(inst, po->position[0], po->pos.begin);
|
||||
eval_pos_for_object(inst, po->position[1], po->pos.end);
|
||||
eval_pos_for_object(inst, pae_obj->position[0], po->pos.begin);
|
||||
eval_pos_for_object(inst, pae_obj->position[1], po->pos.end);
|
||||
glm_vec3_sub(po->pos.end, po->pos.begin, po->move_vec);
|
||||
switch (po->dir_type) {
|
||||
switch (pae_obj->dir_type) {
|
||||
case PARTICLE_DIR_TYPE_NORMAL:
|
||||
glm_vec3_normalize(po->move_vec);
|
||||
glm_vec3_ortho(po->move_vec, po->move_ortho);
|
||||
@@ -798,45 +820,47 @@ void particle_effect_update(struct RE_instance *inst)
|
||||
|
||||
static void calc_emitter_pos(struct particle_object *po, struct particle_instance *pi, float t, vec3 dest, vec3 move_vec)
|
||||
{
|
||||
struct pae_object *pae_obj = po->pae_obj;
|
||||
vec3 begin, end;
|
||||
glm_vec3_add(po->pos.begin, pi->random_offset.begin, begin);
|
||||
glm_vec3_add(po->pos.end, pi->random_offset.end, end);
|
||||
interpolate_pos(begin, end, po->move_curve, t, dest);
|
||||
interpolate_pos(begin, end, pae_obj->move_curve, t, dest);
|
||||
if (move_vec)
|
||||
glm_vec3_sub(end, begin, move_vec);
|
||||
|
||||
// Orbital rotation.
|
||||
vec3 angle, dist;
|
||||
glm_vec3_lerp(po->revolution_angle.begin, po->revolution_angle.end, t, angle);
|
||||
glm_vec3_lerp(po->revolution_distance.begin, po->revolution_distance.end, t, dist);
|
||||
glm_vec3_lerp(pae_obj->revolution_angle.begin, pae_obj->revolution_angle.end, t, angle);
|
||||
glm_vec3_lerp(pae_obj->revolution_distance.begin, pae_obj->revolution_distance.end, t, dist);
|
||||
glm_vec3_scale(angle, GLM_PIf / 180.0f, angle); // deg -> rad
|
||||
if (po->revolution_angle.begin[0] != 0.0f || po->revolution_angle.end[0] != 0.0f) {
|
||||
if (pae_obj->revolution_angle.begin[0] != 0.0f || pae_obj->revolution_angle.end[0] != 0.0f) {
|
||||
dest[1] += dist[0] * sinf(angle[0]);
|
||||
dest[2] -= dist[0] * cosf(angle[0]);
|
||||
}
|
||||
if (po->revolution_angle.begin[1] != 0.0f || po->revolution_angle.end[1] != 0.0f) {
|
||||
if (pae_obj->revolution_angle.begin[1] != 0.0f || pae_obj->revolution_angle.end[1] != 0.0f) {
|
||||
dest[0] += dist[1] * sinf(angle[1]);
|
||||
dest[2] -= dist[1] * cosf(angle[1]);
|
||||
}
|
||||
if (po->revolution_angle.begin[2] != 0.0f || po->revolution_angle.end[2] != 0.0f) {
|
||||
if (pae_obj->revolution_angle.begin[2] != 0.0f || pae_obj->revolution_angle.end[2] != 0.0f) {
|
||||
dest[1] += dist[2] * sinf(angle[2]);
|
||||
dest[0] += dist[2] * cosf(angle[2]);
|
||||
}
|
||||
|
||||
// Apply the curve.
|
||||
glm_vec3_muladds(po->curve_length, 4.9f * t * (1.0f - t), dest);
|
||||
glm_vec3_muladds(pae_obj->curve_length, 4.9f * t * (1.0f - t), dest);
|
||||
}
|
||||
|
||||
static void calc_pos_and_up_vector(struct particle_object *po, struct particle_instance *pi, float t, vec3 pos, vec3 up_vector)
|
||||
{
|
||||
switch (po->move_type) {
|
||||
struct pae_object *pae_obj = po->pae_obj;
|
||||
switch (pae_obj->move_type) {
|
||||
case PARTICLE_MOVE_FIXED:
|
||||
glm_vec3_add(po->pos.begin, pi->random_offset.begin, pos);
|
||||
glm_vec3_copy(GLM_YUP, up_vector);
|
||||
break;
|
||||
case PARTICLE_MOVE_LINEAR:
|
||||
calc_emitter_pos(po, pi, t, pos, up_vector);
|
||||
switch (po->up_vector_type) {
|
||||
switch (pae_obj->up_vector_type) {
|
||||
case PARTICLE_UP_VECTOR_Y_AXIS:
|
||||
case PARTICLE_UP_VECTOR_INSTANCE_MOVE:
|
||||
glm_vec3_copy(GLM_YUP, up_vector);
|
||||
@@ -852,12 +876,12 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i
|
||||
case PARTICLE_MOVE_EMITTER:
|
||||
{
|
||||
// Calculate the instance's initial and final position.
|
||||
float t0 = glm_clamp_zo(glm_percent(po->begin_frame, po->end_frame, pi->begin_frame));
|
||||
float t0 = glm_clamp_zo(glm_percent(pae_obj->begin_frame, pae_obj->end_frame, pi->begin_frame));
|
||||
vec3_range inst_pos;
|
||||
calc_emitter_pos(po, pi, t0, inst_pos.begin, NULL);
|
||||
vec3 inst_move;
|
||||
glm_vec3_copy(po->move_vec, inst_move);
|
||||
switch (po->dir_type) {
|
||||
switch (pae_obj->dir_type) {
|
||||
case PARTICLE_DIR_TYPE_NORMAL:
|
||||
glm_vec3_rotate(inst_move, pi->roll_angle, po->move_ortho);
|
||||
glm_vec3_rotate(inst_move, pi->pitch_angle, po->move_vec);
|
||||
@@ -867,12 +891,12 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i
|
||||
break;
|
||||
}
|
||||
glm_vec3_copy(inst_pos.begin, inst_pos.end);
|
||||
switch (po->child_move_dir_type) {
|
||||
switch (pae_obj->child_move_dir_type) {
|
||||
case PARTICLE_CHILD_MOVE_DIR_NORMAL:
|
||||
glm_vec3_muladds(inst_move, po->child_length, inst_pos.end);
|
||||
glm_vec3_muladds(inst_move, pae_obj->child_length, inst_pos.end);
|
||||
break;
|
||||
case PARTICLE_CHILD_MOVE_DIR_REVERSE:
|
||||
glm_vec3_muladds(inst_move, po->child_length, inst_pos.begin);
|
||||
glm_vec3_muladds(inst_move, pae_obj->child_length, inst_pos.begin);
|
||||
glm_vec3_negate(inst_move);
|
||||
break;
|
||||
}
|
||||
@@ -880,7 +904,7 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i
|
||||
glm_vec3_lerp(inst_pos.begin, inst_pos.end, t, pos);
|
||||
|
||||
// Calculate the up vector.
|
||||
switch (po->up_vector_type) {
|
||||
switch (pae_obj->up_vector_type) {
|
||||
case PARTICLE_UP_VECTOR_Y_AXIS:
|
||||
glm_vec3_copy(GLM_YUP, up_vector);
|
||||
break;
|
||||
@@ -888,13 +912,13 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i
|
||||
glm_vec3_copy(po->move_vec, up_vector);
|
||||
break;
|
||||
case PARTICLE_UP_VECTOR_INSTANCE_MOVE:
|
||||
if (po->child_length != 0.0f)
|
||||
if (pae_obj->child_length != 0.0f)
|
||||
glm_vec3_copy(inst_move, up_vector);
|
||||
else
|
||||
glm_vec3_copy(GLM_XUP, up_vector);
|
||||
break;
|
||||
}
|
||||
if (po->dir_type == PARTICLE_DIR_TYPE_XY_PLANE) {
|
||||
if (pae_obj->dir_type == PARTICLE_DIR_TYPE_XY_PLANE) {
|
||||
mat3 rot = {{ inst_move[1], -inst_move[0], 0.0f },
|
||||
{ inst_move[0], inst_move[1], 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f }};
|
||||
@@ -905,7 +929,7 @@ static void calc_pos_and_up_vector(struct particle_object *po, struct particle_i
|
||||
}
|
||||
}
|
||||
|
||||
static void calc_scale(struct particle_object *po, int frame, vec3 dest)
|
||||
static void calc_scale(struct pae_object *po, int frame, vec3 dest)
|
||||
{
|
||||
glm_vec3_broadcast(po->sizes2[min(frame, po->nr_sizes2 - 1)], dest);
|
||||
if (po->nr_sizes_x)
|
||||
@@ -916,6 +940,7 @@ static void calc_scale(struct particle_object *po, int frame, vec3 dest)
|
||||
|
||||
void particle_object_calc_local_transform(struct RE_instance *inst, struct particle_object *po, struct particle_instance *pi, float frame, mat4 dest)
|
||||
{
|
||||
struct pae_object *pae_obj = po->pae_obj;
|
||||
float t = glm_percent(pi->begin_frame, pi->end_frame, frame);
|
||||
|
||||
vec3 pos, up_vector;
|
||||
@@ -927,7 +952,7 @@ void particle_object_calc_local_transform(struct RE_instance *inst, struct parti
|
||||
float step_frac = rel_frame - cur_step;
|
||||
|
||||
glm_translate_make(dest, pos);
|
||||
if (po->type == PARTICLE_TYPE_BILLBOARD) {
|
||||
if (pae_obj->type == PARTICLE_TYPE_BILLBOARD) {
|
||||
mat4 view_mat;
|
||||
RE_calc_view_matrix(&inst->plugin->camera, up_vector, view_mat);
|
||||
mat3 rot;
|
||||
@@ -936,7 +961,7 @@ void particle_object_calc_local_transform(struct RE_instance *inst, struct parti
|
||||
}
|
||||
|
||||
vec3 angles;
|
||||
glm_vec3_lerp(po->rotation.begin, po->rotation.end, t, angles);
|
||||
glm_vec3_lerp(pae_obj->rotation.begin, pae_obj->rotation.end, t, angles);
|
||||
angles[0] *= -GLM_PIf / 180.0f;
|
||||
angles[1] *= -GLM_PIf / 180.0f;
|
||||
angles[2] *= GLM_PIf / 180.0f;
|
||||
@@ -944,21 +969,21 @@ void particle_object_calc_local_transform(struct RE_instance *inst, struct parti
|
||||
glm_euler_zxy(angles, rotation_mat);
|
||||
glm_mat4_mul(dest, rotation_mat, dest);
|
||||
|
||||
if (po->nr_sizes2 > 0) {
|
||||
if (pae_obj->nr_sizes2 > 0) {
|
||||
vec3 scale, scale2;
|
||||
calc_scale(po, cur_step, scale);
|
||||
calc_scale(po, next_step, scale2);
|
||||
calc_scale(pae_obj, cur_step, scale);
|
||||
calc_scale(pae_obj, next_step, scale2);
|
||||
glm_vec3_lerp(scale, scale2, step_frac, scale);
|
||||
glm_scale(dest, scale);
|
||||
} else {
|
||||
glm_scale_uni(dest, glm_lerp(po->size[0], po->size[1], t));
|
||||
glm_scale_uni(dest, glm_lerp(pae_obj->size[0], pae_obj->size[1], t));
|
||||
}
|
||||
|
||||
glm_translate_x(dest, -po->offset_x);
|
||||
glm_translate_y(dest, -po->offset_y);
|
||||
glm_translate_x(dest, -pae_obj->offset_x);
|
||||
glm_translate_y(dest, -pae_obj->offset_y);
|
||||
}
|
||||
|
||||
float particle_object_calc_alpha(struct particle_object *po, struct particle_instance *pi, float frame)
|
||||
float pae_object_calc_alpha(struct pae_object *po, struct particle_instance *pi, float frame)
|
||||
{
|
||||
frame -= pi->begin_frame;
|
||||
if (frame < po->alpha_fadein_frame)
|
||||
|
||||
+122
-87
@@ -24,6 +24,7 @@
|
||||
#include "system4.h"
|
||||
#include "system4/aar.h"
|
||||
#include "system4/cg.h"
|
||||
#include "system4/hashtable.h"
|
||||
#include "system4/string.h"
|
||||
|
||||
#include "3d_internal.h"
|
||||
@@ -66,7 +67,7 @@ static void unload_instance(struct RE_instance *instance)
|
||||
instance->next_motion = NULL;
|
||||
}
|
||||
if (instance->model) {
|
||||
model_free(instance->model);
|
||||
// No need to free, model is owned by plugin->model_cache.
|
||||
instance->model = NULL;
|
||||
}
|
||||
if (instance->effect) {
|
||||
@@ -137,8 +138,12 @@ static void update_motion(struct motion *m, float delta_frame)
|
||||
|
||||
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);
|
||||
uint32_t cur_frame = m->current_frame;
|
||||
uint32_t next_frame = ceilf(m->current_frame);
|
||||
if (next_frame >= m->mot->nr_frames) {
|
||||
*out = m->mot->motions[bone]->frames[m->mot->nr_frames - 1];
|
||||
return;
|
||||
}
|
||||
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);
|
||||
@@ -215,6 +220,8 @@ struct RE_plugin *RE_plugin_new(void)
|
||||
plugin->nr_instances = 16;
|
||||
plugin->instances = xcalloc(plugin->nr_instances, sizeof(struct RE_instance *));
|
||||
plugin->aar = aar;
|
||||
plugin->model_cache = ht_create(32);
|
||||
plugin->pae_cache = ht_create(32);
|
||||
for (int i = 0; i < RE_NR_BACK_CGS; i++)
|
||||
RE_back_cg_init(&plugin->back_cg[i]);
|
||||
plugin->fog_type = RE_FOG_NONE;
|
||||
@@ -232,6 +239,10 @@ void RE_plugin_free(struct RE_plugin *plugin)
|
||||
}
|
||||
free(plugin->instances);
|
||||
archive_free(plugin->aar);
|
||||
ht_foreach_value(plugin->model_cache, (void(*)(void*))model_free);
|
||||
ht_free(plugin->model_cache);
|
||||
ht_foreach_value(plugin->pae_cache, (void(*)(void*))pae_free);
|
||||
ht_free(plugin->pae_cache);
|
||||
if (plugin->renderer)
|
||||
RE_renderer_free(plugin->renderer);
|
||||
for (int i = 0; i < RE_NR_BACK_CGS; i++)
|
||||
@@ -372,21 +383,34 @@ bool RE_instance_load(struct RE_instance *instance, const char *name)
|
||||
if (name[0] == '\0')
|
||||
return false;
|
||||
|
||||
struct pae *pae;
|
||||
switch (instance->type) {
|
||||
case RE_ITYPE_STATIC:
|
||||
case RE_ITYPE_SKINNED:
|
||||
instance->model = model_load(instance->plugin->aar, name);
|
||||
instance->model = ht_get(instance->plugin->model_cache, name, NULL);
|
||||
if (!instance->model) {
|
||||
instance->model = model_load(instance->plugin->aar, name);
|
||||
if (instance->model)
|
||||
ht_put(instance->plugin->model_cache, name, instance->model);
|
||||
}
|
||||
if (instance->model && instance->model->nr_bones > 0)
|
||||
instance->bone_transforms = xcalloc(instance->model->nr_bones, sizeof(mat4));
|
||||
return !!instance->model;
|
||||
case RE_ITYPE_PARTICLE_EFFECT:
|
||||
instance->effect = particle_effect_load(instance->plugin->aar, name);
|
||||
pae = ht_get(instance->plugin->pae_cache, name, NULL);
|
||||
if (!pae) {
|
||||
pae = pae_load(instance->plugin->aar, name);
|
||||
if (!pae)
|
||||
return false;
|
||||
ht_put(instance->plugin->pae_cache, name, pae);
|
||||
}
|
||||
instance->effect = particle_effect_create(pae);
|
||||
if (!instance->motion) {
|
||||
instance->motion = xcalloc(1, sizeof(struct motion));
|
||||
instance->motion->instance = instance;
|
||||
particle_effect_calc_frame_range(instance->effect, instance->motion);
|
||||
pae_calc_frame_range(instance->effect->pae, instance->motion);
|
||||
}
|
||||
return !!instance->effect;
|
||||
return true;
|
||||
default:
|
||||
WARNING("Invalid instance type %d", instance->type);
|
||||
return false;
|
||||
@@ -468,8 +492,19 @@ float RE_instance_calc_height(struct RE_instance *instance, float x, float z)
|
||||
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;
|
||||
|
||||
float y;
|
||||
if (RE_renderer_detect_height(instance->height_detector, x, z, &y))
|
||||
return y;
|
||||
|
||||
// Return the average of 4 neighbors.
|
||||
int cnt = 0;
|
||||
float total = 0.0f;
|
||||
if (RE_renderer_detect_height(instance->height_detector, x - 0.5f, z, &y)) { cnt++; total += y; }
|
||||
if (RE_renderer_detect_height(instance->height_detector, x + 0.5f, z, &y)) { cnt++; total += y; }
|
||||
if (RE_renderer_detect_height(instance->height_detector, x, z - 0.5f, &y)) { cnt++; total += y; }
|
||||
if (RE_renderer_detect_height(instance->height_detector, x, z + 0.5f, &y)) { cnt++; total += y; }
|
||||
return cnt ? total / cnt : 0.0f;
|
||||
}
|
||||
|
||||
bool RE_instance_set_debug_draw_shadow_volume(struct RE_instance *inst, bool draw)
|
||||
@@ -565,7 +600,7 @@ bool RE_motion_set_loop_frame_range(struct motion *motion, float begin, float en
|
||||
|
||||
int RE_effect_get_num_object(struct particle_effect *effect)
|
||||
{
|
||||
return effect ? effect->nr_objects : 0;
|
||||
return effect ? effect->pae->nr_objects : 0;
|
||||
}
|
||||
|
||||
bool RE_effect_get_camera_quake_flag(struct particle_effect *effect)
|
||||
@@ -583,47 +618,47 @@ bool RE_effect_set_camera_quake_flag(struct particle_effect *effect, bool enable
|
||||
|
||||
struct particle_object *RE_get_effect_object(struct particle_effect *effect, unsigned object)
|
||||
{
|
||||
if (!effect || object >= (unsigned)effect->nr_objects)
|
||||
if (!effect || object >= (unsigned)effect->pae->nr_objects)
|
||||
return NULL;
|
||||
return &effect->objects[object];
|
||||
}
|
||||
|
||||
int RE_particle_get_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->type : 0;
|
||||
return po ? po->pae_obj->type : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_move_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->move_type : 0;
|
||||
return po ? po->pae_obj->move_type : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_up_vec_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->up_vector_type : 0;
|
||||
return po ? po->pae_obj->up_vector_type : 0;
|
||||
}
|
||||
|
||||
float RE_particle_get_move_curve(struct particle_object *po)
|
||||
{
|
||||
return po ? po->move_curve : 0.0;
|
||||
return po ? po->pae_obj->move_curve : 0.0;
|
||||
}
|
||||
|
||||
void RE_particle_get_frame(struct particle_object *po, int *begin_frame, int *end_frame)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_frame = po->begin_frame;
|
||||
*end_frame = po->end_frame;
|
||||
*begin_frame = po->pae_obj->begin_frame;
|
||||
*end_frame = po->pae_obj->end_frame;
|
||||
}
|
||||
|
||||
int RE_particle_get_stop_frame(struct particle_object *po)
|
||||
{
|
||||
return po ? po->stop_frame : 0;
|
||||
return po ? po->pae_obj->stop_frame : 0;
|
||||
}
|
||||
|
||||
const char *RE_particle_get_name(struct particle_object *po)
|
||||
{
|
||||
return po ? po->name : NULL;
|
||||
return po ? po->pae_obj->name : NULL;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_pos(struct particle_object *po)
|
||||
@@ -638,9 +673,9 @@ int RE_particle_get_num_pos_unit(struct particle_object *po, int pos)
|
||||
|
||||
static struct particle_position_unit *get_position_unit(struct particle_object *po, int pos, int unit)
|
||||
{
|
||||
if (!po || pos >= NR_PARTICLE_POSITIONS || !po->position[pos] || unit >= NR_PARTICLE_POSITION_UNITS)
|
||||
if (!po || pos >= NR_PARTICLE_POSITIONS || !po->pae_obj->position[pos] || unit >= NR_PARTICLE_POSITION_UNITS)
|
||||
return NULL;
|
||||
return &po->position[pos]->units[unit];
|
||||
return &po->pae_obj->position[pos]->units[unit];
|
||||
}
|
||||
|
||||
int RE_particle_get_pos_unit_type(struct particle_object *po, int pos, int unit)
|
||||
@@ -666,298 +701,298 @@ int RE_particle_get_pos_unit_index(struct particle_object *po, int pos, int unit
|
||||
|
||||
int RE_particle_get_num_texture(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_textures : 0;
|
||||
return po ? po->pae_obj->nr_textures : 0;
|
||||
}
|
||||
|
||||
const char *RE_particle_get_texture(struct particle_object *po, int texture)
|
||||
{
|
||||
if (!po || texture >= po->nr_textures)
|
||||
if (!po || texture >= po->pae_obj->nr_textures)
|
||||
return NULL;
|
||||
return po->textures[texture];
|
||||
return po->pae_obj->textures[texture];
|
||||
}
|
||||
|
||||
bool RE_particle_get_size(struct particle_object *po, float *begin_size, float *end_size)
|
||||
{
|
||||
if (!po)
|
||||
return false;
|
||||
*begin_size = po->size[0];
|
||||
*end_size = po->size[1];
|
||||
*begin_size = po->pae_obj->size[0];
|
||||
*end_size = po->pae_obj->size[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_particle_get_size2(struct particle_object *po, int frame, float *size)
|
||||
{
|
||||
if (!po || frame >= po->nr_sizes2)
|
||||
if (!po || frame >= po->pae_obj->nr_sizes2)
|
||||
return false;
|
||||
*size = po->sizes2[frame];
|
||||
*size = po->pae_obj->sizes2[frame];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_particle_get_size_x(struct particle_object *po, int frame, float *size)
|
||||
{
|
||||
if (!po || frame >= po->nr_sizes_x)
|
||||
if (!po || frame >= po->pae_obj->nr_sizes_x)
|
||||
return false;
|
||||
*size = po->sizes_x[frame];
|
||||
*size = po->pae_obj->sizes_x[frame];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_particle_get_size_y(struct particle_object *po, int frame, float *size)
|
||||
{
|
||||
if (!po || frame >= po->nr_sizes_y)
|
||||
if (!po || frame >= po->pae_obj->nr_sizes_y)
|
||||
return false;
|
||||
*size = po->sizes_y[frame];
|
||||
*size = po->pae_obj->sizes_y[frame];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_particle_get_size_type(struct particle_object *po, int frame, int *type)
|
||||
{
|
||||
if (!po || frame >= po->nr_size_types)
|
||||
if (!po || frame >= po->pae_obj->nr_size_types)
|
||||
return false;
|
||||
*type = po->size_types[frame];
|
||||
*type = po->pae_obj->size_types[frame];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_particle_get_size_x_type(struct particle_object *po, int frame, int *type)
|
||||
{
|
||||
if (!po || frame >= po->nr_size_x_types)
|
||||
if (!po || frame >= po->pae_obj->nr_size_x_types)
|
||||
return false;
|
||||
*type = po->size_x_types[frame];
|
||||
*type = po->pae_obj->size_x_types[frame];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_particle_get_size_y_type(struct particle_object *po, int frame, int *type)
|
||||
{
|
||||
if (!po || frame >= po->nr_size_y_types)
|
||||
if (!po || frame >= po->pae_obj->nr_size_y_types)
|
||||
return false;
|
||||
*type = po->size_y_types[frame];
|
||||
*type = po->pae_obj->size_y_types[frame];
|
||||
return true;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_size2(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_sizes2 : 0;
|
||||
return po ? po->pae_obj->nr_sizes2 : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_size_x(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_sizes_x : 0;
|
||||
return po ? po->pae_obj->nr_sizes_x : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_size_y(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_sizes_y : 0;
|
||||
return po ? po->pae_obj->nr_sizes_y : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_size_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_size_types : 0;
|
||||
return po ? po->pae_obj->nr_size_types : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_size_x_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_size_x_types : 0;
|
||||
return po ? po->pae_obj->nr_size_x_types : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_size_y_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_size_y_types : 0;
|
||||
return po ? po->pae_obj->nr_size_y_types : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_blend_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->blend_type : 0;
|
||||
return po ? po->pae_obj->blend_type : 0;
|
||||
}
|
||||
|
||||
const char *RE_particle_get_polygon_name(struct particle_object *po)
|
||||
{
|
||||
return po ? po->polygon_name : NULL;
|
||||
return po ? po->pae_obj->polygon_name : NULL;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_particles(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_particles : 0;
|
||||
return po ? po->pae_obj->nr_particles : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_alpha_fadein_time(struct particle_object *po)
|
||||
{
|
||||
return po ? po->alpha_fadein_time : 0;
|
||||
return po ? po->pae_obj->alpha_fadein_time : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_alpha_fadeout_time(struct particle_object *po)
|
||||
{
|
||||
return po ? po->alpha_fadeout_time : 0;
|
||||
return po ? po->pae_obj->alpha_fadeout_time : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_texture_anime_time(struct particle_object *po)
|
||||
{
|
||||
return po ? po->texture_anime_time : 0;
|
||||
return po ? po->pae_obj->texture_anime_time : 0;
|
||||
}
|
||||
|
||||
float RE_particle_get_alpha_fadein_frame(struct particle_object *po)
|
||||
{
|
||||
return po ? po->alpha_fadein_frame : 0.0;
|
||||
return po ? po->pae_obj->alpha_fadein_frame : 0.0;
|
||||
}
|
||||
|
||||
float RE_particle_get_alpha_fadeout_frame(struct particle_object *po)
|
||||
{
|
||||
return po ? po->alpha_fadeout_frame : 0.0;
|
||||
return po ? po->pae_obj->alpha_fadeout_frame : 0.0;
|
||||
}
|
||||
|
||||
float RE_particle_get_texture_anime_frame(struct particle_object *po)
|
||||
{
|
||||
return po ? po->texture_anime_frame : 0.0;
|
||||
return po ? po->pae_obj->texture_anime_frame : 0.0;
|
||||
}
|
||||
|
||||
int RE_particle_get_frame_ref_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->frame_ref_type : 0;
|
||||
return po ? po->pae_obj->frame_ref_type : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_frame_ref_param(struct particle_object *po)
|
||||
{
|
||||
return po ? po->frame_ref_param : 0;
|
||||
return po ? po->pae_obj->frame_ref_param : 0;
|
||||
}
|
||||
|
||||
void RE_particle_get_x_rotation_angle(struct particle_object *po, float *begin_angle, float *end_angle)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_angle = po->rotation.begin[0];
|
||||
*end_angle = po->rotation.end[0];
|
||||
*begin_angle = po->pae_obj->rotation.begin[0];
|
||||
*end_angle = po->pae_obj->rotation.end[0];
|
||||
}
|
||||
|
||||
void RE_particle_get_y_rotation_angle(struct particle_object *po, float *begin_angle, float *end_angle)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_angle = po->rotation.begin[1];
|
||||
*end_angle = po->rotation.end[1];
|
||||
*begin_angle = po->pae_obj->rotation.begin[1];
|
||||
*end_angle = po->pae_obj->rotation.end[1];
|
||||
}
|
||||
|
||||
void RE_particle_get_z_rotation_angle(struct particle_object *po, float *begin_angle, float *end_angle)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_angle = po->rotation.begin[2];
|
||||
*end_angle = po->rotation.end[2];
|
||||
*begin_angle = po->pae_obj->rotation.begin[2];
|
||||
*end_angle = po->pae_obj->rotation.end[2];
|
||||
}
|
||||
|
||||
void RE_particle_get_x_revolution_angle(struct particle_object *po, float *begin_angle, float *end_angle)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_angle = po->revolution_angle.begin[0];
|
||||
*end_angle = po->revolution_angle.end[0];
|
||||
*begin_angle = po->pae_obj->revolution_angle.begin[0];
|
||||
*end_angle = po->pae_obj->revolution_angle.end[0];
|
||||
}
|
||||
|
||||
void RE_particle_get_x_revolution_distance(struct particle_object *po, float *begin_distance, float *end_distance)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_distance = po->revolution_distance.begin[0];
|
||||
*end_distance = po->revolution_distance.end[0];
|
||||
*begin_distance = po->pae_obj->revolution_distance.begin[0];
|
||||
*end_distance = po->pae_obj->revolution_distance.end[0];
|
||||
}
|
||||
|
||||
void RE_particle_get_y_revolution_angle(struct particle_object *po, float *begin_angle, float *end_angle)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_angle = po->revolution_angle.begin[1];
|
||||
*end_angle = po->revolution_angle.end[1];
|
||||
*begin_angle = po->pae_obj->revolution_angle.begin[1];
|
||||
*end_angle = po->pae_obj->revolution_angle.end[1];
|
||||
}
|
||||
|
||||
void RE_particle_get_y_revolution_distance(struct particle_object *po, float *begin_distance, float *end_distance)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_distance = po->revolution_distance.begin[1];
|
||||
*end_distance = po->revolution_distance.end[1];
|
||||
*begin_distance = po->pae_obj->revolution_distance.begin[1];
|
||||
*end_distance = po->pae_obj->revolution_distance.end[1];
|
||||
}
|
||||
|
||||
void RE_particle_get_z_revolution_angle(struct particle_object *po, float *begin_angle, float *end_angle)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_angle = po->revolution_angle.begin[2];
|
||||
*end_angle = po->revolution_angle.end[2];
|
||||
*begin_angle = po->pae_obj->revolution_angle.begin[2];
|
||||
*end_angle = po->pae_obj->revolution_angle.end[2];
|
||||
}
|
||||
|
||||
void RE_particle_get_z_revolution_distance(struct particle_object *po, float *begin_distance, float *end_distance)
|
||||
{
|
||||
if (!po)
|
||||
return;
|
||||
*begin_distance = po->revolution_distance.begin[2];
|
||||
*end_distance = po->revolution_distance.end[2];
|
||||
*begin_distance = po->pae_obj->revolution_distance.begin[2];
|
||||
*end_distance = po->pae_obj->revolution_distance.end[2];
|
||||
}
|
||||
|
||||
bool RE_particle_get_curve_length(struct particle_object *po, vec3 out)
|
||||
{
|
||||
if (!po)
|
||||
return false;
|
||||
glm_vec3_copy(po->curve_length, out);
|
||||
glm_vec3_copy(po->pae_obj->curve_length, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
int RE_particle_get_child_frame(struct particle_object *po)
|
||||
{
|
||||
return po ? po->child_frame : 0;
|
||||
return po ? po->pae_obj->child_frame : 0;
|
||||
}
|
||||
|
||||
float RE_particle_get_child_length(struct particle_object *po)
|
||||
{
|
||||
return po ? po->child_length : 0.0;
|
||||
return po ? po->pae_obj->child_length : 0.0;
|
||||
}
|
||||
|
||||
float RE_particle_get_child_begin_slope(struct particle_object *po)
|
||||
{
|
||||
return po ? po->child_begin_slope : 0.0;
|
||||
return po ? po->pae_obj->child_begin_slope : 0.0;
|
||||
}
|
||||
|
||||
float RE_particle_get_child_end_slope(struct particle_object *po)
|
||||
{
|
||||
return po ? po->child_end_slope : 0.0;
|
||||
return po ? po->pae_obj->child_end_slope : 0.0;
|
||||
}
|
||||
|
||||
float RE_particle_get_child_create_begin_frame(struct particle_object *po)
|
||||
{
|
||||
return po ? po->child_create_begin_frame : 0.0;
|
||||
return po ? po->pae_obj->child_create_begin_frame : 0.0;
|
||||
}
|
||||
|
||||
float RE_particle_get_child_create_end_frame(struct particle_object *po)
|
||||
{
|
||||
return po ? po->child_create_end_frame : 0.0;
|
||||
return po ? po->pae_obj->child_create_end_frame : 0.0;
|
||||
}
|
||||
|
||||
int RE_particle_get_child_move_dir_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->child_move_dir_type : 0;
|
||||
return po ? po->pae_obj->child_move_dir_type : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_dir_type(struct particle_object *po)
|
||||
{
|
||||
return po ? po->dir_type : 0;
|
||||
return po ? po->pae_obj->dir_type : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_num_damage(struct particle_object *po)
|
||||
{
|
||||
return po ? po->nr_damages : 0;
|
||||
return po ? po->pae_obj->nr_damages : 0;
|
||||
}
|
||||
|
||||
int RE_particle_get_damage(struct particle_object *po, int frame)
|
||||
{
|
||||
if (!po || frame >= po->nr_damages)
|
||||
if (!po || frame >= po->pae_obj->nr_damages)
|
||||
return 0;
|
||||
return po->damages[frame];
|
||||
return po->pae_obj->damages[frame];
|
||||
}
|
||||
|
||||
float RE_particle_get_offset_x(struct particle_object *po)
|
||||
{
|
||||
return po ? po->offset_x : 0.0;
|
||||
return po ? po->pae_obj->offset_x : 0.0;
|
||||
}
|
||||
|
||||
float RE_particle_get_offset_y(struct particle_object *po)
|
||||
{
|
||||
return po ? po->offset_y : 0.0;
|
||||
return po ? po->pae_obj->offset_y : 0.0;
|
||||
}
|
||||
|
||||
bool RE_effect_get_frame_range(struct RE_instance *instance, int *begin_frame, int *end_frame)
|
||||
|
||||
+23
-18
@@ -490,7 +490,8 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma
|
||||
|
||||
static void render_billboard_particles(struct RE_renderer *r, struct RE_instance *inst, struct particle_object *po, float frame)
|
||||
{
|
||||
if (po->nr_textures == 0)
|
||||
struct pae_object *pae_obj = po->pae_obj;
|
||||
if (pae_obj->nr_textures == 0)
|
||||
return;
|
||||
|
||||
glUniform1i(r->diffuse_type, DIFFUSE_EMISSIVE);
|
||||
@@ -500,19 +501,19 @@ static void render_billboard_particles(struct RE_renderer *r, struct RE_instance
|
||||
glUniform1i(r->texture, 0);
|
||||
glBindVertexArray(r->billboard_vao);
|
||||
|
||||
for (int index = 0; index < po->nr_particles; index++) {
|
||||
for (int index = 0; index < pae_obj->nr_particles; index++) {
|
||||
struct particle_instance *pi = &po->instances[index];
|
||||
if (frame < pi->begin_frame || pi->end_frame < frame)
|
||||
if (frame < pi->begin_frame || pi->end_frame <= frame)
|
||||
continue;
|
||||
|
||||
int step = (int)((frame - pi->begin_frame) / po->texture_anime_frame);
|
||||
struct billboard_texture *bt = ht_get(inst->effect->textures, po->textures[step % po->nr_textures], NULL);
|
||||
int step = (int)((frame - pi->begin_frame) / pae_obj->texture_anime_frame);
|
||||
struct billboard_texture *bt = ht_get(inst->effect->pae->textures, pae_obj->textures[step % pae_obj->nr_textures], NULL);
|
||||
if (!bt)
|
||||
continue;
|
||||
glBindTexture(GL_TEXTURE_2D, bt->texture);
|
||||
|
||||
float alpha = particle_object_calc_alpha(po, pi, frame);
|
||||
if (po->blend_type == PARTICLE_BLEND_ADDITIVE && !bt->has_alpha)
|
||||
float alpha = pae_object_calc_alpha(pae_obj, pi, frame);
|
||||
if (pae_obj->blend_type == PARTICLE_BLEND_ADDITIVE && !bt->has_alpha)
|
||||
alpha *= alpha; // why...
|
||||
glUniform1f(r->alpha_mod, alpha);
|
||||
|
||||
@@ -530,19 +531,20 @@ static void render_billboard_particles(struct RE_renderer *r, struct RE_instance
|
||||
|
||||
static void render_polygon_particles(struct RE_renderer *r, struct RE_instance *inst, struct particle_object *po, float frame)
|
||||
{
|
||||
struct model *model = po->model;
|
||||
struct pae_object *pae_obj = po->pae_obj;
|
||||
struct model *model = pae_obj->model;
|
||||
if (!model)
|
||||
return;
|
||||
|
||||
glUniform1i(r->diffuse_type, DIFFUSE_NORMAL);
|
||||
glUniform1i(r->fog_type, inst->plugin->fog_mode ? inst->plugin->fog_type : 0);
|
||||
|
||||
for (int index = 0; index < po->nr_particles; index++) {
|
||||
for (int index = 0; index < pae_obj->nr_particles; index++) {
|
||||
struct particle_instance *pi = &po->instances[index];
|
||||
if (frame < pi->begin_frame || pi->end_frame < frame)
|
||||
if (frame < pi->begin_frame || pi->end_frame <= frame)
|
||||
continue;
|
||||
|
||||
float alpha = particle_object_calc_alpha(po, pi, frame);
|
||||
float alpha = pae_object_calc_alpha(pae_obj, pi, frame);
|
||||
glUniform1f(r->alpha_mod, alpha);
|
||||
|
||||
mat4 local_transform;
|
||||
@@ -588,10 +590,10 @@ static void render_particle_effect(struct RE_instance *inst, struct RE_renderer
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
for (int i = 0; i < inst->effect->nr_objects; i++) {
|
||||
for (int i = 0; i < inst->effect->pae->nr_objects; i++) {
|
||||
struct particle_object *po = &inst->effect->objects[i];
|
||||
|
||||
switch (po->blend_type) {
|
||||
switch (po->pae_obj->blend_type) {
|
||||
case PARTICLE_BLEND_NORMAL:
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
@@ -600,7 +602,7 @@ static void render_particle_effect(struct RE_instance *inst, struct RE_renderer
|
||||
break;
|
||||
}
|
||||
|
||||
switch (po->type) {
|
||||
switch (po->pae_obj->type) {
|
||||
case PARTICLE_TYPE_BILLBOARD:
|
||||
render_billboard_particles(r, inst, po, inst->motion->current_frame);
|
||||
break;
|
||||
@@ -968,7 +970,7 @@ void RE_renderer_free_height_detector(struct height_detector *hd)
|
||||
free(hd);
|
||||
}
|
||||
|
||||
float RE_renderer_detect_height(struct height_detector *hd, float x, float z)
|
||||
bool RE_renderer_detect_height(struct height_detector *hd, float x, float z, float *y_out)
|
||||
{
|
||||
float minx = hd->aabb[0][0];
|
||||
float maxx = hd->aabb[1][0];
|
||||
@@ -977,9 +979,12 @@ float RE_renderer_detect_height(struct height_detector *hd, float x, float z)
|
||||
float minz = hd->aabb[0][2];
|
||||
float maxz = hd->aabb[1][2];
|
||||
if (x < minx || x > maxx || z < minz || z > maxz)
|
||||
return 0.0;
|
||||
return false;
|
||||
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);
|
||||
GLushort val = hd->buf[pz * SHADOW_WIDTH + px];
|
||||
if (!val)
|
||||
return false;
|
||||
*y_out = glm_lerp(maxy, miny, val / 65535.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user