Adding particle system - probably needs work, should try to get the version from the NS1 svn repository

This commit is contained in:
hjw 2014-01-23 10:49:10 +00:00
parent 0ddfe3c35f
commit c47caa1440
29 changed files with 4366 additions and 49 deletions

View file

@ -49,14 +49,20 @@ typedef int BOOL;
#define MAX_PATH PATH_MAX
#include <limits.h>
#include <stdarg.h>
#ifdef PUZL
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef _vsnprintf
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
#endif
#ifndef _snprintf
#define _snprintf(a,b,c,d,e)
#endif
#endif
#endif //_WIN32
// Misc C-runtime library headers

View file

@ -6,18 +6,18 @@
DLLNAME=ns
ARCH=i386
ARCH=i686
#make sure this is the correct compiler for your system
CC=gcc
LD=gcc
LIBBASE=../../../libraries/current
LIBBASE=..
DLL_SRCDIR=../dlls
GAME_SHARED_SRCDIR = ../game_shared
MOD_SRCDIR = ../mod
PARTICLES_SRCDIR = ../particles
PARTICLES_SRCDIR = ../Particle
PM_SHARED_SRCDIR=../pm_shared
TEXT_SRCDIR = ../textrep
UTIL_SRCDIR = ../util
@ -36,15 +36,15 @@ BASE_CFLAGS=-Dstricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp
# -DAVH_SECURE_PRERELEASE_BUILD for CM testing
#full optimization
CFLAGS=$(BASE_CFLAGS) -w -Wall -nostdinc++ -ffor-scope -fPIC -mcpu=i486 -O3 -pipe -funroll-loops -fdelayed-branch -malign-loops=4 -malign-jumps=4 -malign-functions=4
CFLAGS=$(BASE_CFLAGS) -w -Wall -nostdinc++ -fpermissive -ffor-scope -fPIC -mtune=$(ARCH) -O3 -pipe -funroll-loops -fdelayed-branch -falign-loops=4 -falign-jumps=4 -falign-functions=4
#use these when debugging
#CFLAGS=$(BASE_CFLAGS) -fPIC -fno-for-scope
# add base directory (CGC)
INCLUDEDIRS=-I$(LIBBASE) -I. -I$(LIBBASE)/include -I$(LIBBASE)/include/stlport -I$(LIBBASE)/include/particle -I$(LIBBASE)/include/lua -I../dlls -I../engine -I../common -I../mod -I../game_shared -I../pm_shared -I.. -I/usr/include/c++/3.3/i486-linux -I/usr/include/c++/3.3 -I/usr/include/c++
LINKDIRS= -L$(LIBBASE)/release
INCLUDEDIRS=-I$(LIBBASE) -I. -I$(LIBBASE)/include -I$(LIBBASE)/include/stlport -I$(LIBBASE)/particle -I$(LIBBASE)/include/lua -I../dlls -I../engine -I../common -I../mod -I../game_shared -I../pm_shared -I.. -I/usr/include/x86_64-linux-gnu/c++/4.8 -I/usr/include/c++/4.8 -I/usr/include/c++
LINKDIRS= -L$(LIBBASE)/particle
SHLIBEXT=so
@ -52,7 +52,7 @@ LDPRELIBS= $(CFLAGS) -shared \
-Wl,-Map,ns_map.txt \
$(LINKDIRS)
LDPOSTLIBS= -Wl,-Bstatic -lstlport_gcc -lstdc++ -lsupc++ -llua -llualib -lparticleMP -lcurl \
LDPOSTLIBS= -Wl,-Bstatic -lstdc++ -lsupc++ -lparticleMP -lcurl \
-Wl,-Bdynamic -lm -lgcc -lgcc_eh
# -lgcc -lgcc_eh -lelf
DO_CC=$(CC) $(CFLAGS) $(INCLUDEDIRS) -o $@ -c $<
@ -257,18 +257,18 @@ release: $(DLLNAME)_$(ARCH).$(SHLIBEXT)
curl:
./build-curl.sh
neat:
-mkdir $(CURL_OBJDIR)
-mkdir $(DLL_OBJDIR)
-mkdir $(GAME_SHARED_OBJDIR)
-mkdir $(MOD_OBJDIR)
-mkdir $(PARTICLES_OBJDIR)
-mkdir $(PM_SHARED_OBJDIR)
-mkdir $(TEXT_OBJDIR)
-mkdir $(UTIL_OBJDIR)
-mkdir $(OUTPUT_DIR)
@-mkdir -p $(CURL_OBJDIR)
@-mkdir -p $(DLL_OBJDIR)
@-mkdir -p $(GAME_SHARED_OBJDIR)
@-mkdir -p $(MOD_OBJDIR)
@-mkdir -p $(PARTICLES_OBJDIR)
@-mkdir -p $(PM_SHARED_OBJDIR)
@-mkdir -p $(TEXT_OBJDIR)
@-mkdir -p $(UTIL_OBJDIR)
@-mkdir -p $(OUTPUT_DIR)
clean:
-rm -f $(OBJ)
-rm -f $(DLLNAME)_$(ARCH).$(SHLIBEXT)
-rm $(OBJ)
-rm $(DLLNAME)_$(ARCH).$(SHLIBEXT)
spotless: clean
-rm -r $(CURL_OBJDIR)
-rm -r $(DLL_OBJDIR)

