/* by korenkonder GitHub/GitLab: korenkonder */ #include "glitter.hpp" #include "../gl_state.hpp" namespace Glitter { const float_t min_emission = 0.01f; const CurveTypeFlags effect_curve_flags = (CurveTypeFlags)(0 | CURVE_TYPE_TRANSLATION_XYZ | CURVE_TYPE_ROTATION_XYZ | CURVE_TYPE_SCALE_XYZ | CURVE_TYPE_SCALE_ALL | CURVE_TYPE_COLOR_RGBA); const CurveTypeFlags emitter_curve_flags = (CurveTypeFlags)(0 | CURVE_TYPE_TRANSLATION_XYZ | CURVE_TYPE_ROTATION_XYZ | CURVE_TYPE_SCALE_XYZ | CURVE_TYPE_SCALE_ALL | CURVE_TYPE_EMISSION_INTERVAL | CURVE_TYPE_PARTICLES_PER_EMISSION); const CurveTypeFlags particle_curve_flags = (CurveTypeFlags)(0 | CURVE_TYPE_TRANSLATION_XYZ | CURVE_TYPE_ROTATION_XYZ | CURVE_TYPE_SCALE_XYZ | CURVE_TYPE_SCALE_ALL | CURVE_TYPE_COLOR_RGBA | CURVE_TYPE_UV_SCROLL); const CurveTypeFlags particle_x_curve_flags = (CurveTypeFlags)(0 | CURVE_TYPE_TRANSLATION_XYZ | CURVE_TYPE_ROTATION_XYZ | CURVE_TYPE_SCALE_XYZ | CURVE_TYPE_SCALE_ALL | CURVE_TYPE_COLOR_RGBA | CURVE_TYPE_COLOR_RGB_SCALE | CURVE_TYPE_UV_SCROLL | CURVE_TYPE_UV_SCROLL_2ND); const Direction emitter_direction_types[] = { DIRECTION_BILLBOARD, DIRECTION_BILLBOARD_Y_AXIS, DIRECTION_X_AXIS, DIRECTION_Y_AXIS, DIRECTION_Z_AXIS, DIRECTION_EFFECT_ROTATION, }; const size_t emitter_direction_types_count = sizeof(emitter_direction_types) / sizeof(Direction); const Direction emitter_direction_default_direction = DIRECTION_EFFECT_ROTATION; const EmitterDirection emitter_direction_default = EMITTER_DIRECTION_EFFECT_ROTATION; const Direction particle_draw_types[] = { DIRECTION_BILLBOARD, DIRECTION_BILLBOARD_Y_AXIS, DIRECTION_X_AXIS, DIRECTION_Y_AXIS, DIRECTION_Z_AXIS, DIRECTION_EMITTER_DIRECTION, DIRECTION_EMITTER_ROTATION, DIRECTION_PARTICLE_ROTATION, DIRECTION_PREV_POSITION, DIRECTION_PREV_POSITION_DUP, DIRECTION_EMIT_POSITION, }; const size_t particle_draw_types_count = sizeof(particle_draw_types) / sizeof(Direction); const Direction particle_draw_type_default_direction = DIRECTION_BILLBOARD; const ParticleDrawType particle_draw_type_default = PARTICLE_DRAW_TYPE_BILLBOARD; const ParticleBlend particle_blend_draw_types[] = { PARTICLE_BLEND_TYPICAL, PARTICLE_BLEND_ADD, PARTICLE_BLEND_MULTIPLY, }; const size_t particle_blend_draw_types_count = sizeof(particle_blend_draw_types) / sizeof(ParticleBlend); const ParticleBlend particle_blend_draw_default_blend = PARTICLE_BLEND_TYPICAL; const ParticleBlendDraw particle_blend_draw_default = PARTICLE_BLEND_DRAW_TYPICAL; const ParticleBlend particle_blend_mask_types[] = { PARTICLE_BLEND_TYPICAL, PARTICLE_BLEND_ADD, PARTICLE_BLEND_MULTIPLY, }; const size_t particle_blend_mask_types_count = sizeof(particle_blend_mask_types) / sizeof(ParticleBlend); const ParticleBlend particle_blend_mask_default_blend = PARTICLE_BLEND_TYPICAL; const ParticleBlendMask particle_blend_mask_default = PARTICLE_BLEND_MASK_TYPICAL; const Pivot pivot_reverse[] = { PIVOT_BOTTOM_RIGHT, PIVOT_BOTTOM_CENTER, PIVOT_BOTTOM_LEFT, PIVOT_MIDDLE_RIGHT, PIVOT_MIDDLE_CENTER, PIVOT_MIDDLE_LEFT, PIVOT_TOP_RIGHT, PIVOT_TOP_CENTER, PIVOT_TOP_LEFT, }; const char* effect_ext_anim_index_name[] = { "P1", "P2", "P3", "P4", "P5", "P6", }; const char* effect_ext_anim_node_index_name[] = { "None", "Head", "Mouth", "Belly", "Chest", "Left Shoulder", "Left Elbow", "Left Elbow Dup", "Left Hand", "Right Shoulder", "Right Elbow", "Right Elbow Dup", "Right Hand", "Left Thigh", "Left Knee", "Left Toe", "Right Thigh", "Right Knee", "Right Toe", }; const char* effect_type_name[] = { "Normal", "Local", "Chara Parent", "Object Parent", }; const char* emitter_name[] = { "Box", "Cylinder", "Sphere", "Mesh", "Polygon", }; const char* emitter_direction_name[] = { "Billboard", "Billboard (Y Axis)", "X Axis", "Y Axis", "Z Axis", "Effect Rotation", }; const char* emitter_emission_name[] = { "On Timer", "On Start", "On End", }; const char* emitter_emission_direction_name[] = { "None", "Outward", "Inward", }; const char* emitter_timer_name[] = { "By Time", "By Distance", }; const char* key_name[] = { "Constant", "Linear", "Hermite", }; const char* particle_blend_name[] = { "Zero", "Typical", "Add", "Subtract", "Multiply", "Punch Through", }; const char* particle_blend_draw_name[] = { "Typical", "Add", "Multiply", }; const char* particle_blend_mask_name[] = { "Typical", "Add", "Multiply", }; const char* particle_draw_type_name[] = { "Billboard", "Billboard (Y Axis)", "X Axis", "Y Axis", "Z Axis", "Emitter Direction", "Emitter Rotation", "Particle Rotation", "Prev Position", "Prev Position Dup", "Emit Position", }; const char* particle_name[] = { "Quad", "Line", "Locus", "Mesh", }; const char* pivot_name[] = { "Top Left", "Top Center", "Top Right", "Middle Left", "Middle Center", "Middle Right", "Bottom Left", "Bottom Center", "Bottom Right", }; const char* uv_index_type_name[] = { "Fixed", "Initial Random / Fixed", "Random", "Forward", "Reverse", "Initial Random / Forward", "Initial Random / Reverse", "User", }; void axis_angle_from_vectors(vec3& axis, float_t& angle, const vec3& vec1, const vec3& vec2) { axis = vec3::cross(vec1, vec2); angle = vec3::length(axis); if (angle >= 0.000001f) angle = asinf(clamp_def(angle, -1.0f, 1.0f)); else { angle = 0.0f; axis = vec3::cross(vec3(0.0f, 1.0f, 0.0f), vec1); if (vec3::length(axis) < 0.000001f) axis = vec3::cross(vec3(0.0f, 0.0f, 1.0f), vec1); } if (vec3::dot(vec1, vec2) < 0.0f) angle = (float_t)M_PI - angle; } #if !SHARED_GLITTER_BUFFER void CreateBuffer(size_t max_count, bool is_quad, Buffer*& buffer, GLuint& vao, GL::ArrayBuffer& vbo, GL::ElementArrayBuffer& ebo) { free_def(buffer); buffer = force_malloc(max_count); glGenVertexArrays(1, &vao); gl_state_bind_vertex_array(vao, true); static const GLsizei buffer_size = sizeof(Buffer); vbo.Create(buffer_size * max_count); vbo.Bind(true); if (is_quad) { size_t count = max_count / 4 * 5; uint32_t* ebo_data = force_malloc(count); for (size_t i = 0, j = 0, k = count; k; i += 5, j += 4, k -= 5) { ebo_data[i + 0] = (uint32_t)(j + 0); ebo_data[i + 1] = (uint32_t)(j + 1); ebo_data[i + 2] = (uint32_t)(j + 3); ebo_data[i + 3] = (uint32_t)(j + 2); ebo_data[i + 4] = 0xFFFFFFFF; } ebo.Create(sizeof(uint32_t) * count, ebo_data); ebo.Bind(true); free_def(ebo_data); } glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, (void*)offsetof(Buffer, position)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, buffer_size, (void*)offsetof(Buffer, uv)); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, buffer_size, (void*)offsetof(Buffer, color)); gl_state_bind_array_buffer(0); gl_state_bind_vertex_array(0); if (is_quad) gl_state_bind_element_array_buffer(0); } void DeleteBuffer(Buffer*& buffer, GLuint& vao, GL::ArrayBuffer& vbo, GL::ElementArrayBuffer& ebo) { ebo.Destroy(); vbo.Destroy(); if (vao) { glDeleteVertexArrays(1, &vao); vao = 0; } free_def(buffer); } #endif }