xolatilization/xarticle.h

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]);
}
}