View file

@ -1,4 +1,5 @@
#include <math.h>
#include <string.h>
#include "types.h"
#ifdef AVH_CLIENT
@ -665,4 +666,4 @@ void NS_GetBoneMatrices(const NS_AnimationData& inAnimationData, float time, NS_
}
}
}

View file

@ -1211,17 +1211,17 @@ void TriggerPresence::KeyValue(KeyValueData* pkvd)
}
else if(FStrEq(pkvd->szKeyName, "timebeforeleave"))
{
this->mTimeBeforeLeave = max(atof(pkvd->szValue), 0.0f);
this->mTimeBeforeLeave = max(atof(pkvd->szValue), (double)0.0f);
pkvd->fHandled = TRUE;
}
else if(FStrEq(pkvd->szKeyName, "momentaryopentime"))
{
this->mMomentaryOpenTime = max(atof(pkvd->szValue), 0.01f);
this->mMomentaryOpenTime = max(atof(pkvd->szValue), (double)0.01f);
pkvd->fHandled = TRUE;
}
else if(FStrEq(pkvd->szKeyName, "momentaryclosetime"))
{
this->mMomentaryCloseTime = max(atof(pkvd->szValue), 0.01f);
this->mMomentaryCloseTime = max(atof(pkvd->szValue), (double)0.01f);
pkvd->fHandled = TRUE;
}
else if(FStrEq(pkvd->szKeyName, "spawnflags"))

View file

@ -4,20 +4,22 @@
using std::string;
#include "AvHNexusServer.h"
#include "AvHServerUtil.h"
bool AvHNexus::send(entvars_t* const pev, const unsigned char* data, const unsigned int length) { return false; }
bool AvHNexus::recv(entvars_t* const pev, const char* data, const unsigned int length) { return false; }
string AvHNexus::getNetworkID(const edict_t* edict) { return AvHSUGetPlayerAuthIDString((edict_t *)edict); }
void AvHNexus::handleUnauthorizedJoinTeamAttempt(const edict_t* edict, const unsigned char team_index) {}
void AvHNexus::performSpeedTest(void) {}
void AvHNexus::processResponses(void) {}
void AvHNexus::setGeneratePerformanceData(const edict_t* edict, const bool generate) {}
bool AvHNexus::getGeneratePerformanceData(void) { return false; }
bool AvHNexus::isRecordingGame(void) { return false; }
void AvHNexus::cancelGame(void) {}
void AvHNexus::finishGame(void) {}
void AvHNexus::startGame(void) {}
void AvHNexus::startup(void) {}
void AvHNexus::shutdown(void) {}
namespace AvHNexus {
bool send(entvars_t* const pev, const unsigned char* data, const unsigned int length) { return false; }
bool recv(entvars_t* const pev, const char* data, const unsigned int length) { return false; }
string getNetworkID(const edict_t* edict) { return AvHSUGetPlayerAuthIDString((edict_t *)edict); }
void handleUnauthorizedJoinTeamAttempt(const edict_t* edict, const unsigned char team_index) {}
void performSpeedTest(void) {}
void processResponses(void) {}
void setGeneratePerformanceData(const edict_t* edict, const bool generate) {}
bool getGeneratePerformanceData(void) { return false; }
bool isRecordingGame(void) { return false; }
void cancelGame(void) {}
void finishGame(void) {}
void startGame(void) {}
void startup(void) {}
void shutdown(void) {}
}
#else
#include <NexusServerInterface.h>
#include "AvHNexusServer.h"

