mirror of
https://github.com/unknownworlds/NS.git
synced 2024-11-14 00:41: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