singe/src/particles.h
2026-09-07 01:28:53 -05:00

122 lines
5.8 KiB
C

/*
*
* Singe 3
* Copyright (C) 2006-2026 Scott Duensing <scott@kangaroopunch.com>
*
* This program is free software; 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 (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
// Singe - Particles: emitters that spawn, move and age particles for the 2D overlay and the 3D scene.
#ifndef PARTICLES_H
#define PARTICLES_H
#include <stdbool.h>
#include <stdint.h>
#include <SDL3/SDL.h>
#include "math3d.h"
#define PARTICLES_QUEUE_MAX 256 // 2D emitters that may be queued for drawing in one frame
typedef enum ParticleBlendE {
PARTICLE_ALPHA = 0, // Normal alpha blending
PARTICLE_ADD = 1 // Additive: light on light
} ParticleBlendE;
typedef enum ParticleLayerE {
PARTICLE_OVER = 0, // 2D: drawn above the overlay
PARTICLE_UNDER = 1 // 2D: drawn beneath the overlay, above the video and the scene
} ParticleLayerE;
typedef enum ParticleCollideE {
COLLIDE_NONE = 0,
COLLIDE_FLOOR = 1, // A horizontal plane at a given height
COLLIDE_SCENE = 2 // The physics world, by ray casts (3D only, capped per frame)
} ParticleCollideE;
// One particle, as handed to a renderer: world or overlay position, size, rotation, tint and frame.
typedef struct ParticleViewT {
Vec3T position;
float size;
float angle; // Degrees
float colour[4]; // 0..1
int32_t frame;
} ParticleViewT;
// Renderers ask an emitter for its live particles; the texture per frame is theirs to keep.
typedef struct EmitterViewT {
int32_t id;
int32_t node; // -1 for a 2D emitter
ParticleBlendE blend;
ParticleLayerE layer;
int32_t frameCount;
SDL_Surface **frames; // frameCount surfaces (the built-in disc when no sprite is set)
uint32_t textureVersion; // Bumped whenever the frames change
int32_t count;
ParticleViewT *particles; // count entries, valid until the next update
bool lit; // 3D: shaded by the scene's lights
float softness; // 3D: distance over which a particle fades where it meets geometry; 0 for none
int32_t trailLength; // Points kept behind each particle; 0 for no trails
float trailWidth; // World or overlay units
const float *trailPoints; // Per particle, trailLength points of x, y, z, oldest first
const int32_t *trailCounts; // Per particle, how many of those are valid
Vec3T trailOffset; // Added to trail points (a local emitter's origin)
} EmitterViewT;
void particlesClearQueue2D(void);
void particlesInit(void);
void particlesQueue2D(int32_t emitter); // Draw this emitter this frame
int32_t particlesQueued2D(ParticleLayerE layer, int32_t *emitters, int32_t max);
void particlesQuit(void);
void particlesUpdate(bool advance);
int32_t particlesView3D(EmitterViewT *views, int32_t max); // Every 3D emitter with live particles, up to max; returns how many
bool particlesViewEmitter(int32_t emitter, EmitterViewT *view);
void emitterBurst(int32_t emitter, int32_t count);
void emitterClear(int32_t emitter);
void emitterDelete(int32_t emitter);
int32_t emitterGetCount(int32_t emitter);
bool emitterIs3D(int32_t emitter);
bool emitterIsActive(int32_t emitter);
int32_t emitterNew(int32_t node);
void emitterSetBlend(int32_t emitter, ParticleBlendE blend);
void emitterSetCollide(int32_t emitter, ParticleCollideE mode, float bounce, float friction, float floor);
void emitterSetColor(int32_t emitter, const float *start, const float *finish);
void emitterSetDirection(int32_t emitter, Vec3T direction);
void emitterSetDrag(int32_t emitter, float perSecond);
void emitterSetFrames(int32_t emitter, int32_t first, int32_t last);
void emitterSetGravity(int32_t emitter, Vec3T acceleration);
void emitterSetLayer(int32_t emitter, ParticleLayerE layer);
void emitterSetLife(int32_t emitter, float minSeconds, float maxSeconds);
void emitterSetLit(int32_t emitter, bool lit);
void emitterSetLocal(int32_t emitter, bool local);
void emitterSetMax(int32_t emitter, int32_t count);
void emitterSetPosition(int32_t emitter, Vec3T position);
void emitterSetRadius(int32_t emitter, float radius);
void emitterSetRate(int32_t emitter, float perSecond);
void emitterSetSize(int32_t emitter, float start, float finish, float variation);
void emitterSetSoftness(int32_t emitter, float distance);
void emitterSetSpeed(int32_t emitter, float min, float max);
void emitterSetSpin(int32_t emitter, float min, float max);
void emitterSetSpread(int32_t emitter, float degrees);
void emitterSetTexture(int32_t emitter, SDL_Surface **frames, int32_t frameCount); // Copies the surfaces; NULL restores the disc
void emitterSetTrail(int32_t emitter, int32_t length, float width);
void emitterStart(int32_t emitter);
void emitterStop(int32_t emitter);
bool emitterValid(int32_t emitter);
#endif