View file

@ -688,9 +688,9 @@ AvHParticleSystem::GenerateParticles(int inNumberParticles)
else if(theDomain == PS_Sphere)
{
float theRadius1 = fabs(this->mGenerationEntityAbsMax[0] - this->mGenerationEntityAbsMin[0])/2.0f;
theRadius1 = max(theRadius1 - theEdgeInset, 0);
theRadius1 = max(theRadius1 - theEdgeInset, 0.0f);
float theRadius2 = this->mGenerationEntityParam;
theRadius2 = max(theRadius2 - theEdgeInset, 0);
theRadius2 = max(theRadius2 - theEdgeInset, 0.0f);
theParams[3] = theRadius1;
theParams[4] = theRadius2;
}

View file

@ -205,4 +205,4 @@ private:
};
#endif
#endif

View file

@ -19,6 +19,7 @@
#ifndef AVH_PSMANAGER_H
#define AVH_PSMANAGER_H
#include <string.h>
#include "util/nowarnings.h"
#include "types.h"
#include "mod/AvHParticleSystem.h"
@ -169,4 +170,4 @@ private:
};
#endif
#endif

View file

@ -1,3 +1,4 @@
#include <string.h>
#include "util/nowarnings.h"
#include "mod/AvHParticleTemplate.h"
#include "common/renderingconst.h"

View file

