mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-05 13:18:01 +03:00
742 lines
23 KiB
C++
742 lines
23 KiB
C++
/*
|
|
by korenkonder
|
|
GitHub/GitLab: korenkonder
|
|
*/
|
|
|
|
#include "glitter.hpp"
|
|
|
|
namespace Glitter {
|
|
RenderGroup::RenderGroup() : flags(), type(), draw_type(), pivot(), z_offset(),
|
|
count(), ctrl(), disp(), texture(), mask_texture(), frame(), elements(),
|
|
buffer(), max_count(), random_ptr(), disp_type(), fog_type(), vao() {
|
|
split_u = 1;
|
|
split_v = 1;
|
|
split_uv = 1.0f;
|
|
mat = mat4_identity;
|
|
mat_rot = mat4_identity;
|
|
mat_draw = mat4_identity;
|
|
disp_type = DISP_NORMAL;
|
|
emission = 1.0f;
|
|
#if !SHARED_GLITTER_BUFFER
|
|
use_own_buffer = true;
|
|
#endif
|
|
blend_mode = PARTICLE_BLEND_TYPICAL;
|
|
mask_blend_mode = PARTICLE_BLEND_TYPICAL;
|
|
}
|
|
|
|
RenderGroup::~RenderGroup() {
|
|
|
|
}
|
|
|
|
RenderElement* RenderGroup::AddElement(RenderElement* rend_elem) {
|
|
if (!rend_elem)
|
|
rend_elem = elements;
|
|
|
|
size_t left_count = count - (rend_elem - elements);
|
|
size_t index = 0;
|
|
if (left_count < 1)
|
|
return 0;
|
|
|
|
while (rend_elem->alive) {
|
|
index++;
|
|
rend_elem++;
|
|
if (index >= left_count)
|
|
return 0;
|
|
}
|
|
|
|
rend_elem->alive = true;
|
|
ctrl++;
|
|
return rend_elem;
|
|
}
|
|
|
|
F2RenderGroup::F2RenderGroup(F2ParticleInst* ptcl_inst) : particle() {
|
|
switch (ptcl_inst->data.data.type) {
|
|
case PARTICLE_QUAD:
|
|
case PARTICLE_LINE:
|
|
case PARTICLE_LOCUS:
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if (ptcl_inst->data.data.count > 0)
|
|
count = ptcl_inst->data.data.count;
|
|
else
|
|
count = ptcl_inst->data.data.type == PARTICLE_LOCUS ? 30 : 250;
|
|
max_count = count * 4;
|
|
|
|
random_ptr = ptcl_inst->data.random_ptr;
|
|
particle = ptcl_inst;
|
|
|
|
elements = new RenderElement[count];
|
|
if (!elements || !ptcl_inst) {
|
|
count = 0;
|
|
max_count = 0;
|
|
return;
|
|
}
|
|
|
|
memset(elements, 0, sizeof(RenderElement) * count);
|
|
if (!max_count)
|
|
return;
|
|
|
|
bool is_quad = ptcl_inst->data.data.type == PARTICLE_QUAD;
|
|
|
|
Particle* ptcl = particle->data.particle;
|
|
if (ptcl && ptcl->buffer && !ptcl->buffer_used) {
|
|
buffer = ptcl->buffer;
|
|
max_count = ptcl->max_count;
|
|
vao = ptcl->vao;
|
|
#if !SHARED_GLITTER_BUFFER
|
|
vbo = ptcl->vbo;
|
|
ebo = ptcl->ebo;
|
|
use_own_buffer = false;
|
|
#endif
|
|
ptcl->buffer_used = true;
|
|
}
|
|
|
|
#if !SHARED_GLITTER_BUFFER
|
|
if (use_own_buffer)
|
|
CreateBuffer(max_count, is_quad, buffer, vao, vbo, ebo);
|
|
#endif
|
|
|
|
if (!is_quad)
|
|
draw_list.reserve(count);
|
|
}
|
|
|
|
F2RenderGroup::~F2RenderGroup() {
|
|
DeleteBuffers(false);
|
|
}
|
|
|
|
bool F2RenderGroup::CannotDisp() {
|
|
if (!particle)
|
|
return true;
|
|
else if (particle->data.effect)
|
|
return (particle->data.effect->flags & EFFECT_INST_EXT_ANIM_NON_INIT) != 0;
|
|
else if ((particle = particle->data.parent) && particle->data.effect)
|
|
return (particle->data.effect->flags & EFFECT_INST_EXT_ANIM_NON_INIT) != 0;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
void F2RenderGroup::Copy(F2RenderGroup* dst) {
|
|
dst->flags = flags;
|
|
dst->type = type;
|
|
dst->draw_type = draw_type;
|
|
dst->blend_mode = blend_mode;
|
|
dst->mask_blend_mode = mask_blend_mode;
|
|
dst->pivot = pivot;
|
|
dst->split_u = split_u;
|
|
dst->split_v = split_v;
|
|
dst->split_uv = split_uv;
|
|
dst->z_offset = z_offset;
|
|
if (dst->count > count)
|
|
dst->count = count;
|
|
dst->ctrl = ctrl;
|
|
dst->texture = texture;
|
|
dst->mask_texture = mask_texture;
|
|
dst->frame = frame;
|
|
dst->mat = mat;
|
|
dst->mat_rot = mat_rot;
|
|
dst->mat_draw = mat_draw;
|
|
if (dst->count == count) {
|
|
memmove(dst->elements, elements, sizeof(RenderElement) * dst->count);
|
|
dst->ctrl = ctrl;
|
|
}
|
|
}
|
|
|
|
void F2RenderGroup::Ctrl(GLT, float_t delta_frame, bool copy_mats) {
|
|
if (!particle)
|
|
return;
|
|
|
|
Particle::Data* ptcl_data = &particle->data.data;
|
|
blend_mode = ptcl_data->blend_mode;
|
|
mask_blend_mode = ptcl_data->mask_blend_mode;
|
|
texture = ptcl_data->texture;
|
|
mask_texture = ptcl_data->mask_texture;
|
|
split_u = ptcl_data->split_u;
|
|
split_v = ptcl_data->split_v;
|
|
split_uv = ptcl_data->split_uv;
|
|
type = ptcl_data->type;
|
|
draw_type = ptcl_data->draw_type;
|
|
z_offset = ptcl_data->z_offset;
|
|
pivot = ptcl_data->pivot;
|
|
flags = ptcl_data->flags;
|
|
name.assign(ptcl_data->name);
|
|
|
|
if (copy_mats && particle->data.emitter) {
|
|
F2EmitterInst* emitter = particle->data.emitter;
|
|
mat = emitter->mat;
|
|
mat_rot = emitter->mat_rot;
|
|
}
|
|
|
|
for (size_t ctrl = this->ctrl, i = 0; ctrl; i++) {
|
|
if (!elements[i].alive)
|
|
continue;
|
|
|
|
CtrlParticle(GLT_VAL, &elements[i], delta_frame);
|
|
ctrl--;
|
|
}
|
|
frame += delta_frame;
|
|
}
|
|
|
|
void F2RenderGroup::CtrlParticle(GLT, Glitter::RenderElement* rend_elem, float_t delta_frame) {
|
|
if (!particle || (particle->data.data.flags & PARTICLE_LOOP
|
|
&& particle->HasEnded(false)) || rend_elem->frame >= rend_elem->life_time) {
|
|
rend_elem->alive = false;
|
|
if (rend_elem->locus_history) {
|
|
delete rend_elem->locus_history;
|
|
rend_elem->locus_history = 0;
|
|
}
|
|
ctrl--;
|
|
return;
|
|
}
|
|
|
|
particle->AccelerateParticle(GLT_VAL, rend_elem,
|
|
rend_elem->frame * (float_t)(1.0 / 60.0), delta_frame, random_ptr);
|
|
if (particle->data.data.draw_type == DIRECTION_PARTICLE_ROTATION)
|
|
rend_elem->rotation += rend_elem->rotation_add * delta_frame;
|
|
else
|
|
rend_elem->rotation.z += rend_elem->rotation_add.z * delta_frame;
|
|
|
|
rend_elem->uv_scroll += particle->data.data.uv_scroll_add
|
|
* (particle->data.data.uv_scroll_add_scale * delta_frame);
|
|
|
|
particle->StepUVParticle(GLT_VAL, rend_elem, delta_frame, random_ptr);
|
|
rend_elem->disp = true;
|
|
rend_elem->color = -1.0f;
|
|
|
|
bool disp = true;
|
|
if (particle->data.data.sub_flags & PARTICLE_SUB_USE_CURVE)
|
|
disp = particle->GetValue(GLT_VAL, rend_elem, rend_elem->frame, random_ptr);
|
|
|
|
if (particle->data.data.draw_type == DIRECTION_PARTICLE_ROTATION
|
|
|| fabsf(rend_elem->rotation.z) <= 0.000001f) {
|
|
rend_elem->rot_z_cos = 1.0f;
|
|
rend_elem->rot_z_sin = 0.0f;
|
|
}
|
|
else {
|
|
rend_elem->rot_z_cos = cosf(rend_elem->rotation.z);
|
|
rend_elem->rot_z_sin = sinf(rend_elem->rotation.z);
|
|
}
|
|
|
|
if (disp)
|
|
particle->GetColor(rend_elem);
|
|
|
|
if (particle->data.data.type == PARTICLE_LOCUS)
|
|
rend_elem->locus_history->Append(rend_elem, particle);
|
|
|
|
rend_elem->frame += delta_frame;
|
|
if (particle->data.data.flags & PARTICLE_LOOP && rend_elem->frame >= rend_elem->life_time)
|
|
rend_elem->frame -= rend_elem->life_time;
|
|
}
|
|
|
|
void F2RenderGroup::DeleteBuffers(bool free) {
|
|
Particle* ptcl = 0;
|
|
if (particle) {
|
|
ptcl = particle->data.particle;
|
|
if (!free)
|
|
particle->data.render_group = 0;
|
|
particle = 0;
|
|
}
|
|
|
|
#if SHARED_GLITTER_BUFFER
|
|
if (ptcl && ptcl->buffer)
|
|
ptcl->buffer_used = false;
|
|
#else
|
|
if (use_own_buffer)
|
|
Glitter::DeleteBuffer(buffer, vao, vbo, ebo);
|
|
else if (ptcl && ptcl->buffer)
|
|
ptcl->buffer_used = false;
|
|
#endif
|
|
|
|
if (!free && elements) {
|
|
Free();
|
|
delete[] elements;
|
|
elements = 0;
|
|
}
|
|
}
|
|
|
|
void F2RenderGroup::Emit(GPM, GLT, Particle::Data* ptcl_data,
|
|
F2EmitterInst* emit_inst, int32_t dup_count, int32_t count) {
|
|
RenderElement* element = 0;
|
|
for (int32_t i = 0; i < dup_count; i++)
|
|
for (int32_t index = 0; index < count; index++, element++) {
|
|
element = AddElement(element);
|
|
if (!element)
|
|
break;
|
|
|
|
particle->EmitParticle(GPM_VAL, GLT_VAL,
|
|
element, emit_inst, ptcl_data, index, random_ptr);
|
|
}
|
|
}
|
|
|
|
void F2RenderGroup::Free() {
|
|
if (count <= 0) {
|
|
ctrl = 0;
|
|
return;
|
|
}
|
|
|
|
RenderElement* elem = elements;
|
|
for (size_t i = count; i; i--, elem++) {
|
|
elem->alive = false;
|
|
if (elem->locus_history) {
|
|
delete elem->locus_history;
|
|
elem->locus_history = 0;
|
|
}
|
|
}
|
|
ctrl = 0;
|
|
}
|
|
|
|
void F2RenderGroup::FreeData() {
|
|
DeleteBuffers(true);
|
|
}
|
|
|
|
bool F2RenderGroup::GetExtAnimScale(vec3* ext_anim_scale, float_t* ext_scale) {
|
|
if (particle)
|
|
particle->GetExtAnimScale(ext_anim_scale, ext_scale);
|
|
return false;
|
|
}
|
|
|
|
mat4 F2RenderGroup::RotateToEmitPosition(F2RenderGroup* rend_group,
|
|
RenderElement* rend_elem, vec3* vec) {
|
|
vec3 vec2;
|
|
if (rend_group->flags & PARTICLE_EMITTER_LOCAL)
|
|
vec2 = rend_elem->translation;
|
|
else {
|
|
mat4_get_translation(&rend_group->mat, &vec2);
|
|
vec2 -= rend_elem->translation;
|
|
}
|
|
vec2 = vec3::normalize(vec2);
|
|
|
|
mat4 mat;
|
|
if (fabsf(vec2.y) >= 0.000001f) {
|
|
mat = mat4_identity;
|
|
vec3 vec1 = *vec;
|
|
|
|
vec3 axis;
|
|
float_t angle;
|
|
axis_angle_from_vectors(axis, angle, vec1, vec2);
|
|
mat4_mul_rotation(&mat, &axis, angle, &mat);
|
|
}
|
|
else
|
|
mat4_rotate_z((float_t)M_PI, &mat);
|
|
return mat;
|
|
}
|
|
|
|
mat4 F2RenderGroup::RotateToPrevPosition(F2RenderGroup* rend_group,
|
|
RenderElement* rend_elem, vec3* vec) {
|
|
vec3 vec2 = rend_elem->translation - rend_elem->translation_prev;
|
|
|
|
if (vec3::length_squared(vec2) < 0.000001f)
|
|
vec2 = vec3::normalize(rend_elem->translation);
|
|
else
|
|
vec2 = vec3::normalize(vec2);
|
|
|
|
mat4 mat;
|
|
mat4_rotate_z((float_t)M_PI, &mat);
|
|
if (fabsf(vec2.y) >= 0.000001f) {
|
|
vec3 vec1 = *vec;
|
|
|
|
vec3 axis;
|
|
float_t angle;
|
|
axis_angle_from_vectors(axis, angle, vec1, vec2);
|
|
mat4_mul_rotation(&mat, &axis, angle, &mat);
|
|
}
|
|
return mat;
|
|
}
|
|
|
|
XRenderGroup::XRenderGroup(XParticleInst* ptcl_inst) : particle(), use_culling(), use_camera() {
|
|
object_name_hash = hash_murmurhash_empty;
|
|
|
|
switch (ptcl_inst->data.data.type) {
|
|
case PARTICLE_QUAD:
|
|
if (ptcl_inst->data.data.count > 0)
|
|
count = ptcl_inst->data.data.count;
|
|
else
|
|
count = 2500;
|
|
max_count = 4 * count;
|
|
break;
|
|
case PARTICLE_LINE:
|
|
count = (size_t)ptcl_inst->data.data.locus_history_size
|
|
+ ptcl_inst->data.data.locus_history_size_random;
|
|
max_count = count;
|
|
break;
|
|
case PARTICLE_LOCUS:
|
|
count = (size_t)ptcl_inst->data.data.locus_history_size
|
|
+ ptcl_inst->data.data.locus_history_size_random;
|
|
max_count = 2 * count;
|
|
break;
|
|
case PARTICLE_MESH:
|
|
count = 1280;
|
|
max_count = 0;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
random_ptr = ptcl_inst->data.random_ptr;
|
|
particle = ptcl_inst;
|
|
|
|
elements = new RenderElement[count];
|
|
if (!elements || !ptcl_inst) {
|
|
count = 0;
|
|
max_count = 0;
|
|
return;
|
|
}
|
|
|
|
memset(elements, 0, sizeof(RenderElement) * count);
|
|
if (!max_count || ptcl_inst->data.data.type == PARTICLE_MESH)
|
|
return;
|
|
|
|
bool is_quad = ptcl_inst->data.data.type == PARTICLE_QUAD;
|
|
|
|
Particle* ptcl = particle->data.particle;
|
|
if (ptcl && ptcl->buffer && !ptcl->buffer_used) {
|
|
buffer = ptcl->buffer;
|
|
max_count = ptcl->max_count;
|
|
vao = ptcl->vao;
|
|
#if !SHARED_GLITTER_BUFFER
|
|
vbo = ptcl->vbo;
|
|
ebo = ptcl->ebo;
|
|
use_own_buffer = false;
|
|
#endif
|
|
ptcl->buffer_used = true;
|
|
}
|
|
|
|
#if !SHARED_GLITTER_BUFFER
|
|
if (use_own_buffer)
|
|
CreateBuffer(max_count, is_quad, buffer, vao, vbo, ebo);
|
|
#endif
|
|
|
|
if (!is_quad)
|
|
draw_list.reserve(count);
|
|
}
|
|
|
|
XRenderGroup::~XRenderGroup() {
|
|
DeleteBuffers(false);
|
|
}
|
|
|
|
bool XRenderGroup::CannotDisp() {
|
|
if (!particle)
|
|
return true;
|
|
else if (particle->data.effect)
|
|
return (particle->data.effect->flags & EFFECT_INST_EXT_ANIM_NON_INIT) != 0;
|
|
else if ((particle = particle->data.parent) && particle->data.effect)
|
|
return (particle->data.effect->flags & EFFECT_INST_EXT_ANIM_NON_INIT) != 0;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
void XRenderGroup::CheckUseCamera() {
|
|
if (particle)
|
|
use_camera = particle->GetUseCamera();
|
|
else
|
|
use_camera = false;
|
|
}
|
|
|
|
void XRenderGroup::Copy(XRenderGroup* dst) {
|
|
dst->flags = flags;
|
|
dst->type = type;
|
|
dst->draw_type = draw_type;
|
|
dst->blend_mode = blend_mode;
|
|
dst->mask_blend_mode = mask_blend_mode;
|
|
dst->pivot = pivot;
|
|
dst->split_u = split_u;
|
|
dst->split_v = split_v;
|
|
dst->split_uv = split_uv;
|
|
dst->z_offset = z_offset;
|
|
if (dst->count > count)
|
|
dst->count = count;
|
|
dst->ctrl = ctrl;
|
|
dst->texture = texture;
|
|
dst->mask_texture = mask_texture;
|
|
dst->frame = frame;
|
|
dst->mat = mat;
|
|
dst->mat_rot = mat_rot;
|
|
dst->mat_draw = mat_draw;
|
|
if (dst->count == count) {
|
|
memmove(dst->elements, elements, sizeof(RenderElement) * dst->count);
|
|
dst->ctrl = ctrl;
|
|
}
|
|
}
|
|
|
|
void XRenderGroup::Ctrl(float_t delta_frame, bool copy_mats) {
|
|
if (!particle)
|
|
return;
|
|
|
|
Particle::Data* ptcl_data = &particle->data.data;
|
|
blend_mode = ptcl_data->blend_mode;
|
|
mask_blend_mode = ptcl_data->mask_blend_mode;
|
|
texture = ptcl_data->texture;
|
|
mask_texture = ptcl_data->mask_texture;
|
|
object_name_hash = ptcl_data->mesh.object_name_hash;
|
|
split_u = ptcl_data->split_u;
|
|
split_v = ptcl_data->split_v;
|
|
split_uv = ptcl_data->split_uv;
|
|
type = ptcl_data->type;
|
|
draw_type = ptcl_data->draw_type;
|
|
z_offset = ptcl_data->z_offset;
|
|
pivot = ptcl_data->pivot;
|
|
flags = ptcl_data->flags;
|
|
|
|
if (copy_mats && particle->data.emitter) {
|
|
XEmitterInst* emitter = particle->data.emitter;
|
|
mat = emitter->mat;
|
|
mat_rot = emitter->mat_rot;
|
|
}
|
|
|
|
for (size_t ctrl = this->ctrl, i = 0; ctrl; i++) {
|
|
if (!elements[i].alive)
|
|
continue;
|
|
|
|
CtrlParticle(&elements[i], delta_frame);
|
|
ctrl--;
|
|
}
|
|
frame += delta_frame;
|
|
}
|
|
|
|
void XRenderGroup::CtrlParticle(RenderElement* rend_elem, float_t delta_frame) {
|
|
random_ptr->XSetStep(rend_elem->step);
|
|
if (!particle || (particle->data.data.flags & PARTICLE_LOOP
|
|
&& particle->HasEnded(false)) || rend_elem->frame >= rend_elem->life_time) {
|
|
rend_elem->alive = false;
|
|
if (rend_elem->locus_history) {
|
|
delete rend_elem->locus_history;
|
|
rend_elem->locus_history = 0;
|
|
}
|
|
ctrl--;
|
|
return;
|
|
}
|
|
|
|
particle->AccelerateParticle(rend_elem, delta_frame, random_ptr);
|
|
|
|
if (particle->data.data.draw_type == DIRECTION_PARTICLE_ROTATION
|
|
|| particle->data.data.type == PARTICLE_MESH)
|
|
rend_elem->rotation += rend_elem->rotation_add * delta_frame;
|
|
else
|
|
rend_elem->rotation.z += rend_elem->rotation_add.z * delta_frame;
|
|
|
|
vec2 uv_scroll = particle->data.data.uv_scroll_add
|
|
* (particle->data.data.uv_scroll_add_scale * delta_frame);
|
|
if (uv_scroll.x != 0.0f)
|
|
rend_elem->uv_scroll.x = fmodf(rend_elem->uv_scroll.x + uv_scroll.x, 1.0f);
|
|
if (uv_scroll.y != 0.0f)
|
|
rend_elem->uv_scroll.y = fmodf(rend_elem->uv_scroll.y + uv_scroll.y, 1.0f);
|
|
|
|
if (particle->data.data.sub_flags & PARTICLE_SUB_UV_2ND_ADD) {
|
|
vec2 uv_scroll_2nd = particle->data.data.uv_scroll_2nd_add
|
|
* (particle->data.data.uv_scroll_2nd_add_scale * delta_frame);
|
|
if (uv_scroll_2nd.x != 0.0f)
|
|
rend_elem->uv_scroll_2nd.x = fmodf(rend_elem->uv_scroll_2nd.x + uv_scroll_2nd.x, 1.0f);
|
|
if (uv_scroll_2nd.y != 0.0f)
|
|
rend_elem->uv_scroll_2nd.y = fmodf(rend_elem->uv_scroll_2nd.y + uv_scroll_2nd.y, 1.0f);
|
|
}
|
|
|
|
particle->StepUVParticle(rend_elem, delta_frame, random_ptr);
|
|
rend_elem->disp = true;
|
|
rend_elem->color = -1.0f;
|
|
|
|
bool disp = true;
|
|
float_t color_scale = -1.0f;
|
|
if (particle->data.data.sub_flags & PARTICLE_SUB_USE_CURVE)
|
|
disp = particle->GetValue(rend_elem, rend_elem->frame, random_ptr, &color_scale);
|
|
|
|
if (particle->data.data.draw_type == DIRECTION_PARTICLE_ROTATION
|
|
|| fabsf(rend_elem->rotation.z) <= 0.000001f) {
|
|
rend_elem->rot_z_cos = 1.0f;
|
|
rend_elem->rot_z_sin = 0.0f;
|
|
}
|
|
else {
|
|
rend_elem->rot_z_cos = cosf(rend_elem->rotation.z);
|
|
rend_elem->rot_z_sin = sinf(rend_elem->rotation.z);
|
|
}
|
|
|
|
if (disp)
|
|
particle->GetColor(rend_elem, color_scale);
|
|
|
|
if (particle->data.data.type == PARTICLE_LOCUS)
|
|
rend_elem->locus_history->Append(rend_elem, particle);
|
|
|
|
rend_elem->frame += delta_frame;
|
|
if (particle->data.data.flags & PARTICLE_LOOP && rend_elem->frame >= rend_elem->life_time)
|
|
rend_elem->frame -= rend_elem->life_time;
|
|
}
|
|
|
|
void XRenderGroup::DeleteBuffers(bool free) {
|
|
Particle* ptcl = 0;
|
|
if (particle) {
|
|
ptcl = particle->data.particle;
|
|
if (!free)
|
|
particle->data.render_group = 0;
|
|
particle = 0;
|
|
}
|
|
|
|
#if SHARED_GLITTER_BUFFER
|
|
if (ptcl && ptcl->buffer)
|
|
ptcl->buffer_used = false;
|
|
#else
|
|
if (use_own_buffer)
|
|
Glitter::DeleteBuffer(buffer, vao, vbo, ebo);
|
|
else if (ptcl && ptcl->buffer)
|
|
ptcl->buffer_used = false;
|
|
#endif
|
|
|
|
if (!free && elements) {
|
|
Free();
|
|
delete[] elements;
|
|
elements = 0;
|
|
}
|
|
}
|
|
|
|
void XRenderGroup::Emit(Particle::Data* ptcl_data,
|
|
XEmitterInst* emit_inst, int32_t dup_count, int32_t count, float_t frame) {
|
|
RenderElement* element;
|
|
int64_t i;
|
|
int32_t index;
|
|
uint8_t step;
|
|
|
|
step = emit_inst->RandomGetStep();
|
|
random_ptr->XSetStep(1);
|
|
for (element = 0, i = 0; i < dup_count; i++)
|
|
for (index = 0; index < count; index++, element++) {
|
|
element = AddElement(element);
|
|
if (!element)
|
|
break;
|
|
|
|
emit_inst->RandomStepValue();
|
|
element->frame = frame;
|
|
particle->EmitParticle(element, emit_inst, ptcl_data, index, step, random_ptr);
|
|
}
|
|
}
|
|
|
|
void XRenderGroup::Free() {
|
|
if (count <= 0) {
|
|
ctrl = 0;
|
|
return;
|
|
}
|
|
|
|
RenderElement* elem = elements;
|
|
for (size_t i = count; i; i--, elem++) {
|
|
elem->alive = false;
|
|
if (elem->locus_history) {
|
|
delete elem->locus_history;
|
|
elem->locus_history = 0;
|
|
}
|
|
}
|
|
ctrl = 0;
|
|
}
|
|
|
|
void XRenderGroup::FreeData() {
|
|
DeleteBuffers(true);
|
|
}
|
|
|
|
bool XRenderGroup::GetEmitterScale(vec3& emitter_scale) {
|
|
if (particle) {
|
|
Glitter::EmitterInst* emit_inst = particle->data.emitter;
|
|
if (emit_inst) {
|
|
emitter_scale = emit_inst->scale * emit_inst->scale_all;
|
|
return emitter_scale.x > 0.000001f || emitter_scale.y > 0.000001f || emitter_scale.z > 0.000001f;
|
|
}
|
|
}
|
|
|
|
emitter_scale = 1.0f;
|
|
return false;
|
|
}
|
|
|
|
bool XRenderGroup::GetExtAnimScale(vec3* ext_anim_scale, float_t* ext_scale) {
|
|
if (particle)
|
|
particle->GetExtAnimScale(ext_anim_scale, ext_scale);
|
|
return false;
|
|
}
|
|
|
|
bool XRenderGroup::HasEnded() {
|
|
if (particle)
|
|
return particle->HasEnded(true);
|
|
return true;
|
|
}
|
|
|
|
mat4 XRenderGroup::RotateMeshToEmitPosition(XRenderGroup* rend_group,
|
|
RenderElement* rend_elem, vec3* vec, vec3* trans) {
|
|
vec3 vec2;
|
|
mat4_get_translation(&rend_group->mat, &vec2);
|
|
vec2 -= *trans;
|
|
|
|
if (vec3::length_squared(vec2) < 0.000001f)
|
|
vec2 = { 0.0f, 1.0f, 0.0f };
|
|
else
|
|
vec2 = vec3::normalize(vec2);
|
|
|
|
vec3 vec1 = *vec;
|
|
|
|
vec3 axis;
|
|
float_t angle;
|
|
axis_angle_from_vectors(axis, angle, vec1, vec2);
|
|
|
|
mat4 mat = mat4_identity;
|
|
mat4_mul_rotation(&mat, &axis, angle, &mat);
|
|
return mat;
|
|
}
|
|
|
|
mat4 XRenderGroup::RotateMeshToPrevPosition(XRenderGroup* rend_group,
|
|
RenderElement* rend_elem, vec3* vec, vec3* trans) {
|
|
vec3 vec2 = rend_elem->translation - rend_elem->translation_prev;
|
|
|
|
if (vec3::length_squared(vec2) < 0.000001f)
|
|
vec2 = vec3::normalize(rend_elem->base_direction);
|
|
else
|
|
vec2 = vec3::normalize(vec2);
|
|
|
|
vec3 vec1 = *vec;
|
|
|
|
vec3 axis;
|
|
float_t angle;
|
|
axis_angle_from_vectors(axis, angle, vec1, vec2);
|
|
|
|
mat4 mat = mat4_identity;
|
|
mat4_mul_rotation(&mat, &axis, angle, &mat);
|
|
return mat;
|
|
}
|
|
|
|
mat4 XRenderGroup::RotateToEmitPosition(XRenderGroup* rend_group,
|
|
RenderElement* rend_elem, vec3* vec) {
|
|
vec3 vec2;
|
|
mat4_get_translation(&rend_elem->mat, &vec2);
|
|
vec2 -= rend_elem->translation;
|
|
|
|
if (vec3::length_squared(vec2) < 0.000001f)
|
|
vec2 = { 0.0f, 1.0f, 0.0f };
|
|
else
|
|
vec3::normalize(vec2);
|
|
|
|
vec3 vec1 = *vec;
|
|
|
|
vec3 axis;
|
|
float_t angle;
|
|
axis_angle_from_vectors(axis, angle, vec1, vec2);
|
|
|
|
mat4 mat = mat4_identity;
|
|
mat4_mul_rotation(&mat, &axis, angle, &mat);
|
|
return mat;
|
|
}
|
|
|
|
mat4 XRenderGroup::RotateToPrevPosition(XRenderGroup* rend_group,
|
|
RenderElement* rend_elem, vec3* vec) {
|
|
vec3 vec2 = rend_elem->translation - rend_elem->translation_prev;
|
|
|
|
if (vec3::length_squared(vec2) < 0.000001f)
|
|
vec2 = vec3::normalize(rend_elem->base_direction);
|
|
else
|
|
vec2 = vec3::normalize(vec2);
|
|
|
|
vec3 vec1 = *vec;
|
|
|
|
vec3 axis;
|
|
float_t angle;
|
|
axis_angle_from_vectors(axis, angle, vec1, vec2);
|
|
|
|
mat4 mat = mat4_identity;
|
|
mat4_mul_rotation(&mat, &axis, angle, &mat);
|
|
return mat;
|
|
}
|
|
}
|