NS/main/source/particle/general.h
2015-12-10 18:29:55 +01:00

453 lines
11 KiB
C

// general.h
//
// Copyright 1998 by David K. McAllister.
//
// This file implements the API calls that are not particle actions.
#ifndef general_h
#define general_h
#include "papi.h"
#include "p_vector.h"
#ifdef _WIN32
#pragma warning (disable:4244)
#endif
// A single particle
/*
struct Particle
{
pVector pos;
pVector posB;
pVector size;
pVector vel;
pVector velB; // Used to compute binormal, normal, etc.
pVector color; // Color must be next to alpha so glColor4fv works.
float alpha; // This is both cunning and scary.
float age;
};
// A group of particles - Info and an array of Particles
struct ParticleGroup
{
int p_count; // Number of particles currently existing.
int max_particles; // Max particles allowed in group.
int particles_allocated; // Actual allocated size.
Particle list[1]; // Actually, num_particles in size
inline void Remove(int i)
{
list[i] = list[--p_count];
}
inline bool Add(const pVector &pos, const pVector &posB,
const pVector &size, const pVector &vel, const pVector &color,
const float alpha = 1.0f,
const float age = 0.0f)
{
if(p_count >= max_particles)
return false;
else
{
list[p_count].pos = pos;
list[p_count].posB = posB;
list[p_count].size = size;
list[p_count].vel = vel;
list[p_count].velB = vel; // XXX This should be fixed.
list[p_count].color = color;
list[p_count].alpha = alpha;
list[p_count].age = age;
p_count++;
return true;
}
}
};*/
struct pDomain
{
PDomainEnum type; // PABoxDomain, PASphereDomain, PAConeDomain...
pVector p1, p2; // Box vertices, Sphere center, Cylinder/Cone ends
pVector u, v; // Orthonormal basis vectors for Cylinder/Cone
float radius1; // Outer radius
float radius2; // Inner radius
float radius1Sqr; // Used for fast Within test of spheres,
float radius2Sqr; // and for mag. of u and v vectors for plane.
bool Within(const pVector &) const;
void Generate(pVector &) const;
// This constructor is used when default constructing a
// ParticleAction that has a pDomain.
inline pDomain()
{
}
// Construct a domain in the standard way.
pDomain(PDomainEnum dtype,
float a0=0.0f, float a1=0.0f, float a2=0.0f,
float a3=0.0f, float a4=0.0f, float a5=0.0f,
float a6=0.0f, float a7=0.0f, float a8=0.0f);
};
//////////////////////////////////////////////////////////////////////
// Type codes for all actions
enum PActionEnum
{
PAHeaderID, // The first action in each list.
PAAvoidID, // Avoid entering the domain of space.
PABounceID, // Bounce particles off a domain of space.
PACallActionListID, //
PACopyVertexBID, // Set the secondary position from current position.
PADampingID, // Dampen particle velocities.
PAExplosionID, // An Explosion.
PAFollowID, // Accelerate toward the previous particle in the group.
PAGravitateID, // Accelerate each particle toward each other particle.
PAGravityID, // Acceleration in the given direction.
PAJetID, //
PAKillOldID, //
PAMatchVelocityID, //
PAMoveID, //
PAOrbitLineID, //
PAOrbitPointID, //
PARandomAccelID, //
PARandomDisplaceID, //
PARandomVelocityID, //
PARestoreID, //
PASinkID, //
PASinkVelocityID, //
PASourceID, //
PASpeedLimitID, //
PATargetColorID, //
PATargetSizeID, //
PATargetVelocityID, //
PAVortexID //
};
// This method actually does the particle's action.
#define ExecMethod void Execute(ParticleGroup *pg);
struct ParticleAction
{
static float dt; // This is copied to here from global state.
PActionEnum type; // Type field
};
///////////////////////////////////////////////////////////////////////////
// Data types derived from Action.
struct PAHeader : public ParticleAction
{
int actions_allocated;
int count; // Total actions in the list.
float padding[96]; // This must be the largest action.
ExecMethod
};
struct PAAvoid : public ParticleAction
{
pDomain position; // Avoid region
float look_ahead; // how many time units ahead to look
float magnitude; // what percent of the way to go each time
float epsilon; // add to r^2 for softening
ExecMethod
};
struct PABounce : public ParticleAction
{
pDomain position; // Bounce region
float oneMinusFriction; // Friction tangent to surface
float resilience; // Resilence perpendicular to surface
float cutoffSqr; // cutoff velocity; friction applies iff v > cutoff
ExecMethod
};
struct PACallActionList : public ParticleAction
{
int action_list_num; // The action list number to call
ExecMethod
};
struct PACopyVertexB : public ParticleAction
{
bool copy_pos; // True to copy pos to posB.
bool copy_vel; // True to copy vel to velB.
ExecMethod
};
struct PADamping : public ParticleAction
{
pVector damping; // Damping constant applied to velocity
float vlowSqr; // Low and high cutoff velocities
float vhighSqr;
ExecMethod
};
struct PAExplosion : public ParticleAction
{
pVector center; // The center of the explosion
float velocity; // Of shock wave
float magnitude; // At unit radius
float stdev; // Sharpness or width of shock wave
float age; // How long it's been going on
float epsilon; // Softening parameter
ExecMethod
};
struct PAFollow : public ParticleAction
{
float magnitude; // The grav of each particle
float epsilon; // Softening parameter
float max_radius; // Only influence particles within max_radius
ExecMethod
};
struct PAGravitate : public ParticleAction
{
float magnitude; // The grav of each particle
float epsilon; // Softening parameter
float max_radius; // Only influence particles within max_radius
ExecMethod
};
struct PAGravity : public ParticleAction
{
pVector direction; // Amount to increment velocity
ExecMethod
};
struct PAJet : public ParticleAction
{
pVector center; // Center of the fan
pDomain acc; // Acceleration vector domain
float magnitude; // Scales acceleration
float epsilon; // Softening parameter
float max_radius; // Only influence particles within max_radius
ExecMethod
};
struct PAKillOld : public ParticleAction
{
float age_limit; // Exact age at which to kill particles.
bool kill_less_than; // True to kill particles less than limit.
ExecMethod
};
struct PAMatchVelocity : public ParticleAction
{
float magnitude; // The grav of each particle
float epsilon; // Softening parameter
float max_radius; // Only influence particles within max_radius
ExecMethod
};
struct PAMove : public ParticleAction
{
ExecMethod
};
struct PAOrbitLine : public ParticleAction
{
pVector p, axis; // Endpoints of line to which particles are attracted
float magnitude; // Scales acceleration
float epsilon; // Softening parameter
float max_radius; // Only influence particles within max_radius
ExecMethod
};
struct PAOrbitPoint : public ParticleAction
{
pVector center; // Point to which particles are attracted
float magnitude; // Scales acceleration
float epsilon; // Softening parameter
float max_radius; // Only influence particles within max_radius
ExecMethod
};
struct PARandomAccel : public ParticleAction
{
pDomain gen_acc; // The domain of random accelerations.
ExecMethod
};
struct PARandomDisplace : public ParticleAction
{
pDomain gen_disp; // The domain of random displacements.
ExecMethod
};
struct PARandomVelocity : public ParticleAction
{
pDomain gen_vel; // The domain of random velocities.
ExecMethod
};
struct PARestore : public ParticleAction
{
float time_left; // Time remaining until they should be in position.
ExecMethod
};
struct PASink : public ParticleAction
{
bool kill_inside; // True to dispose of particles *inside* domain
pDomain position; // Disposal region
ExecMethod
};
struct PASinkVelocity : public ParticleAction
{
bool kill_inside; // True to dispose of particles with vel *inside* domain
pDomain velocity; // Disposal region
ExecMethod
};
struct PASpeedLimit : public ParticleAction
{
float min_speed; // Clamp speed to this minimum.
float max_speed; // Clamp speed to this maximum.
ExecMethod
};
struct PASource : public ParticleAction
{
pDomain position; // Choose a position in this domain.
pDomain positionB; // Choose a positionB in this domain.
pDomain size; // Choose a size in this domain.
pDomain velocity; // Choose a velocity in this domain.
pDomain color; // Choose a color in this domain.
float alpha; // Alpha of all generated particles
float particle_rate; // Particles to generate per unit time
float age; // Initial age of the particles
float age_sigma; // St. dev. of initial age of the particles
bool vertexB_tracks; // True to get positionB from position.
ExecMethod
};
struct PATargetColor : public ParticleAction
{
pVector color; // Color to shift towards
float alpha; // Alpha value to shift towards
float scale; // Amount to shift by (1 == all the way)
ExecMethod
};
struct PATargetSize : public ParticleAction
{
pVector size; // Size to shift towards
pVector scale; // Amount to shift by per frame (1 == all the way)
ExecMethod
};
struct PATargetVelocity : public ParticleAction
{
pVector velocity; // Velocity to shift towards
float scale; // Amount to shift by (1 == all the way)
ExecMethod
};
struct PAVortex : public ParticleAction
{
pVector center; // Center of vortex
pVector axis; // Axis around which vortex is applied
float magnitude; // Scale for rotation around axis
float epsilon; // Softening parameter
float max_radius; // Only influence particles within max_radius
ExecMethod
};
// Global state vector
struct _ParticleState
{
float dt;
bool in_call_list;
bool in_new_list;
bool vertexB_tracks;
int group_id;
int list_id;
ParticleGroup *pgrp;
PAHeader *pact;
int tid; // Only used in the MP case, but always define it.
// These are static because all threads access the same groups.
// All accesses to these should be locked.
static ParticleGroup **group_list;
static PAHeader **alist_list;
static int group_count;
static int alist_count;
pDomain Size;
pDomain Vel;
pDomain VertexB;
pDomain Color;
float Alpha;
float Age;
float AgeSigma;
_ParticleState();
// Return an index into the list of particle groups where
// p_group_count groups can be added.
int GenerateGroups(int p_group_count);
int GenerateLists(int alist_count);
ParticleGroup *GetGroupPtr(int p_group_num);
PAHeader *GetListPtr(int action_list_num);
};
#ifdef PARTICLE_MP
// All entry points call this to get their particle state.
inline _ParticleState &_GetPState()
{
// Returns a reference to the appropriate particle state.
extern _ParticleState &_GetPStateWithTID();
return _GetPStateWithTID();
}
#else
// All entry points call this to get their particle state.
// For the non-MP case this is practically a no-op.
inline _ParticleState &_GetPState()
{
// This is the global state.
extern _ParticleState __ps;
return __ps;
}
#endif
// Just a silly little function.
static inline float fsqr(float f) { return f * f; }
#endif