@ -6878,7 +6878,7 @@ void AvHPlayer::InternalMovementThink()
float factor = pushbackfactor / (radius / distance);
float weigthFactor=1.0f;
int veriticalLimit=110;
float veriticalLimit=110.0f;
switch(theEntity->pev->iuser3) {
case AVH_USER3_ALIEN_PLAYER4:
weigthFactor=0.70f;
@ -9227,7 +9227,7 @@ bool AvHPlayer::RunClientScript(const string& inScriptName)
void AvHPlayer::PrintWeaponListToClient(CBaseEntity *theAvHPlayer) {
char msg[1024];
sprintf(msg, "Weapons for %s:\n", this->GetPlayerName());
sprintf(msg, "Weapons for %s:\n", this->GetPlayerName().c_str());
ClientPrint(theAvHPlayer->pev, HUD_PRINTNOTIFY, msg);
for(int i = 0; i < MAX_ITEM_TYPES; i++)

View file

@ -46,13 +46,16 @@
#include "common/event_api.h"
#include "mod/AvHScriptManager.h"
#ifdef USE_LUA
extern "C" {
#include <lua.h>
}
#endif
extern void DrawScaledHUDSprite(int inSpriteHandle, int inMode, int inRowsInSprite = 1, int inX = 0, int inY = 0, int inWidth = ScreenWidth(), int inHeight = ScreenHeight(), int inForceSpriteFrame = -1, float inStartU = 0.0f, float inStartV = 0.0f, float inEndU = 1.0f, float inEndV = 1.0f, float inRotateUVRadians = 0.0f, bool inUVWrapsOverFrames = false);
extern vec3_t v_origin;
#ifdef USE_LUA
static int errormessage(lua_State* inState)
{
const char *s = lua_tostring(inState, 1);
@ -93,6 +96,7 @@ static int print(lua_State* inState)
return 0;
}
// Runs a client command, returns success
static int clientCommand(lua_State* inState)
{
@ -438,9 +442,11 @@ static int triFog(lua_State* inState)
return 1;
}
#endif
void AvHScriptInstance::InitClient()
{
#ifdef USE_LUA
//lua_register(this->mState, LUA_ERRORMESSAGE, errormessage);
lua_register(this->mState, "print", print);
lua_register(this->mState, "clientCommand", clientCommand);
@ -469,4 +475,5 @@ void AvHScriptInstance::InitClient()
//lua_register(this->mState, "drawScaledHUDSprite", drawScaledHUDSpriteUV);
//lua_register(this->mState, "drawScaledTiledHUDSprite", drawScaledTiledHUDSprite);
}
#endif
}

View file

@ -28,17 +28,21 @@
#include "util/STLUtil.h"
#include "mod/AvHConstants.h"
#ifdef USE_LUA
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#endif
AvHScriptInstance* gRunningScript = NULL;
AvHScriptInstance::AvHScriptInstance(string inScriptName)
{
#ifdef USE_LUA
this->mState = NULL;
#endif
this->Init();
@ -70,10 +74,12 @@ void AvHScriptInstance::CallSimpleFunction(const string& inFunctionName)
{
gRunningScript = this;
#ifdef USE_LUA
// Execute callback
lua_getglobal(this->mState, inFunctionName.c_str());
//lua_pushstring(this->mState, inFunctionName.c_str());
lua_call(this->mState, 0, 0);
#endif
gRunningScript = NULL;
}
@ -83,16 +89,21 @@ void AvHScriptInstance::Cleanup()
ASSERT(!this->CallbacksPending());
ASSERT(this->mState);
#ifdef USE_LUA
lua_close(this->mState);
#endif
}
#ifdef USE_LUA
lua_State* AvHScriptInstance::GetState()
{
return this->mState;
}
#endif
void AvHScriptInstance::Init()
{
#ifdef USE_LUA
this->mState = lua_open();
lua_baselibopen(this->mState);
@ -107,6 +118,7 @@ void AvHScriptInstance::Init()
#else
this->InitClient();
#endif
#endif
}
void AvHScriptInstance::Reset()
@ -127,7 +139,9 @@ void AvHScriptInstance::Run()
// Set global current script so it's accessible statically (needed for setting callbacks)
gRunningScript = this;
#ifdef USE_LUA
lua_dofile(this->mState, this->mScriptName.c_str());
#endif
gRunningScript = NULL;
}
@ -235,6 +249,7 @@ void AvHScriptManager::Update(float inTime)
#ifdef AVH_CLIENT
void AvHScriptManager::ClientUpdate(float inTimePassed)
{
#ifdef USE_LUA
// For all scripts
for(AvHScriptInstanceListType::iterator theIter = this->mScriptList.begin(); theIter != this->mScriptList.end(); /* no increment */)
{
@ -269,6 +284,7 @@ void AvHScriptManager::ClientUpdate(float inTimePassed)
theIter++;
}
}
#endif
}
void AvHScriptManager::DrawNormal()
@ -301,6 +317,7 @@ void AvHScriptManager::DrawNoZBuffering()
bool AvHScriptManager::GetClientMove(int& outButtonBits, int& outImpulse)
{
bool theSuccess = false;
#ifdef USE_LUA
#ifdef DEBUG
@ -335,6 +352,7 @@ bool AvHScriptManager::GetClientMove(int& outButtonBits, int& outImpulse)
#endif
#endif
return theSuccess;
}

View file

@ -23,7 +23,9 @@
#include "util/Checksum.h"
#include "util/STLUtil.h"
#ifdef USE_LUA
extern "C" struct lua_State;
#endif
class AvHScriptInstance
{
@ -38,7 +40,9 @@ public:
void Cleanup();
#ifdef USE_LUA
lua_State* GetState();
#endif
void Reset();
@ -58,7 +62,9 @@ private:
#endif
// This gets copied around, so make sure elements can be shallow-copied or write a copy constructor
#ifdef USE_LUA
lua_State* mState;
#endif
string mScriptName;
typedef pair<string, float> CallbackType;
@ -96,4 +102,4 @@ private:
};
#endif
#endif

View file

@ -33,6 +33,7 @@
#include "util/Checksum.h"
#include "util/STLUtil.h"
#ifdef USE_LUA
extern "C" {
#include <lua.h>
}
@ -545,8 +546,11 @@ static int setServerVariable(lua_State* inState)
return 0;
}
#endif
void AvHScriptInstance::InitServer()
{
#ifdef USE_LUA
//lua_register(this->mState, LUA_ERRORMESSAGE, errormessage);
//lua_register(this->mState, "execute", execute);
@ -579,4 +583,6 @@ void AvHScriptInstance::InitServer()
lua_register(this->mState, "runClientScript", runClientScript);
lua_register(this->mState, "setServerVariable", setServerVariable);
}
#endif
}

