171 lines
6.9 KiB
C
171 lines
6.9 KiB
C
/// _ _ _
|
|
/// __ ____ _ _ __| |_(_) ___| | ___
|
|
/// \ \/ / _` | '__| __| |/ __| |/ _ \
|
|
/// > < (_| | | | |_| | (__| | __/
|
|
/// /_/\_\__,_|_| \__|_|\___|_|\___|
|
|
///
|
|
/// 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]);
|
|
}
|
|
}
|