/// _ _ _ /// __ ____ _ _ __| |_(_) ___| | ___ /// \ \/ / _` | '__| __| |/ __| |/ _ \ /// > < (_| | | | |_| | (__| | __/ /// /_/\_\__,_|_| \__|_|\___|_|\___| /// /// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic /// /// xolatile@chud.cyou - xarticle - Forgiving, kind and nice general static 3D particle system. /// /// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU /// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish... /// /// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied /// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License /// for more details, if you dare, it is a lot of text that nobody wants to read... typedef struct { natural count; natural limit; natural * sprite; real * life; natural * colour_in; natural * colour_out; vector_3 * * position; vector_3 * * target; vector_3 * * speed; } particle_structure; static particle_structure * particle_initialize (natural limit) { particle_structure * particle = allocate (sizeof (* particle)); particle->limit = limit; particle->sprite = allocate (limit * sizeof (* particle->sprite)); particle->life = allocate (limit * sizeof (* particle->life)); particle->colour_in = allocate (limit * sizeof (* particle->colour_in)); particle->colour_out = allocate (limit * sizeof (* particle->colour_out)); particle->position = allocate (limit * sizeof (* particle->position)); particle->target = allocate (limit * sizeof (* particle->target)); particle->speed = allocate (limit * sizeof (* particle->speed)); for (natural index = 0; index < limit; ++index) { particle->life [index] = 0.0f; particle->position [index] = allocate (sizeof (* * particle->position)); particle->target [index] = allocate (sizeof (* * particle->target)); particle->speed [index] = allocate (sizeof (* * particle->speed)); vector_3_nullify (particle->position [index]); vector_3_nullify (particle->target [index]); vector_3_nullify (particle->speed [index]); } return (particle); } static particle_structure * particle_deinitialize (particle_structure * particle) { for (natural index = 0; index < particle->count; ++index) { particle->position [index] = deallocate (particle->position [index]); particle->target [index] = deallocate (particle->target [index]); particle->speed [index] = deallocate (particle->speed [index]); } particle->sprite = deallocate (particle->sprite); particle->life = deallocate (particle->life); particle->colour_in = deallocate (particle->colour_in); particle->colour_out = deallocate (particle->colour_out); particle->position = deallocate (particle->position); particle->target = deallocate (particle->target); particle->speed = deallocate (particle->speed); return (deallocate (particle)); } static procedure particle_append (particle_structure * particle, natural sprite, real life, natural colour_in, natural colour_out, vector_3 * position, vector_3 * target, vector_3 * speed) { if (particle->count + 1 >= particle->limit) return; ++particle->count; natural current = particle->count - 1; particle->sprite [current] = sprite; particle->life [current] = life; particle->colour_in [current] = colour_in; particle->colour_out [current] = colour_out; vector_3_copy (particle->position [current], position); vector_3_copy (particle->target [current], target); vector_3_copy (particle->speed [current], speed); } static procedure particle_switch (particle_structure * particle, natural this, natural with) { exchange_natural (& particle->sprite [this], & particle->sprite [with]); exchange_real (& particle->life [this], & particle->life [with]); exchange_natural (& particle->colour_in [this], & particle->colour_in [with]); exchange_natural (& particle->colour_out [this], & particle->colour_out [with]); vector_3_exchange ( particle->position [this], particle->position [with]); vector_3_exchange ( particle->target [this], particle->target [with]); vector_3_exchange ( particle->speed [this], particle->speed [with]); } static procedure particle_remove (particle_structure * particle, natural index) { if (index >= particle->count) return; particle_switch (particle, index, particle->count - 1); --particle->count; } static procedure particle_effect_splash (particle_structure * particle, natural sprite, real life, natural colour_in, natural colour_out, vector_3 * position, natural ray_count, real ray_force, real ray_error) { for (natural ray = 0; ray < ray_count; ++ray) { vector_3 target = { //~position->x + random_real (- ray_force, + ray_force), //~position->y + random_real (- ray_force, + ray_force), //~position->z + random_real (- ray_force, + ray_force) + random_real (- ray_error, + ray_error) //~random_real (- ray_force, + ray_force), //~random_real (- ray_force, + ray_force), //~random_real (- ray_force, + ray_force) 0.0f, 0.0f, 0.0f }; vector_3 speed = { random_real (- ray_force, + ray_force), random_real (- ray_force, + ray_force), random_real (- ray_force, + ray_force) }; life += random_real (- 1.0f, + 1.0f); particle_append (particle, sprite, life, colour_in, colour_out, position, & target, & speed); } } static procedure particle_effect_evaporate (particle_structure * particle, natural sprite, real life, natural colour_in, natural colour_out, vector_3 * position, natural ray_count, real ray_force, real ray_error) { for (natural ray = 0; ray < ray_count; ++ray) { vector_3 target = { random_real (0.0f, + ray_force / 6.0f), random_real (0.0f, + ray_force / 1.0f), random_real (0.0f, + ray_force / 6.0f), }; vector_3 speed = { random_real (- ray_force, + ray_force), random_real (- ray_force, + ray_force), random_real (- ray_force, + ray_force) }; life += random_real (- 1.0f, + 1.0f); particle_append (particle, sprite, life, colour_in, colour_out, position, & target, & speed); } } static procedure particle_synchronize (particle_structure * particle, natural framerate) { for (natural index = 0; index < particle->count; ++index) { particle->life [index] -= 1.0f / (real) framerate; if (particle->life [index] < 0.0f) { particle_remove (particle, index); } vector_3_add (particle->position [index], particle->speed [index]); vector_3_add (particle->speed [index], particle->target [index]); //~vector_3_add (particle->position [index], particle->target [index]); } }