View file

@ -37,6 +37,7 @@
#include "mod/AvHSharedUtil.h"
#ifdef USE_LUA
extern "C" {
#include <lua.h>
}
@ -93,3 +94,4 @@ void AvHScriptInstance::InitShared()
lua_register(this->mState, "getTime", getTime);
}
#endif

View file

@ -0,0 +1,43 @@
######################################################################
# Particle System API
#
# Copyright 1998 by David K. McAllister.
#
######################################################################
C++ = g++
GLUT_HOME =/usr/local/contrib/unmoderated
MP = #-mp -DPARTICLE_MP
# Make it real fast on an Origin 2000.
#LNO =-LNO:opt=1:fusion=2:fission=2:fusion_peeling_limit=2048:cs1=32K:cs2=8M
COPT = $(MP) -O3 $(LNO) -fPIC
CFLAGS = $(COPT) $(COMPFLAGS) -I. -I.. -I$(GLUT_HOME)/include -I/usr/include/c++/4.8/
POBJS =action_api.o actions.o opengl.o system.o
ALL = libparticleMP.a SPDir
all: $(ALL)
# following line needed for c++ .cc files
.SUFFIXES : .cpp
.cpp.o:
$(C++) $(CFLAGS) -c $<
libparticleMP.a: $(POBJS)
rm -f $@
ar clq $@ $(POBJS)
SPDir:
(cd SP ; smake)
clean:
(cd SP ; smake clean)
rm -f libpar*
rm -f *.o
rm -rf *ii_files

View file

@ -0,0 +1,132 @@
# Microsoft Developer Studio Project File - Name="ParticleDLL" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=ParticleDLL - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ParticleDLL.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ParticleDLL.mak" CFG="ParticleDLL - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ParticleDLL - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "ParticleDLL - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "ParticleDLL - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I ".." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "PARTICLEDLL_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# SUBTRACT LINK32 /profile
!ELSEIF "$(CFG)" == "ParticleDLL - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "PARTICLEDLL_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "ParticleDLL - Win32 Release"
# Name "ParticleDLL - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\action_api.cpp
# End Source File
# Begin Source File
SOURCE=.\actions.cpp
# End Source File
# Begin Source File
SOURCE=.\opengl.cpp
# End Source File
# Begin Source File
SOURCE=.\system.cpp
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Group "Header Files"
# PROP Default_Filter ".h"
# Begin Source File
SOURCE=.\general.h
# End Source File
# Begin Source File
SOURCE=.\p_vector.h
# End Source File
# Begin Source File
SOURCE=.\papi.h
# End Source File
# End Group
# End Target
# End Project

View 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.

View file

@ -0,0 +1,390 @@
// 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"
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));
}

File diff suppressed because it is too large Load diff

View file

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

Binary file not shown.

View 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();
}
}

View 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

229
main/source/particle/papi.h Normal file
View file

@ -0,0 +1,229 @@
// 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
#ifdef WIN32
#include <windows.h>
#ifdef PARTICLEDLL_EXPORTS
#define PARTICLEDLL_API __declspec(dllexport)
#else
#define PARTICLEDLL_API __declspec(dllimport)
#endif
#else
#define PARTICLEDLL_API
#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
};
// 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 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 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);
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

View file

@ -0,0 +1,883 @@
// 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;
// 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
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.
extern 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;
}
// 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;
}
// 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;
}

View file

@ -9,6 +9,8 @@
#include <memory>
#include <set>
#include <vector>
#include <string.h>
#include <stdlib.h>
#include "Balance.h"
using std::auto_ptr;
@ -1054,4 +1056,4 @@ bool FileValueContainer::save(void)
file.close();
return true;
}
}

View file

@ -2,6 +2,7 @@
#define C_STRING_H
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
using std::string;

View file

@ -29,6 +29,7 @@
#ifndef STL_UTIL_H
#define STL_UTIL_H
#include <string.h>
#include "util/nowarnings.h"
#include "util/CString.h"
#include "types.h"
@ -53,4 +54,4 @@ bool MakeHexPairsFromBytes(const unsigned char* inBytes, string& ioHex, int numB
extern int32 sprintf(string& inOutput, const char* inPattern, ...);
#endif
#endif