mirror of
https://github.com/ENSL/NS.git
synced 2025-02-18 18:12:06 +00:00
- Added Dave McAllister's particle system code (not licensed, but so old and not found online so I think it's OK)
This commit is contained in:
parent
9ededaf0b5
commit
b16ad0f3f3
18 changed files with 6671 additions and 0 deletions
248
main/source/particles/HLRender.cpp
Normal file
248
main/source/particles/HLRender.cpp
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
// This file implements the API calls that draw particle groups in Half-life
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// This is for something in gl.h.
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#include <GL/gl.h>
|
||||||
|
#include "common/triangleapi.h"
|
||||||
|
#include "cl_dll/wrect.h"
|
||||||
|
#include "cl_dll/cl_dll.h"
|
||||||
|
#include "common/renderingconst.h"
|
||||||
|
#include "particles/papi.h"
|
||||||
|
|
||||||
|
// XXX #include <iostream.h>
|
||||||
|
|
||||||
|
// Draw as a splat texture on a quad.
|
||||||
|
void DrawGroupTriSplat(const pVector &view, const pVector &up,
|
||||||
|
float size_scale, bool draw_tex,
|
||||||
|
bool const_size, bool const_color)
|
||||||
|
{
|
||||||
|
int cnt = pGetGroupCount();
|
||||||
|
|
||||||
|
if(cnt < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pVector *ppos = new pVector[cnt];
|
||||||
|
float *color = const_color ? NULL : new float[cnt * 4];
|
||||||
|
pVector *size = const_size ? NULL : new pVector[cnt];
|
||||||
|
|
||||||
|
pGetParticles(0, cnt, (float *)ppos, color, NULL, (float *)size);
|
||||||
|
|
||||||
|
// Compute the vectors from the particle to the corners of its tri.
|
||||||
|
// 2
|
||||||
|
// |\ The particle is at the center of the x.
|
||||||
|
// |-\ V0, V1, and V2 go from there to the vertices.
|
||||||
|
// |x|\ The texcoords are (0,0), (2,0), and (0,2) respectively.
|
||||||
|
// 0-+-1 We clamp the texture so the rest is transparent.
|
||||||
|
|
||||||
|
pVector right = view ^ up;
|
||||||
|
right.normalize();
|
||||||
|
pVector nup = right ^ view;
|
||||||
|
right *= size_scale;
|
||||||
|
nup *= size_scale;
|
||||||
|
|
||||||
|
pVector V0 = -(right + nup);
|
||||||
|
pVector V1 = V0 + right * 4;
|
||||||
|
pVector V2 = V0 + nup*4 + right*2;
|
||||||
|
|
||||||
|
//cerr << "x " << view.x << " " << view.y << " " << view.z << endl;
|
||||||
|
//cerr << "x " << nup.x << " " << nup.y << " " << nup.z << endl;
|
||||||
|
//cerr << "x " << right.x << " " << right.y << " " << right.z << endl;
|
||||||
|
//cerr << "x " << V0.x << " " << V0.y << " " << V0.z << endl;
|
||||||
|
|
||||||
|
//glBegin(GL_TRIANGLES);
|
||||||
|
gEngfuncs.pTriAPI->Begin( TRI_TRIANGLES );
|
||||||
|
//gEngfuncs.pTriAPI->RenderMode( kRenderTransAlpha );
|
||||||
|
|
||||||
|
for(int i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
pVector &p = ppos[i];
|
||||||
|
|
||||||
|
float* theCurrentColor = &color[i*4];
|
||||||
|
if(!const_color)
|
||||||
|
{
|
||||||
|
//glColor4fv((GLfloat *)&color[i*4]);
|
||||||
|
gEngfuncs.pTriAPI->Color4f(theCurrentColor[0], theCurrentColor[1], theCurrentColor[2], theCurrentColor[3]);
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// gEngfuncs.pTriAPI->Color4f(1.0f, 1.0f, 1.0f, .5f);
|
||||||
|
//}
|
||||||
|
|
||||||
|
pVector sV0 = V0;
|
||||||
|
pVector sV1 = V1;
|
||||||
|
pVector sV2 = V2;
|
||||||
|
|
||||||
|
if(!const_size)
|
||||||
|
{
|
||||||
|
sV0 *= size[i].x;
|
||||||
|
sV1 *= size[i].x;
|
||||||
|
sV2 *= size[i].x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(draw_tex) glTexCoord2f(0,0);
|
||||||
|
if(draw_tex) gEngfuncs.pTriAPI->TexCoord2f(0,0);
|
||||||
|
pVector ver = p + sV0;
|
||||||
|
//glVertex3fv((GLfloat *)&ver);
|
||||||
|
gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
|
||||||
|
|
||||||
|
//if(draw_tex) glTexCoord2f(2,0);
|
||||||
|
if(draw_tex) gEngfuncs.pTriAPI->TexCoord2f(1,0);
|
||||||
|
ver = p + sV1;
|
||||||
|
//glVertex3fv((GLfloat *)&ver);
|
||||||
|
gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
|
||||||
|
|
||||||
|
//if(draw_tex) glTexCoord2f(0,2);
|
||||||
|
if(draw_tex) gEngfuncs.pTriAPI->TexCoord2f(.5,1);
|
||||||
|
ver = p + sV2;
|
||||||
|
//glVertex3fv((GLfloat *)&ver);
|
||||||
|
gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
|
||||||
|
}
|
||||||
|
|
||||||
|
//glEnd();
|
||||||
|
gEngfuncs.pTriAPI->End();
|
||||||
|
|
||||||
|
delete [] ppos;
|
||||||
|
if(color) delete [] color;
|
||||||
|
if(size) delete [] size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Emit OpenGL calls to draw the particles. These are drawn with
|
||||||
|
// whatever primitive type the user specified(GL_POINTS, for
|
||||||
|
// example). The color and radius are set per primitive, by default.
|
||||||
|
// For GL_LINES, the other vertex of the line is the velocity vector.
|
||||||
|
// XXX const_size is ignored.
|
||||||
|
//PARTICLEDLL_API void pDrawGroupp(int primitive, bool const_size, bool const_color)
|
||||||
|
//{
|
||||||
|
// _ParticleState &_ps = _GetPState();
|
||||||
|
//
|
||||||
|
// // Get a pointer to the particles in gp memory
|
||||||
|
// ParticleGroup *pg = _ps.pgrp;
|
||||||
|
//
|
||||||
|
// if(pg == NULL)
|
||||||
|
// return; // ERROR
|
||||||
|
//
|
||||||
|
// if(pg->p_count < 1)
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// if(primitive == GL_POINTS)
|
||||||
|
// {
|
||||||
|
// glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||||
|
// glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
// if(!const_color)
|
||||||
|
// {
|
||||||
|
// glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
// glColorPointer(4, GL_FLOAT, sizeof(Particle), &pg->list[0].color);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// glVertexPointer(3, GL_FLOAT, sizeof(Particle), &pg->list[0].pos);
|
||||||
|
// glDrawArrays((GLenum)primitive, 0, pg->p_count);
|
||||||
|
// glPopClientAttrib();
|
||||||
|
// // XXX For E&S
|
||||||
|
// glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // Assume GL_LINES
|
||||||
|
// glBegin((GLenum)primitive);
|
||||||
|
//
|
||||||
|
// if(!const_color)
|
||||||
|
// {
|
||||||
|
// for(int i = 0; i < pg->p_count; i++)
|
||||||
|
// {
|
||||||
|
// Particle &m = pg->list[i];
|
||||||
|
//
|
||||||
|
// // Warning: this depends on alpha following color in the Particle struct.
|
||||||
|
// glColor4fv((GLfloat *)&m.color);
|
||||||
|
// glVertex3fv((GLfloat *)&m.pos);
|
||||||
|
//
|
||||||
|
// // For lines, make a tail with the velocity vector's direction and
|
||||||
|
// // a length of radius.
|
||||||
|
// pVector tail = m.pos - m.vel;
|
||||||
|
// glVertex3fv((GLfloat *)&tail);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// for(int i = 0; i < pg->p_count; i++)
|
||||||
|
// {
|
||||||
|
// Particle &m = pg->list[i];
|
||||||
|
// glVertex3fv((GLfloat *)&m.pos);
|
||||||
|
//
|
||||||
|
// // For lines, make a tail with the velocity vector's direction and
|
||||||
|
// // a length of radius.
|
||||||
|
// pVector tail = m.pos - m.vel;
|
||||||
|
// glVertex3fv((GLfloat *)&tail);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// glEnd();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//PARTICLEDLL_API void pDrawGroupl(int dlist, bool const_size, bool const_color, bool const_rotation)
|
||||||
|
//{
|
||||||
|
// _ParticleState &_ps = _GetPState();
|
||||||
|
//
|
||||||
|
// // Get a pointer to the particles in gp memory
|
||||||
|
// ParticleGroup *pg = _ps.pgrp;
|
||||||
|
// if(pg == NULL)
|
||||||
|
// return; // ERROR
|
||||||
|
//
|
||||||
|
// if(pg->p_count < 1)
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// //if(const_color)
|
||||||
|
// // glColor4fv((GLfloat *)&pg->list[0].color);
|
||||||
|
//
|
||||||
|
// for(int i = 0; i < pg->p_count; i++)
|
||||||
|
// {
|
||||||
|
// Particle &m = pg->list[i];
|
||||||
|
//
|
||||||
|
// glPushMatrix();
|
||||||
|
// glTranslatef(m.pos.x, m.pos.y, m.pos.z);
|
||||||
|
//
|
||||||
|
// if(!const_size)
|
||||||
|
// glScalef(m.size.x, m.size.y, m.size.z);
|
||||||
|
// else
|
||||||
|
// glScalef(pg->list[i].size.x, pg->list[i].size.y, pg->list[i].size.z);
|
||||||
|
//
|
||||||
|
// // Expensive! A sqrt, cross prod and acos. Yow.
|
||||||
|
// if(!const_rotation)
|
||||||
|
// {
|
||||||
|
// pVector vN(m.vel);
|
||||||
|
// vN.normalize();
|
||||||
|
// pVector voN(m.velB);
|
||||||
|
// voN.normalize();
|
||||||
|
//
|
||||||
|
// pVector biN;
|
||||||
|
// if(voN.x == vN.x && voN.y == vN.y && voN.z == vN.z)
|
||||||
|
// biN = pVector(0, 1, 0);
|
||||||
|
// else
|
||||||
|
// biN = vN ^ voN;
|
||||||
|
// biN.normalize();
|
||||||
|
//
|
||||||
|
// pVector N(vN ^ biN);
|
||||||
|
//
|
||||||
|
// double M[16];
|
||||||
|
// M[0] = vN.x; M[4] = biN.x; M[8] = N.x; M[12] = 0;
|
||||||
|
// M[1] = vN.y; M[5] = biN.y; M[9] = N.y; M[13] = 0;
|
||||||
|
// M[2] = vN.z; M[6] = biN.z; M[10] = N.z; M[14] = 0;
|
||||||
|
// M[3] = 0; M[7] = 0; M[11] = 0; M[15] = 1;
|
||||||
|
// glMultMatrixd(M);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Warning: this depends on alpha following color in the Particle struct.
|
||||||
|
// if(!const_color)
|
||||||
|
// glColor4fv((GLfloat *)&m.color);
|
||||||
|
//
|
||||||
|
// glCallList(dlist);
|
||||||
|
//
|
||||||
|
// glPopMatrix();
|
||||||
|
// }
|
||||||
|
//}
|
29
main/source/particles/Overview.txt
Normal file
29
main/source/particles/Overview.txt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
Particle system goals
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Versatility
|
||||||
|
Not dependent on Half-life, OpenGL or any particular output device or API
|
||||||
|
|
||||||
|
Collision detection with arbitrary areas
|
||||||
|
This would be nice but isn't necessarily needed
|
||||||
|
|
||||||
|
Arbitrary updating of particle source
|
||||||
|
|
||||||
|
Ability to hook into Worldcraft or be dynamically generated
|
||||||
|
As an entity
|
||||||
|
|
||||||
|
Ability to have multiple particle systems at once, all with different parameters
|
||||||
|
|
||||||
|
Allow static and near-static systems
|
||||||
|
Volumetric light, haze
|
||||||
|
|
||||||
|
Allow custom behavior on collision (less important)
|
||||||
|
Including altering particle lifetime, draw mode or creation of new particles inheriting characteristics with some randomly alteration
|
||||||
|
Allows rain that spatters on hit, waterfall that mists
|
||||||
|
|
||||||
|
|
||||||
|
Suggests handle/manager based system
|
||||||
|
Suggests extendable classes for drawing, updating and iterating through systems
|
||||||
|
Allow creating of templates which can be named and then later created
|
||||||
|
|
||||||
|
|
2065
main/source/particles/PS Docs.htm
Normal file
2065
main/source/particles/PS Docs.htm
Normal file
File diff suppressed because it is too large
Load diff
4
main/source/particles/Readme.txt
Normal file
4
main/source/particles/Readme.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
For SGI we make a version of the library that's made for
|
||||||
|
multiprocessing in this directory and a version that's made for single
|
||||||
|
processing in the SP directory. Typing make in this directory will make both.
|
||||||
|
|
391
main/source/particles/action_api.cpp
Normal file
391
main/source/particles/action_api.cpp
Normal file
|
@ -0,0 +1,391 @@
|
||||||
|
// action_api.cpp
|
||||||
|
//
|
||||||
|
// Copyright 1997-1998 by David K. McAllister
|
||||||
|
//
|
||||||
|
// This file implements the action API calls by creating
|
||||||
|
// action class instances, which are either executed or
|
||||||
|
// added to an action list.
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
#include "particles/papi.h"
|
||||||
|
|
||||||
|
extern void _pAddActionToList(ParticleAction *S, int size);
|
||||||
|
extern void _pCallActionList(ParticleAction *pa, int num_actions,
|
||||||
|
ParticleGroup *pg);
|
||||||
|
|
||||||
|
// Do not call this function.
|
||||||
|
void _pSendAction(ParticleAction *S, PActionEnum type, int size)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
S->type = type;
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
{
|
||||||
|
_pAddActionToList(S, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Immediate mode. Execute it.
|
||||||
|
// This is a hack to give them local access to dt.
|
||||||
|
S->dt = _ps.dt;
|
||||||
|
_pCallActionList(S, 1, _ps.pgrp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pAvoid(float magnitude, float epsilon, float look_ahead,
|
||||||
|
PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
PAAvoid S;
|
||||||
|
|
||||||
|
S.position = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.look_ahead = look_ahead;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAAvoidID, sizeof(PAAvoid));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pBounce(float friction, float resilience, float cutoff,
|
||||||
|
PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
PABounce S;
|
||||||
|
|
||||||
|
S.position = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
S.oneMinusFriction = 1.0f - friction;
|
||||||
|
S.resilience = resilience;
|
||||||
|
S.cutoffSqr = fsqr(cutoff);
|
||||||
|
|
||||||
|
_pSendAction(&S, PABounceID, sizeof(PABounce));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pCopyVertexB(bool copy_pos, bool copy_vel)
|
||||||
|
{
|
||||||
|
PACopyVertexB S;
|
||||||
|
|
||||||
|
S.copy_pos = copy_pos;
|
||||||
|
S.copy_vel = copy_vel;
|
||||||
|
|
||||||
|
_pSendAction(&S, PACopyVertexBID, sizeof(PACopyVertexB));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDamping(float damping_x, float damping_y, float damping_z,
|
||||||
|
float vlow, float vhigh)
|
||||||
|
{
|
||||||
|
PADamping S;
|
||||||
|
|
||||||
|
S.damping = pVector(damping_x, damping_y, damping_z);
|
||||||
|
S.vlowSqr = fsqr(vlow);
|
||||||
|
S.vhighSqr = fsqr(vhigh);
|
||||||
|
|
||||||
|
_pSendAction(&S, PADampingID, sizeof(PADamping));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pExplosion(float center_x, float center_y, float center_z, float velocity,
|
||||||
|
float magnitude, float stdev, float epsilon, float age)
|
||||||
|
{
|
||||||
|
PAExplosion S;
|
||||||
|
|
||||||
|
S.center = pVector(center_x, center_y, center_z);
|
||||||
|
S.velocity = velocity;
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.stdev = stdev;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.age = age;
|
||||||
|
|
||||||
|
if(S.epsilon < 0.0f)
|
||||||
|
S.epsilon = P_EPS;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAExplosionID, sizeof(PAExplosion));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pFollow(float magnitude, float epsilon, float max_radius)
|
||||||
|
{
|
||||||
|
PAFollow S;
|
||||||
|
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.max_radius = max_radius;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAFollowID, sizeof(PAFollow));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pGravitate(float magnitude, float epsilon, float max_radius)
|
||||||
|
{
|
||||||
|
PAGravitate S;
|
||||||
|
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.max_radius = max_radius;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAGravitateID, sizeof(PAGravitate));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pGravity(float dir_x, float dir_y, float dir_z)
|
||||||
|
{
|
||||||
|
PAGravity S;
|
||||||
|
|
||||||
|
S.direction = pVector(dir_x, dir_y, dir_z);
|
||||||
|
|
||||||
|
_pSendAction(&S, PAGravityID, sizeof(PAGravity));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pJet(float center_x, float center_y, float center_z,
|
||||||
|
float magnitude, float epsilon, float max_radius)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
PAJet S;
|
||||||
|
|
||||||
|
S.center = pVector(center_x, center_y, center_z);
|
||||||
|
S.acc = _ps.Vel;
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.max_radius = max_radius;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAJetID, sizeof(PAJet));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pKillOld(float age_limit, bool kill_less_than)
|
||||||
|
{
|
||||||
|
PAKillOld S;
|
||||||
|
|
||||||
|
S.age_limit = age_limit;
|
||||||
|
S.kill_less_than = kill_less_than;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAKillOldID, sizeof(PAKillOld));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pMatchVelocity(float magnitude, float epsilon, float max_radius)
|
||||||
|
{
|
||||||
|
PAMatchVelocity S;
|
||||||
|
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.max_radius = max_radius;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAMatchVelocityID, sizeof(PAMatchVelocity));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pMove()
|
||||||
|
{
|
||||||
|
PAMove S;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAMoveID, sizeof(PAMove));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pOrbitLine(float p_x, float p_y, float p_z,
|
||||||
|
float axis_x, float axis_y, float axis_z,
|
||||||
|
float magnitude, float epsilon, float max_radius)
|
||||||
|
{
|
||||||
|
PAOrbitLine S;
|
||||||
|
|
||||||
|
S.p = pVector(p_x, p_y, p_z);
|
||||||
|
S.axis = pVector(axis_x, axis_y, axis_z);
|
||||||
|
S.axis.normalize();
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.max_radius = max_radius;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAOrbitLineID, sizeof(PAOrbitLine));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pOrbitPoint(float center_x, float center_y, float center_z,
|
||||||
|
float magnitude, float epsilon, float max_radius)
|
||||||
|
{
|
||||||
|
PAOrbitPoint S;
|
||||||
|
|
||||||
|
S.center = pVector(center_x, center_y, center_z);
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.max_radius = max_radius;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAOrbitPointID, sizeof(PAOrbitPoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pRandomAccel(PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
PARandomAccel S;
|
||||||
|
|
||||||
|
S.gen_acc = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
|
||||||
|
_pSendAction(&S, PARandomAccelID, sizeof(PARandomAccel));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pRandomDisplace(PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
PARandomDisplace S;
|
||||||
|
|
||||||
|
S.gen_disp = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
|
||||||
|
_pSendAction(&S, PARandomDisplaceID, sizeof(PARandomDisplace));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pRandomVelocity(PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
PARandomVelocity S;
|
||||||
|
|
||||||
|
S.gen_vel = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
|
||||||
|
_pSendAction(&S, PARandomVelocityID, sizeof(PARandomVelocity));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pRestore(float time_left)
|
||||||
|
{
|
||||||
|
PARestore S;
|
||||||
|
|
||||||
|
S.time_left = time_left;
|
||||||
|
|
||||||
|
_pSendAction(&S, PARestoreID, sizeof(PARestore));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSink(bool kill_inside, PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
PASink S;
|
||||||
|
|
||||||
|
S.kill_inside = kill_inside;
|
||||||
|
S.position = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
|
||||||
|
_pSendAction(&S, PASinkID, sizeof(PASink));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSinkVelocity(bool kill_inside, PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
PASinkVelocity S;
|
||||||
|
|
||||||
|
S.kill_inside = kill_inside;
|
||||||
|
S.velocity = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
|
||||||
|
_pSendAction(&S, PASinkVelocityID, sizeof(PASinkVelocity));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSource(float particle_rate, PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
PASource S;
|
||||||
|
|
||||||
|
S.particle_rate = particle_rate;
|
||||||
|
S.position = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
S.positionB = _ps.VertexB;
|
||||||
|
S.size = _ps.Size;
|
||||||
|
S.velocity = _ps.Vel;
|
||||||
|
S.color = _ps.Color;
|
||||||
|
S.alpha = _ps.Alpha;
|
||||||
|
S.age = _ps.Age;
|
||||||
|
S.age_sigma = _ps.AgeSigma;
|
||||||
|
S.vertexB_tracks = _ps.vertexB_tracks;
|
||||||
|
|
||||||
|
_pSendAction(&S, PASourceID, sizeof(PASource));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSpeedLimit(float min_speed, float max_speed)
|
||||||
|
{
|
||||||
|
PASpeedLimit S;
|
||||||
|
|
||||||
|
S.min_speed = min_speed;
|
||||||
|
S.max_speed = max_speed;
|
||||||
|
|
||||||
|
_pSendAction(&S, PASpeedLimitID, sizeof(PASpeedLimit));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pTargetColor(float color_x, float color_y, float color_z,
|
||||||
|
float alpha, float scale)
|
||||||
|
{
|
||||||
|
PATargetColor S;
|
||||||
|
|
||||||
|
S.color = pVector(color_x, color_y, color_z);
|
||||||
|
S.alpha = alpha;
|
||||||
|
S.scale = scale;
|
||||||
|
|
||||||
|
_pSendAction(&S, PATargetColorID, sizeof(PATargetColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pTargetSize(float size_x, float size_y, float size_z,
|
||||||
|
float scale_x, float scale_y, float scale_z)
|
||||||
|
{
|
||||||
|
PATargetSize S;
|
||||||
|
|
||||||
|
S.size = pVector(size_x, size_y, size_z);
|
||||||
|
S.scale = pVector(scale_x, scale_y, scale_z);
|
||||||
|
|
||||||
|
_pSendAction(&S, PATargetSizeID, sizeof(PATargetSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pTargetVelocity(float vel_x, float vel_y, float vel_z, float scale)
|
||||||
|
{
|
||||||
|
PATargetVelocity S;
|
||||||
|
|
||||||
|
S.velocity = pVector(vel_x, vel_y, vel_z);
|
||||||
|
S.scale = scale;
|
||||||
|
|
||||||
|
_pSendAction(&S, PATargetVelocityID, sizeof(PATargetVelocity));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If in immediate mode, quickly add a vertex.
|
||||||
|
// If building an action list, call pSource.
|
||||||
|
PARTICLEDLL_API void pVertex(float x, float y, float z)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
{
|
||||||
|
pSource(1, PDPoint, x, y, z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Immediate mode. Quickly add the vertex.
|
||||||
|
if(_ps.pgrp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pVector pos(x, y, z);
|
||||||
|
pVector siz, vel, col, posB;
|
||||||
|
if(_ps.vertexB_tracks)
|
||||||
|
posB = pos;
|
||||||
|
else
|
||||||
|
_ps.VertexB.Generate(posB);
|
||||||
|
_ps.Size.Generate(siz);
|
||||||
|
_ps.Vel.Generate(vel);
|
||||||
|
_ps.Color.Generate(col);
|
||||||
|
_ps.pgrp->Add(pos, posB, siz, vel, col, _ps.Alpha, _ps.Age);
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVortex(float center_x, float center_y, float center_z,
|
||||||
|
float axis_x, float axis_y, float axis_z,
|
||||||
|
float magnitude, float epsilon, float max_radius)
|
||||||
|
{
|
||||||
|
PAVortex S;
|
||||||
|
|
||||||
|
S.center = pVector(center_x, center_y, center_z);
|
||||||
|
S.axis = pVector(axis_x, axis_y, axis_z);
|
||||||
|
S.axis.normalize();
|
||||||
|
S.magnitude = magnitude;
|
||||||
|
S.epsilon = epsilon;
|
||||||
|
S.max_radius = max_radius;
|
||||||
|
|
||||||
|
_pSendAction(&S, PAVortexID, sizeof(PAVortex));
|
||||||
|
}
|
1841
main/source/particles/actions.cpp
Normal file
1841
main/source/particles/actions.cpp
Normal file
File diff suppressed because it is too large
Load diff
404
main/source/particles/general.h
Normal file
404
main/source/particles/general.h
Normal file
|
@ -0,0 +1,404 @@
|
||||||
|
// 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"
|
||||||
|
#include "particledefs.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma warning (disable:4244)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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
|
149
main/source/particles/opengl.cpp
Normal file
149
main/source/particles/opengl.cpp
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
// opengl.cpp
|
||||||
|
//
|
||||||
|
// Copyright 1998 by David K. McAllister
|
||||||
|
//
|
||||||
|
// This file implements the API calls that draw particle groups in OpenGL.
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// This is for something in gl.h.
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
// XXX #include <iostream.h>
|
||||||
|
|
||||||
|
// Emit OpenGL calls to draw the particles. These are drawn with
|
||||||
|
// whatever primitive type the user specified(GL_POINTS, for
|
||||||
|
// example). The color and radius are set per primitive, by default.
|
||||||
|
// For GL_LINES, the other vertex of the line is the velocity vector.
|
||||||
|
// XXX const_size is ignored.
|
||||||
|
PARTICLEDLL_API void pDrawGroupp(int primitive, bool const_size, bool const_color)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
// Get a pointer to the particles in gp memory
|
||||||
|
ParticleGroup *pg = _ps.pgrp;
|
||||||
|
|
||||||
|
if(pg == NULL)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
if(pg->p_count < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(primitive == GL_POINTS)
|
||||||
|
{
|
||||||
|
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
if(!const_color)
|
||||||
|
{
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glColorPointer(4, GL_FLOAT, sizeof(Particle), &pg->list[0].color);
|
||||||
|
}
|
||||||
|
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(Particle), &pg->list[0].pos);
|
||||||
|
glDrawArrays((GLenum)primitive, 0, pg->p_count);
|
||||||
|
glPopClientAttrib();
|
||||||
|
// XXX For E&S
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Assume GL_LINES
|
||||||
|
glBegin((GLenum)primitive);
|
||||||
|
|
||||||
|
if(!const_color)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < pg->p_count; i++)
|
||||||
|
{
|
||||||
|
Particle &m = pg->list[i];
|
||||||
|
|
||||||
|
// Warning: this depends on alpha following color in the Particle struct.
|
||||||
|
glColor4fv((GLfloat *)&m.color);
|
||||||
|
glVertex3fv((GLfloat *)&m.pos);
|
||||||
|
|
||||||
|
// For lines, make a tail with the velocity vector's direction and
|
||||||
|
// a length of radius.
|
||||||
|
pVector tail = m.pos - m.vel;
|
||||||
|
glVertex3fv((GLfloat *)&tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i = 0; i < pg->p_count; i++)
|
||||||
|
{
|
||||||
|
Particle &m = pg->list[i];
|
||||||
|
glVertex3fv((GLfloat *)&m.pos);
|
||||||
|
|
||||||
|
// For lines, make a tail with the velocity vector's direction and
|
||||||
|
// a length of radius.
|
||||||
|
pVector tail = m.pos - m.vel;
|
||||||
|
glVertex3fv((GLfloat *)&tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDrawGroupl(int dlist, bool const_size, bool const_color, bool const_rotation)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
// Get a pointer to the particles in gp memory
|
||||||
|
ParticleGroup *pg = _ps.pgrp;
|
||||||
|
if(pg == NULL)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
if(pg->p_count < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//if(const_color)
|
||||||
|
// glColor4fv((GLfloat *)&pg->list[0].color);
|
||||||
|
|
||||||
|
for(int i = 0; i < pg->p_count; i++)
|
||||||
|
{
|
||||||
|
Particle &m = pg->list[i];
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(m.pos.x, m.pos.y, m.pos.z);
|
||||||
|
|
||||||
|
if(!const_size)
|
||||||
|
glScalef(m.size.x, m.size.y, m.size.z);
|
||||||
|
else
|
||||||
|
glScalef(pg->list[i].size.x, pg->list[i].size.y, pg->list[i].size.z);
|
||||||
|
|
||||||
|
// Expensive! A sqrt, cross prod and acos. Yow.
|
||||||
|
if(!const_rotation)
|
||||||
|
{
|
||||||
|
pVector vN(m.vel);
|
||||||
|
vN.normalize();
|
||||||
|
pVector voN(m.velB);
|
||||||
|
voN.normalize();
|
||||||
|
|
||||||
|
pVector biN;
|
||||||
|
if(voN.x == vN.x && voN.y == vN.y && voN.z == vN.z)
|
||||||
|
biN = pVector(0, 1, 0);
|
||||||
|
else
|
||||||
|
biN = vN ^ voN;
|
||||||
|
biN.normalize();
|
||||||
|
|
||||||
|
pVector N(vN ^ biN);
|
||||||
|
|
||||||
|
double M[16];
|
||||||
|
M[0] = vN.x; M[4] = biN.x; M[8] = N.x; M[12] = 0;
|
||||||
|
M[1] = vN.y; M[5] = biN.y; M[9] = N.y; M[13] = 0;
|
||||||
|
M[2] = vN.z; M[6] = biN.z; M[10] = N.z; M[14] = 0;
|
||||||
|
M[3] = 0; M[7] = 0; M[11] = 0; M[15] = 1;
|
||||||
|
glMultMatrixd(M);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning: this depends on alpha following color in the Particle struct.
|
||||||
|
if(!const_color)
|
||||||
|
glColor4fv((GLfloat *)&m.color);
|
||||||
|
|
||||||
|
glCallList(dlist);
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
}
|
141
main/source/particles/p_vector.h
Normal file
141
main/source/particles/p_vector.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
// p_vector.h - yet another vector class.
|
||||||
|
//
|
||||||
|
// Copyright 1997 by Jonathan P. Leech
|
||||||
|
// Modifications Copyright 1997-1999 by David K. McAllister
|
||||||
|
//
|
||||||
|
// A simple 3D float vector class for internal use by the particle systems.
|
||||||
|
|
||||||
|
#ifndef particle_vector_h
|
||||||
|
#define particle_vector_h
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.1415926535897932384626433f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define drand48() (((float) rand())/((float) RAND_MAX))
|
||||||
|
#define srand48(x) srand(x)
|
||||||
|
|
||||||
|
// This is because their stupid compiler thinks it's smart.
|
||||||
|
#define inline __forceinline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class pVector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float x, y, z;
|
||||||
|
|
||||||
|
inline pVector(float ax, float ay, float az) : x(ax), y(ay), z(az)
|
||||||
|
{
|
||||||
|
//x = ax; y = ay; z = az;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector() {}
|
||||||
|
|
||||||
|
inline float length() const
|
||||||
|
{
|
||||||
|
return sqrtf(x*x+y*y+z*z);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float length2() const
|
||||||
|
{
|
||||||
|
return (x*x+y*y+z*z);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float normalize()
|
||||||
|
{
|
||||||
|
float onel = 1.0f / sqrtf(x*x+y*y+z*z);
|
||||||
|
x *= onel;
|
||||||
|
y *= onel;
|
||||||
|
z *= onel;
|
||||||
|
|
||||||
|
return onel;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float operator*(const pVector &a) const
|
||||||
|
{
|
||||||
|
return x*a.x + y*a.y + z*a.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector operator*(const float s) const
|
||||||
|
{
|
||||||
|
return pVector(x*s, y*s, z*s);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector operator/(const float s) const
|
||||||
|
{
|
||||||
|
float invs = 1.0f / s;
|
||||||
|
return pVector(x*invs, y*invs, z*invs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector operator+(const pVector& a) const
|
||||||
|
{
|
||||||
|
return pVector(x+a.x, y+a.y, z+a.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector operator-(const pVector& a) const
|
||||||
|
{
|
||||||
|
return pVector(x-a.x, y-a.y, z-a.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector operator-()
|
||||||
|
{
|
||||||
|
x = -x;
|
||||||
|
y = -y;
|
||||||
|
z = -z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector& operator+=(const pVector& a)
|
||||||
|
{
|
||||||
|
x += a.x;
|
||||||
|
y += a.y;
|
||||||
|
z += a.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector& operator-=(const pVector& a)
|
||||||
|
{
|
||||||
|
x -= a.x;
|
||||||
|
y -= a.y;
|
||||||
|
z -= a.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector& operator*=(const float a)
|
||||||
|
{
|
||||||
|
x *= a;
|
||||||
|
y *= a;
|
||||||
|
z *= a;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector& operator/=(const float a)
|
||||||
|
{
|
||||||
|
float b = 1.0f / a;
|
||||||
|
x *= b;
|
||||||
|
y *= b;
|
||||||
|
z *= b;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector& operator=(const pVector& a)
|
||||||
|
{
|
||||||
|
x = a.x;
|
||||||
|
y = a.y;
|
||||||
|
z = a.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pVector operator^(const pVector& b) const
|
||||||
|
{
|
||||||
|
return pVector(
|
||||||
|
y*b.z-z*b.y,
|
||||||
|
z*b.x-x*b.z,
|
||||||
|
x*b.y-y*b.x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
201
main/source/particles/papi.h
Normal file
201
main/source/particles/papi.h
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
// papi.h
|
||||||
|
//
|
||||||
|
// Copyright 1997-1998 by David K. McAllister
|
||||||
|
// http://www.cs.unc.edu/~davemc/Particle
|
||||||
|
//
|
||||||
|
// Include this file in all applications that use the Particle System API.
|
||||||
|
|
||||||
|
#ifndef _particle_api_h
|
||||||
|
#define _particle_api_h
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// This is the major and minor version number of this release of the API.
|
||||||
|
#define P_VERSION 120
|
||||||
|
|
||||||
|
// added <<< cgc >>>
|
||||||
|
#include <particles/p_vector.h>
|
||||||
|
#include <particles/general.h>
|
||||||
|
#include <particles/particledefs.h>
|
||||||
|
|
||||||
|
// State setting calls
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pColor(float red, float green, float blue, float alpha = 1.0f);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pColorD(float alpha, 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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSize(float size_x, float size_y = 1.0f, float size_z = 1.0f);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSizeD(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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pStartingAge(float age, float sigma = 1.0f);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pTimeStep(float new_dt);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVelocity(float x, float y, float z);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVelocityD(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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVertexB(float x, float y, float z);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVertexBD(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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVertexBTracks(bool track_vertex = true);
|
||||||
|
|
||||||
|
|
||||||
|
// Action List Calls
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pCallActionList(int action_list_num);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDeleteActionLists(int action_list_num, int action_list_count = 1);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pEndActionList();
|
||||||
|
|
||||||
|
PARTICLEDLL_API int pGenActionLists(int action_list_count = 1);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pNewActionList(int action_list_num);
|
||||||
|
|
||||||
|
|
||||||
|
// Particle Group Calls
|
||||||
|
|
||||||
|
PARTICLEDLL_API ParticleGroup* pGetParticleGroupRef(int p_group_num);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pCopyGroup(int p_src_group_num, int index = 0, int copy_count = P_MAXINT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pCurrentGroup(int p_group_num);
|
||||||
|
|
||||||
|
PARTICLEDLL_API ParticleGroup* pGetCurrentGroup(void);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDeleteParticleGroups(int p_group_num, int p_group_count = 1);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDrawGroupl(int dlist, bool const_size = false,
|
||||||
|
bool const_color = false, bool const_rotation = false);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDrawGroupp(int primitive, bool const_size = false,
|
||||||
|
bool const_color = false);
|
||||||
|
|
||||||
|
// Added <<< cgc >>>
|
||||||
|
PARTICLEDLL_API void DrawGroupTriSplat(const pVector &view, const pVector &up, float size_scale = 1.0f, bool draw_tex=false, bool const_size=false, bool const_color=false);
|
||||||
|
// end
|
||||||
|
|
||||||
|
PARTICLEDLL_API int pGenParticleGroups(int p_group_count = 1, int max_particles = 0);
|
||||||
|
|
||||||
|
PARTICLEDLL_API int pGetGroupCount();
|
||||||
|
|
||||||
|
PARTICLEDLL_API int pGetParticles(int index, int count, float *position = NULL, float *color = NULL,
|
||||||
|
float *vel = NULL, float *size = NULL, float *age = NULL);
|
||||||
|
|
||||||
|
PARTICLEDLL_API int pSetMaxParticles(int max_count);
|
||||||
|
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pAvoid(float magnitude, float epsilon, float look_ahead,
|
||||||
|
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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pBounce(float friction, float resilience, float cutoff,
|
||||||
|
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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pCopyVertexB(bool copy_pos = true, bool copy_vel = false);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDamping(float damping_x, float damping_y, float damping_z,
|
||||||
|
float vlow = 0.0f, float vhigh = P_MAXFLOAT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pExplosion(float center_x, float center_y, float center_z, float velocity,
|
||||||
|
float magnitude, float stdev, float epsilon = P_EPS, float age = 0.0f);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pFollow(float magnitude = 1.0f, float epsilon = P_EPS, float max_radius = P_MAXFLOAT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pGravitate(float magnitude = 1.0f, float epsilon = P_EPS, float max_radius = P_MAXFLOAT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pGravity(float dir_x, float dir_y, float dir_z);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pJet(float center_x, float center_y, float center_z, float magnitude = 1.0f,
|
||||||
|
float epsilon = P_EPS, float max_radius = P_MAXFLOAT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pKillOld(float age_limit, bool kill_less_than = false);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pMatchVelocity(float magnitude = 1.0f, float epsilon = P_EPS,
|
||||||
|
float max_radius = P_MAXFLOAT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pMove();
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pOrbitLine(float p_x, float p_y, float p_z,
|
||||||
|
float axis_x, float axis_y, float axis_z, float magnitude = 1.0f,
|
||||||
|
float epsilon = P_EPS, float max_radius = P_MAXFLOAT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pOrbitPoint(float center_x, float center_y, float center_z,
|
||||||
|
float magnitude = 1.0f, float epsilon = P_EPS,
|
||||||
|
float max_radius = P_MAXFLOAT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pRandomAccel(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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pRandomDisplace(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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pRandomVelocity(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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pRestore(float time);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pShade(float color_x, float color_y, float color_z,
|
||||||
|
float alpha, float scale);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSink(bool kill_inside, 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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSinkVelocity(bool kill_inside, 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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSource(float particle_rate, 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);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSpeedLimit(float min_speed, float max_speed = P_MAXFLOAT);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pTargetColor(float color_x, float color_y, float color_z,
|
||||||
|
float alpha, float scale);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pTargetSize(float size_x, float size_y, float size_z,
|
||||||
|
float scale_x = 0.0f, float scale_y = 0.0f, float scale_z = 0.0f);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pTargetVelocity(float vel_x, float vel_y, float vel_z, float scale);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVertex(float x, float y, float z);
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVortex(float center_x, float center_y, float center_z,
|
||||||
|
float axis_x, float axis_y, float axis_z,
|
||||||
|
float magnitude = 1.0f, float epsilon = P_EPS,
|
||||||
|
float max_radius = P_MAXFLOAT);
|
||||||
|
|
||||||
|
#endif
|
111
main/source/particles/particledefs.h
Normal file
111
main/source/particles/particledefs.h
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
// general.h
|
||||||
|
//
|
||||||
|
// Copyright 1998 by David K. McAllister.
|
||||||
|
//
|
||||||
|
// This file implements the API calls that are not particle actions.
|
||||||
|
|
||||||
|
#ifndef particledefs_h
|
||||||
|
#define particledefs_h
|
||||||
|
|
||||||
|
#include "p_vector.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
// removed <<< cgc >>>
|
||||||
|
//#ifdef PARTICLEDLL_EXPORTS
|
||||||
|
//#define PARTICLEDLL_API __declspec(dllexport)
|
||||||
|
//#else
|
||||||
|
//#define PARTICLEDLL_API __declspec(dllimport)
|
||||||
|
//#endif
|
||||||
|
#define PARTICLEDLL_API extern "C"
|
||||||
|
|
||||||
|
// removed <<< cgc >>>
|
||||||
|
//#else
|
||||||
|
//#define PARTICLEDLL_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma warning (disable:4244)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Actually this must be < sqrt(MAXFLOAT) since we store this value squared.
|
||||||
|
#define P_MAXFLOAT 1.0e16f
|
||||||
|
|
||||||
|
#ifdef MAXINT
|
||||||
|
#define P_MAXINT MAXINT
|
||||||
|
#else
|
||||||
|
#define P_MAXINT 0x7fffffff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define P_EPS 1e-3f
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Type codes for domains
|
||||||
|
PARTICLEDLL_API enum PDomainEnum
|
||||||
|
{
|
||||||
|
PDPoint = 0, // Single point
|
||||||
|
PDLine = 1, // Line segment
|
||||||
|
PDTriangle = 2, // Triangle
|
||||||
|
PDPlane = 3, // Arbitrarily-oriented plane
|
||||||
|
PDBox = 4, // Axis-aligned box
|
||||||
|
PDSphere = 5, // Sphere
|
||||||
|
PDCylinder = 6, // Cylinder
|
||||||
|
PDCone = 7, // Cone
|
||||||
|
PDBlob = 8, // Gaussian blob
|
||||||
|
PDDisc = 9, // Arbitrarily-oriented disc
|
||||||
|
PDRectangle = 10 // Rhombus-shaped planar region
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
BIN
main/source/particles/particles.sdf
Normal file
BIN
main/source/particles/particles.sdf
Normal file
Binary file not shown.
20
main/source/particles/particles.sln
Normal file
20
main/source/particles/particles.sln
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual C++ Express 2010
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "particles", "particles.vcxproj", "{5AADD469-7488-4B34-A9FD-01CFAC5972FD}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{5AADD469-7488-4B34-A9FD-01CFAC5972FD}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{5AADD469-7488-4B34-A9FD-01CFAC5972FD}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{5AADD469-7488-4B34-A9FD-01CFAC5972FD}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{5AADD469-7488-4B34-A9FD-01CFAC5972FD}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
BIN
main/source/particles/particles.suo
Normal file
BIN
main/source/particles/particles.suo
Normal file
Binary file not shown.
103
main/source/particles/particles.vcxproj
Normal file
103
main/source/particles/particles.vcxproj
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{5AADD469-7488-4B34-A9FD-01CFAC5972FD}</ProjectGuid>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<Keyword>ManagedCProj</Keyword>
|
||||||
|
<RootNamespace>particles</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<CLRSupport>true</CLRSupport>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<CLRSupport>true</CLRSupport>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;..;</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IncludePath>$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;..;</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>
|
||||||
|
</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>
|
||||||
|
</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Overview.txt" />
|
||||||
|
<None Include="PS Docs.htm">
|
||||||
|
<DeploymentContent>true</DeploymentContent>
|
||||||
|
</None>
|
||||||
|
<None Include="Readme.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="general.h" />
|
||||||
|
<ClInclude Include="papi.h" />
|
||||||
|
<ClInclude Include="particledefs.h" />
|
||||||
|
<ClInclude Include="p_vector.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="actions.cpp" />
|
||||||
|
<ClCompile Include="action_api.cpp" />
|
||||||
|
<ClCompile Include="HLRender.cpp" />
|
||||||
|
<ClCompile Include="opengl.cpp" />
|
||||||
|
<ClCompile Include="system.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
53
main/source/particles/particles.vcxproj.filters
Normal file
53
main/source/particles/particles.vcxproj.filters
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PS Docs.htm" />
|
||||||
|
<None Include="Overview.txt" />
|
||||||
|
<None Include="Readme.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="general.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="p_vector.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="papi.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="particledefs.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="action_api.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="actions.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="HLRender.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="opengl.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="system.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
3
main/source/particles/particles.vcxproj.user
Normal file
3
main/source/particles/particles.vcxproj.user
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
</Project>
|
908
main/source/particles/system.cpp
Normal file
908
main/source/particles/system.cpp
Normal file
|
@ -0,0 +1,908 @@
|
||||||
|
// system.cpp
|
||||||
|
//
|
||||||
|
// Copyright 1998 by David K. McAllister.
|
||||||
|
//
|
||||||
|
// This file implements the API calls that are not particle actions.
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
#include <iostream>
|
||||||
|
// using namespace std;
|
||||||
|
|
||||||
|
// <<< cgc >>> removed DllMain() because I'm linking statically
|
||||||
|
// For Windows DLL.
|
||||||
|
//#ifdef WIN32
|
||||||
|
//BOOL APIENTRY DllMain( HANDLE hModule,
|
||||||
|
// DWORD ul_reason_for_call,
|
||||||
|
// LPVOID lpReserved
|
||||||
|
// )
|
||||||
|
//{
|
||||||
|
// switch (ul_reason_for_call)
|
||||||
|
// {
|
||||||
|
// case DLL_PROCESS_ATTACH:
|
||||||
|
// case DLL_THREAD_ATTACH:
|
||||||
|
// case DLL_THREAD_DETACH:
|
||||||
|
// case DLL_PROCESS_DETACH:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// return TRUE;
|
||||||
|
//}
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
// <<< cgc >>> added this pre-declaration
|
||||||
|
extern void _pSendAction(ParticleAction *S, PActionEnum type, int size);
|
||||||
|
|
||||||
|
float ParticleAction::dt;
|
||||||
|
|
||||||
|
ParticleGroup **_ParticleState::group_list;
|
||||||
|
PAHeader **_ParticleState::alist_list;
|
||||||
|
int _ParticleState::group_count;
|
||||||
|
int _ParticleState::alist_count;
|
||||||
|
|
||||||
|
// This AutoCall struct allows for static initialization of the above shared variables.
|
||||||
|
struct AutoCall
|
||||||
|
{
|
||||||
|
AutoCall();
|
||||||
|
};
|
||||||
|
|
||||||
|
AutoCall::AutoCall()
|
||||||
|
{
|
||||||
|
// The list of groups, etc.
|
||||||
|
_ParticleState::group_list = new ParticleGroup *[16];
|
||||||
|
_ParticleState::group_count = 16;
|
||||||
|
_ParticleState::alist_list = new PAHeader *[16];
|
||||||
|
_ParticleState::alist_count = 16;
|
||||||
|
for(int i=0; i<16; i++)
|
||||||
|
{
|
||||||
|
_ParticleState::group_list[i] = NULL;
|
||||||
|
_ParticleState::alist_list[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PARTICLE_MP
|
||||||
|
// This code is defined if we are compiling the library to be used on
|
||||||
|
// multiple threads. We need to have each API call figure out which
|
||||||
|
// _ParticleState belongs to it. We hash pointers to contexts in
|
||||||
|
// _CtxHash. Whenever a TID is asked for but doesn't exist we create
|
||||||
|
// it.
|
||||||
|
|
||||||
|
#include <mpc.h>
|
||||||
|
|
||||||
|
// XXX This hard limit should get fixed.
|
||||||
|
int _CtxCount = 151;
|
||||||
|
_ParticleState **_CtxHash = NULL;
|
||||||
|
|
||||||
|
inline int _HashTID(int tid)
|
||||||
|
{
|
||||||
|
return ((tid << 13) ^ ((tid >> 11) ^ tid)) % _CtxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a reference to the appropriate particle state.
|
||||||
|
_ParticleState &_GetPStateWithTID()
|
||||||
|
{
|
||||||
|
int tid = mp_my_threadnum();
|
||||||
|
|
||||||
|
int ind = _HashTID(tid);
|
||||||
|
|
||||||
|
// cerr << tid << "->" << ind << endl;
|
||||||
|
|
||||||
|
// Check through the hash table and find it.
|
||||||
|
for(int i=ind; i<_CtxCount; i++)
|
||||||
|
if(_CtxHash[i] && _CtxHash[i]->tid == tid)
|
||||||
|
{
|
||||||
|
//#pragma critical
|
||||||
|
//cerr << tid << " => " << i << endl;
|
||||||
|
|
||||||
|
return *_CtxHash[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<ind; i++)
|
||||||
|
if(_CtxHash[i] && _CtxHash[i]->tid == tid)
|
||||||
|
return *_CtxHash[i];
|
||||||
|
|
||||||
|
// It didn't exist. It's a new context, so create it.
|
||||||
|
_ParticleState *psp = new _ParticleState();
|
||||||
|
psp->tid = tid;
|
||||||
|
|
||||||
|
// Find a place to put it.
|
||||||
|
for(i=ind; i<_CtxCount; i++)
|
||||||
|
if(_CtxHash[i] == NULL)
|
||||||
|
{
|
||||||
|
// #pragma critical
|
||||||
|
// cerr << "Stored " << tid << " at " << i << endl;
|
||||||
|
_CtxHash[i] = psp;
|
||||||
|
return *psp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<ind; i++)
|
||||||
|
if(_CtxHash[i] == NULL)
|
||||||
|
{
|
||||||
|
_CtxHash[i] = psp;
|
||||||
|
return *psp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should never get here. The hash table got full.
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
// To appease warnings.
|
||||||
|
return *_CtxHash[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void _PLock()
|
||||||
|
{
|
||||||
|
// XXX This implementation is specific to the #pragma parallel directives.
|
||||||
|
// cerr << "Getting lock.\n";
|
||||||
|
// mp_setlock();
|
||||||
|
// cerr << "Got lock.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void _PUnLock()
|
||||||
|
{
|
||||||
|
// XXX This implementation is specific to the #pragma parallel directives.
|
||||||
|
// cerr << "Giving lock.\n";
|
||||||
|
// mp_unsetlock();
|
||||||
|
// cerr << "Gave lock.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
// This is the global state.
|
||||||
|
_ParticleState __ps;
|
||||||
|
|
||||||
|
inline void _PLock()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void _PUnLock()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_ParticleState::_ParticleState()
|
||||||
|
{
|
||||||
|
in_call_list = false;
|
||||||
|
in_new_list = false;
|
||||||
|
vertexB_tracks = true;
|
||||||
|
|
||||||
|
dt = 1.0f;
|
||||||
|
|
||||||
|
group_id = -1;
|
||||||
|
list_id = -1;
|
||||||
|
pgrp = NULL;
|
||||||
|
pact = NULL;
|
||||||
|
tid = 0; // This will be filled in above if we're MP.
|
||||||
|
|
||||||
|
Size = pDomain(PDPoint, 1.0f, 1.0f, 1.0f);
|
||||||
|
Vel = pDomain(PDPoint, 0.0f, 0.0f, 0.0f);
|
||||||
|
VertexB = pDomain(PDPoint, 0.0f, 0.0f, 0.0f);
|
||||||
|
Color = pDomain(PDPoint, 1.0f, 1.0f, 1.0f);
|
||||||
|
Alpha = 1.0f;
|
||||||
|
Age = 0.0f;
|
||||||
|
AgeSigma = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleGroup *_ParticleState::GetGroupPtr(int p_group_num)
|
||||||
|
{
|
||||||
|
if(p_group_num < 0)
|
||||||
|
return NULL; // IERROR
|
||||||
|
|
||||||
|
if(p_group_num >= group_count)
|
||||||
|
return NULL; // IERROR
|
||||||
|
|
||||||
|
return group_list[p_group_num];
|
||||||
|
}
|
||||||
|
|
||||||
|
PAHeader *_ParticleState::GetListPtr(int a_list_num)
|
||||||
|
{
|
||||||
|
if(a_list_num < 0)
|
||||||
|
return NULL; // IERROR
|
||||||
|
|
||||||
|
if(a_list_num >= alist_count)
|
||||||
|
return NULL; // IERROR
|
||||||
|
|
||||||
|
return alist_list[a_list_num];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an index into the list of particle groups where
|
||||||
|
// p_group_count groups can be added.
|
||||||
|
int _ParticleState::GenerateGroups(int p_group_count)
|
||||||
|
{
|
||||||
|
int num_empty = 0;
|
||||||
|
int first_empty = -1;
|
||||||
|
|
||||||
|
for(int i=0; i<group_count; i++)
|
||||||
|
{
|
||||||
|
if(group_list[i])
|
||||||
|
{
|
||||||
|
num_empty = 0;
|
||||||
|
first_empty = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(first_empty < 0)
|
||||||
|
first_empty = i;
|
||||||
|
num_empty++;
|
||||||
|
if(num_empty >= p_group_count)
|
||||||
|
return first_empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't find a big enough gap. Reallocate.
|
||||||
|
int new_count = 16 + group_count + p_group_count;
|
||||||
|
ParticleGroup **glist = new ParticleGroup *[new_count];
|
||||||
|
memcpy(glist, group_list, group_count * sizeof(void*));
|
||||||
|
for(int i=group_count; i<new_count; i++)
|
||||||
|
glist[i] = NULL;
|
||||||
|
delete [] group_list;
|
||||||
|
group_list = glist;
|
||||||
|
group_count = new_count;
|
||||||
|
|
||||||
|
return GenerateGroups(p_group_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an index into the list of action lists where
|
||||||
|
// list_count lists can be added.
|
||||||
|
int _ParticleState::GenerateLists(int list_count)
|
||||||
|
{
|
||||||
|
int num_empty = 0;
|
||||||
|
int first_empty = -1;
|
||||||
|
|
||||||
|
for(int i=0; i<alist_count; i++)
|
||||||
|
{
|
||||||
|
if(alist_list[i])
|
||||||
|
{
|
||||||
|
num_empty = 0;
|
||||||
|
first_empty = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(first_empty < 0)
|
||||||
|
first_empty = i;
|
||||||
|
num_empty++;
|
||||||
|
if(num_empty >= list_count)
|
||||||
|
return first_empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't find a big enough gap. Reallocate.
|
||||||
|
int new_count = 16 + alist_count + list_count;
|
||||||
|
PAHeader **new_list = new PAHeader *[new_count];
|
||||||
|
memcpy(new_list, alist_list, alist_count * sizeof(void*));
|
||||||
|
for(int i=list_count; i<new_count; i++)
|
||||||
|
new_list[i] = NULL;
|
||||||
|
delete [] alist_list;
|
||||||
|
alist_list = new_list;
|
||||||
|
alist_count = new_count;
|
||||||
|
|
||||||
|
return GenerateLists(list_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
// Auxiliary calls
|
||||||
|
void _pCallActionList(ParticleAction *apa, int num_actions,
|
||||||
|
ParticleGroup *pg)
|
||||||
|
{
|
||||||
|
// All these require a particle group, so check for it.
|
||||||
|
if(pg == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PAHeader *pa = (PAHeader *)apa;
|
||||||
|
|
||||||
|
// Step through all the actions in the action list.
|
||||||
|
for(int action = 0; action < num_actions; action++, pa++)
|
||||||
|
{
|
||||||
|
switch(pa->type)
|
||||||
|
{
|
||||||
|
case PAAvoidID:
|
||||||
|
((PAAvoid *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PABounceID:
|
||||||
|
((PABounce *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PACallActionListID:
|
||||||
|
((PACallActionList *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PACopyVertexBID:
|
||||||
|
((PACopyVertexB *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PADampingID:
|
||||||
|
((PADamping *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAExplosionID:
|
||||||
|
((PAExplosion *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAFollowID:
|
||||||
|
((PAFollow *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAGravitateID:
|
||||||
|
((PAGravitate *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAGravityID:
|
||||||
|
((PAGravity *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAJetID:
|
||||||
|
((PAJet *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAKillOldID:
|
||||||
|
((PAKillOld *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAMatchVelocityID:
|
||||||
|
((PAMatchVelocity *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAMoveID:
|
||||||
|
((PAMove *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAOrbitLineID:
|
||||||
|
((PAOrbitLine *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAOrbitPointID:
|
||||||
|
((PAOrbitPoint *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PARandomAccelID:
|
||||||
|
((PARandomAccel *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PARandomDisplaceID:
|
||||||
|
((PARandomDisplace *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PARandomVelocityID:
|
||||||
|
((PARandomVelocity *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PARestoreID:
|
||||||
|
((PARestore *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PASinkID:
|
||||||
|
((PASink *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PASinkVelocityID:
|
||||||
|
((PASinkVelocity *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PASourceID:
|
||||||
|
((PASource *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PASpeedLimitID:
|
||||||
|
((PASpeedLimit *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PATargetColorID:
|
||||||
|
((PATargetColor *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PATargetSizeID:
|
||||||
|
((PATargetSize *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PATargetVelocityID:
|
||||||
|
((PATargetVelocity *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
case PAVortexID:
|
||||||
|
((PAVortex *)pa)->Execute(pg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the incoming action to the end of the current action list.
|
||||||
|
void _pAddActionToList(ParticleAction *S, int size)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(!_ps.in_new_list)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
if(_ps.pact == NULL)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
if(_ps.list_id < 0)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
PAHeader *alist = _ps.pact;
|
||||||
|
|
||||||
|
if(alist->actions_allocated <= alist->count)
|
||||||
|
{
|
||||||
|
// Must reallocate.
|
||||||
|
int new_alloc = 16 + alist->actions_allocated;
|
||||||
|
PAHeader *new_alist = new PAHeader[new_alloc];
|
||||||
|
memcpy(new_alist, alist, alist->count * sizeof(PAHeader));
|
||||||
|
|
||||||
|
delete [] alist;
|
||||||
|
_ps.alist_list[_ps.list_id] = _ps.pact = alist = new_alist;
|
||||||
|
|
||||||
|
alist->actions_allocated = new_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add it in.
|
||||||
|
memcpy(&alist[alist->count], S, size);
|
||||||
|
alist->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
// State setting calls
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pColor(float red, float green, float blue, float alpha)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.Alpha = alpha;
|
||||||
|
_ps.Color = pDomain(PDPoint, red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pColorD(float alpha, PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.Alpha = alpha;
|
||||||
|
_ps.Color = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVelocity(float x, float y, float z)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.Vel = pDomain(PDPoint, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVelocityD(PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.Vel = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVertexB(float x, float y, float z)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.VertexB = pDomain(PDPoint, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVertexBD(PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.VertexB = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pVertexBTracks(bool trackVertex)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.vertexB_tracks = trackVertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSize(float size_x, float size_y, float size_z)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.Size = pDomain(PDPoint, size_x, size_y, size_z);
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pSizeD(PDomainEnum dtype,
|
||||||
|
float a0, float a1, float a2,
|
||||||
|
float a3, float a4, float a5,
|
||||||
|
float a6, float a7, float a8)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.Size = pDomain(dtype, a0, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pStartingAge(float age, float sigma)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.Age = age;
|
||||||
|
_ps.AgeSigma = sigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pTimeStep(float newDT)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
_ps.dt = newDT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
// Action List Calls
|
||||||
|
|
||||||
|
PARTICLEDLL_API int pGenActionLists(int action_list_count)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return -1; // ERROR
|
||||||
|
|
||||||
|
_PLock();
|
||||||
|
|
||||||
|
int ind = _ps.GenerateLists(action_list_count);
|
||||||
|
|
||||||
|
for(int i=ind; i<ind+action_list_count; i++)
|
||||||
|
{
|
||||||
|
_ps.alist_list[i] = new PAHeader[8];
|
||||||
|
_ps.alist_list[i]->actions_allocated = 8;
|
||||||
|
_ps.alist_list[i]->type = PAHeaderID;
|
||||||
|
_ps.alist_list[i]->count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_PUnLock();
|
||||||
|
|
||||||
|
return ind;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pNewActionList(int action_list_num)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
_ps.pact = _ps.GetListPtr(action_list_num);
|
||||||
|
|
||||||
|
if(_ps.pact == NULL)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
_ps.list_id = action_list_num;
|
||||||
|
_ps.in_new_list = true;
|
||||||
|
|
||||||
|
// Remove whatever used to be in the list.
|
||||||
|
_ps.pact->count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pEndActionList()
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(!_ps.in_new_list)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
_ps.in_new_list = false;
|
||||||
|
|
||||||
|
_ps.pact = NULL;
|
||||||
|
_ps.list_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDeleteActionLists(int action_list_num, int action_list_count)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
if(action_list_num < 0)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
if(action_list_num + action_list_count > _ps.alist_count)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
_PLock();
|
||||||
|
|
||||||
|
for(int i = action_list_num; i < action_list_num + action_list_count; i++)
|
||||||
|
{
|
||||||
|
if(_ps.alist_list[i])
|
||||||
|
{
|
||||||
|
delete [] _ps.alist_list[i];
|
||||||
|
_ps.alist_list[i] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_PUnLock();
|
||||||
|
return; // ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_PUnLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pCallActionList(int action_list_num)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
{
|
||||||
|
// Add this call as an action to the current list.
|
||||||
|
// <<< cgc >>> commented out predeclaration
|
||||||
|
//void _pSendAction(ParticleAction *S, PActionEnum type, int size);
|
||||||
|
|
||||||
|
PACallActionList S;
|
||||||
|
S.action_list_num = action_list_num;
|
||||||
|
|
||||||
|
_pSendAction(&S, PACallActionListID, sizeof(PACallActionList));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Execute the specified action list.
|
||||||
|
PAHeader *pa = _ps.GetListPtr(action_list_num);
|
||||||
|
|
||||||
|
if(pa == NULL)
|
||||||
|
return; // ERRROR
|
||||||
|
|
||||||
|
// XXX A temporary hack.
|
||||||
|
pa->dt = _ps.dt;
|
||||||
|
|
||||||
|
_ps.in_call_list = true;
|
||||||
|
|
||||||
|
_pCallActionList(pa+1, pa->count-1, _ps.pgrp);
|
||||||
|
|
||||||
|
_ps.in_call_list = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
// Particle Group Calls
|
||||||
|
|
||||||
|
// Create particle groups, each with max_particles allocated.
|
||||||
|
PARTICLEDLL_API int pGenParticleGroups(int p_group_count, int max_particles)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return -1; // ERROR
|
||||||
|
|
||||||
|
_PLock();
|
||||||
|
// cerr << "Generating pg " << _ps.tid << " cnt= " << max_particles << endl;
|
||||||
|
|
||||||
|
int ind = _ps.GenerateGroups(p_group_count);
|
||||||
|
|
||||||
|
for(int i=ind; i<ind+p_group_count; i++)
|
||||||
|
{
|
||||||
|
_ps.group_list[i] = (ParticleGroup *)new
|
||||||
|
Particle[max_particles + 2];
|
||||||
|
_ps.group_list[i]->max_particles = max_particles;
|
||||||
|
_ps.group_list[i]->particles_allocated = max_particles;
|
||||||
|
_ps.group_list[i]->p_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_PUnLock();
|
||||||
|
|
||||||
|
return ind;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API void pDeleteParticleGroups(int p_group_num, int p_group_count)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(p_group_num < 0)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
if(p_group_num + p_group_count > _ps.group_count)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
_PLock();
|
||||||
|
|
||||||
|
for(int i = p_group_num; i < p_group_num + p_group_count; i++)
|
||||||
|
{
|
||||||
|
if(_ps.group_list[i])
|
||||||
|
{
|
||||||
|
delete [] _ps.group_list[i];
|
||||||
|
_ps.group_list[i] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_PUnLock();
|
||||||
|
return; // ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_PUnLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change which group is current.
|
||||||
|
PARTICLEDLL_API void pCurrentGroup(int p_group_num)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
_ps.pgrp = _ps.GetGroupPtr(p_group_num);
|
||||||
|
if(_ps.pgrp)
|
||||||
|
_ps.group_id = p_group_num;
|
||||||
|
else
|
||||||
|
_ps.group_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API ParticleGroup* pGetCurrentGroup(void)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
ParticleGroup *pg = _ps.pgrp;
|
||||||
|
return pg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the maximum number of particles in the current group.
|
||||||
|
PARTICLEDLL_API int pSetMaxParticles(int max_count)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return 0; // ERROR
|
||||||
|
|
||||||
|
ParticleGroup *pg = _ps.pgrp;
|
||||||
|
if(pg == NULL)
|
||||||
|
return 0; // ERROR
|
||||||
|
|
||||||
|
if(max_count < 0)
|
||||||
|
return 0; // ERROR
|
||||||
|
|
||||||
|
// Reducing max.
|
||||||
|
if(pg->particles_allocated >= max_count)
|
||||||
|
{
|
||||||
|
pg->max_particles = max_count;
|
||||||
|
|
||||||
|
// May have to kill particles.
|
||||||
|
if(pg->p_count > pg->max_particles)
|
||||||
|
pg->p_count = pg->max_particles;
|
||||||
|
|
||||||
|
return max_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
_PLock();
|
||||||
|
|
||||||
|
// Allocate particles.
|
||||||
|
ParticleGroup *pg2 =(ParticleGroup *)new Particle[max_count + 2];
|
||||||
|
if(pg2 == NULL)
|
||||||
|
{
|
||||||
|
// Not enough memory. Just give all we've got.
|
||||||
|
// ERROR
|
||||||
|
pg->max_particles = pg->particles_allocated;
|
||||||
|
|
||||||
|
_PUnLock();
|
||||||
|
|
||||||
|
return pg->max_particles;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pg2, pg, (pg->p_count + 2) * sizeof(Particle));
|
||||||
|
|
||||||
|
delete [] pg;
|
||||||
|
|
||||||
|
_ps.group_list[_ps.group_id] = _ps.pgrp = pg2;
|
||||||
|
pg2->max_particles = max_count;
|
||||||
|
pg2->particles_allocated = max_count;
|
||||||
|
|
||||||
|
_PUnLock();
|
||||||
|
|
||||||
|
return max_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy from the specified group to the current group.
|
||||||
|
PARTICLEDLL_API void pCopyGroup(int p_src_group_num, int index, int copy_count)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
ParticleGroup *srcgrp = _ps.GetGroupPtr(p_src_group_num);
|
||||||
|
if(srcgrp == NULL)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
ParticleGroup *destgrp = _ps.pgrp;
|
||||||
|
if(destgrp == NULL)
|
||||||
|
return; // ERROR
|
||||||
|
|
||||||
|
// Find out exactly how many to copy.
|
||||||
|
int ccount = copy_count;
|
||||||
|
if(ccount > srcgrp->p_count - index)
|
||||||
|
ccount = srcgrp->p_count - index;
|
||||||
|
if(ccount > destgrp->max_particles - destgrp->p_count)
|
||||||
|
ccount = destgrp->max_particles - destgrp->p_count;
|
||||||
|
|
||||||
|
// #pragma critical
|
||||||
|
// cerr << p_src_group_num << ": " << ccount << " " << srcgrp->p_count << " " << index << endl;
|
||||||
|
|
||||||
|
if(ccount<0)
|
||||||
|
ccount = 0;
|
||||||
|
|
||||||
|
// Directly copy the particles to the current list.
|
||||||
|
for(int i=0; i<ccount; i++)
|
||||||
|
{
|
||||||
|
destgrp->list[destgrp->p_count+i] =
|
||||||
|
srcgrp->list[index+i];
|
||||||
|
}
|
||||||
|
destgrp->p_count += ccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTICLEDLL_API ParticleGroup* pGetParticleGroupRef(int p_group_num)
|
||||||
|
{
|
||||||
|
ParticleGroup* theGroup = NULL;
|
||||||
|
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(!_ps.in_new_list)
|
||||||
|
{
|
||||||
|
theGroup = _ps.GetGroupPtr(p_group_num);
|
||||||
|
}
|
||||||
|
return theGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy from the current group to application memory.
|
||||||
|
PARTICLEDLL_API int pGetParticles(int index, int count, float *verts,
|
||||||
|
float *color, float *vel, float *size, float *age)
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
// XXX I should think about whether color means color3, color4, or what.
|
||||||
|
// For now, it means color4.
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return -1; // ERROR
|
||||||
|
|
||||||
|
ParticleGroup *pg = _ps.pgrp;
|
||||||
|
if(pg == NULL)
|
||||||
|
return -2; // ERROR
|
||||||
|
|
||||||
|
if(index < 0 || count < 0)
|
||||||
|
return -3; // ERROR
|
||||||
|
|
||||||
|
if(index + count > pg->p_count)
|
||||||
|
{
|
||||||
|
count = pg->p_count - index;
|
||||||
|
if(count <= 0)
|
||||||
|
return -4; // ERROR index out of bounds.
|
||||||
|
}
|
||||||
|
|
||||||
|
int vi = 0, ci = 0, li = 0, si = 0, ai = 0;
|
||||||
|
|
||||||
|
// This could be optimized.
|
||||||
|
for(int i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
Particle &m = pg->list[index + i];
|
||||||
|
|
||||||
|
if(verts)
|
||||||
|
{
|
||||||
|
verts[vi++] = m.pos.x;
|
||||||
|
verts[vi++] = m.pos.y;
|
||||||
|
verts[vi++] = m.pos.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(color)
|
||||||
|
{
|
||||||
|
color[ci++] = m.color.x;
|
||||||
|
color[ci++] = m.color.y;
|
||||||
|
color[ci++] = m.color.z;
|
||||||
|
color[ci++] = m.alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vel)
|
||||||
|
{
|
||||||
|
vel[li++] = m.vel.x;
|
||||||
|
vel[li++] = m.vel.y;
|
||||||
|
vel[li++] = m.vel.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(size)
|
||||||
|
{
|
||||||
|
size[si++] = m.size.x;
|
||||||
|
size[si++] = m.size.y;
|
||||||
|
size[si++] = m.size.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(age)
|
||||||
|
{
|
||||||
|
age[ai++] = m.age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the number of particles currently in the group.
|
||||||
|
PARTICLEDLL_API int pGetGroupCount()
|
||||||
|
{
|
||||||
|
_ParticleState &_ps = _GetPState();
|
||||||
|
|
||||||
|
if(_ps.in_new_list)
|
||||||
|
return 0; // ERROR
|
||||||
|
|
||||||
|
if(_ps.pgrp == NULL)
|
||||||
|
return 0; // ERROR
|
||||||
|
|
||||||
|
return _ps.pgrp->p_count;
|
||||||
|
}
|
Loading…
Reference in a new issue