// 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