2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-13 18:17:49 -04:00

Fix line endings and tabs

This commit is contained in:
Branan Purvine-Riley
2011-04-11 16:27:55 -07:00
parent d4250e19b5
commit 908aaeb6f6
2738 changed files with 702562 additions and 702562 deletions

View File

@ -1,34 +1,34 @@
include_directories("../../CoreLib")
include_directories("../../NucleusLib/inc")
include_directories("../../NucleusLib")
include_directories("../../PubUtilLib")
set(plParticleSystem_SOURCES
plBoundInterface.cpp
plConvexVolume.cpp
plParticleApplicator.cpp
plParticleEffect.cpp
plParticleEmitter.cpp
plParticleGenerator.cpp
plParticleSDLMod.cpp
plParticleSystem.cpp
)
set(plParticleSystem_HEADERS
plBoundInterface.h
plConvexVolume.h
plEffectTargetInfo.h
plParticle.h
plParticleApplicator.h
plParticleCreatable.h
plParticleEffect.h
plParticleEmitter.h
plParticleGenerator.h
plParticleSDLMod.h
plParticleSystem.h
)
add_library(plParticleSystem STATIC ${plParticleSystem_SOURCES} ${plParticleSystem_HEADERS})
source_group("Source Files" FILES ${plParticleSystem_SOURCES})
source_group("Header Files" FILES ${plParticleSystem_HEADERS})
include_directories("../../CoreLib")
include_directories("../../NucleusLib/inc")
include_directories("../../NucleusLib")
include_directories("../../PubUtilLib")
set(plParticleSystem_SOURCES
plBoundInterface.cpp
plConvexVolume.cpp
plParticleApplicator.cpp
plParticleEffect.cpp
plParticleEmitter.cpp
plParticleGenerator.cpp
plParticleSDLMod.cpp
plParticleSystem.cpp
)
set(plParticleSystem_HEADERS
plBoundInterface.h
plConvexVolume.h
plEffectTargetInfo.h
plParticle.h
plParticleApplicator.h
plParticleCreatable.h
plParticleEffect.h
plParticleEmitter.h
plParticleGenerator.h
plParticleSDLMod.h
plParticleSystem.h
)
add_library(plParticleSystem STATIC ${plParticleSystem_SOURCES} ${plParticleSystem_HEADERS})
source_group("Source Files" FILES ${plParticleSystem_SOURCES})
source_group("Header Files" FILES ${plParticleSystem_HEADERS})

View File

@ -1,76 +1,76 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsGeometry3.h"
#include "plBoundInterface.h"
#include "plConvexVolume.h"
#include "hsResMgr.h"
plBoundInterface::plBoundInterface() : fBounds(nil)
{
}
plBoundInterface::~plBoundInterface()
{
ReleaseData();
}
void plBoundInterface::ReleaseData()
{
delete fBounds;
fBounds = nil;
}
void plBoundInterface::Init(plConvexVolume *bounds)
{
ReleaseData();
fBounds = bounds;
}
// Right now, this is ignoring the enabled property of ObjInterface, since I'm not aware that
// anything ever makes use of it (and if nothing does, this saves us on some needless matrix
// copying). Should we make use of the disabled prop, this function should just store the l2w
// matrix, but not send an update to fBounds.
void plBoundInterface::SetTransform(const hsMatrix44 &l2w, const hsMatrix44&w2l)
{
if (fBounds != nil)
fBounds->Update(l2w);
}
void plBoundInterface::Read(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Read(s, mgr);
fBounds = plConvexVolume::ConvertNoRef(mgr->ReadCreatable(s));
//mgr->ReadKeyNotifyMe(s, new plIntRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plIntRefMsg::kOwner), plRefFlags::kPassiveRef);
}
void plBoundInterface::Write(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Write(s, mgr);
mgr->WriteCreatable(s, fBounds);
//mgr->WriteKey(s, fBounds);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsGeometry3.h"
#include "plBoundInterface.h"
#include "plConvexVolume.h"
#include "hsResMgr.h"
plBoundInterface::plBoundInterface() : fBounds(nil)
{
}
plBoundInterface::~plBoundInterface()
{
ReleaseData();
}
void plBoundInterface::ReleaseData()
{
delete fBounds;
fBounds = nil;
}
void plBoundInterface::Init(plConvexVolume *bounds)
{
ReleaseData();
fBounds = bounds;
}
// Right now, this is ignoring the enabled property of ObjInterface, since I'm not aware that
// anything ever makes use of it (and if nothing does, this saves us on some needless matrix
// copying). Should we make use of the disabled prop, this function should just store the l2w
// matrix, but not send an update to fBounds.
void plBoundInterface::SetTransform(const hsMatrix44 &l2w, const hsMatrix44&w2l)
{
if (fBounds != nil)
fBounds->Update(l2w);
}
void plBoundInterface::Read(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Read(s, mgr);
fBounds = plConvexVolume::ConvertNoRef(mgr->ReadCreatable(s));
//mgr->ReadKeyNotifyMe(s, new plIntRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plIntRefMsg::kOwner), plRefFlags::kPassiveRef);
}
void plBoundInterface::Write(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Write(s, mgr);
mgr->WriteCreatable(s, fBounds);
//mgr->WriteKey(s, fBounds);
}
// No need to save/load. The coordinate interface on our sceneObject will update us.

View File

@ -1,67 +1,67 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plBoundInterface_inc
#define plBoundInterface_inc
#include "pnSceneObject/plObjInterface.h"
class plConvexVolume;
struct hsMatrix44;
class plBoundInterface : public plObjInterface
{
enum {
kDisable = 0x0,
kNumProps // last
};
protected:
//hsMatrix44 fLocalToWorld;
plConvexVolume *fBounds;
public:
plBoundInterface();
~plBoundInterface();
void Init(plConvexVolume *bounds);
plConvexVolume *GetVolume() { return fBounds; }
CLASSNAME_REGISTER( plBoundInterface );
GETINTERFACE_ANY( plBoundInterface, plObjInterface );
virtual Int32 GetNumProperties() const { return kNumProps; }
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual void ReleaseData();
};
#endif // plBoundInterface_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plBoundInterface_inc
#define plBoundInterface_inc
#include "pnSceneObject/plObjInterface.h"
class plConvexVolume;
struct hsMatrix44;
class plBoundInterface : public plObjInterface
{
enum {
kDisable = 0x0,
kNumProps // last
};
protected:
//hsMatrix44 fLocalToWorld;
plConvexVolume *fBounds;
public:
plBoundInterface();
~plBoundInterface();
void Init(plConvexVolume *bounds);
plConvexVolume *GetVolume() { return fBounds; }
CLASSNAME_REGISTER( plBoundInterface );
GETINTERFACE_ANY( plBoundInterface, plObjInterface );
virtual Int32 GetNumProperties() const { return kNumProps; }
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual void ReleaseData();
};
#endif // plBoundInterface_inc

View File

@ -1,193 +1,193 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "plConvexVolume.h"
#include "hsStream.h"
plConvexVolume::plConvexVolume()
{
//fFlags = nil;
fLocalPlanes = nil;
fWorldPlanes = nil;
fNumPlanes = 0;
}
plConvexVolume::~plConvexVolume()
{
IClear();
}
void plConvexVolume::IClear()
{
//delete [] fFlags;
delete [] fLocalPlanes;
delete [] fWorldPlanes;
}
hsBool plConvexVolume::AddPlane(const hsPlane3 &plane)
{
// First check for a redundant plane (since we're convex, a comparison of normals should do)
int i;
// Start the comparison with the most recently added plane, it's most likely to match
for (i = fNumPlanes - 1; i >= 0; i--)
{
const float MIN_COS_THETA = 0.99999f; // translates to < 0.25 degree angle
// If the angle betwen the normals is close enough, count them as equal.
if (fLocalPlanes[i].fN.InnerProduct(plane.fN) >= MIN_COS_THETA)
return false; // no need to add it
}
fNumPlanes++;
//delete [] fFlags;
//fFlags = TRACKED_NEW UInt32[fNumPlanes];
hsPlane3 *tempPlanes = TRACKED_NEW hsPlane3[fNumPlanes];
for (i = 0; i < fNumPlanes - 1; i++)
{
tempPlanes[i] = fLocalPlanes[i];
}
tempPlanes[fNumPlanes - 1] = plane;
delete [] fLocalPlanes;
fLocalPlanes = tempPlanes;
delete [] fWorldPlanes;
fWorldPlanes = TRACKED_NEW hsPlane3[fNumPlanes];
return true;
}
void plConvexVolume::Update(const hsMatrix44 &l2w)
{
int i;
hsPoint3 planePt;
for (i = 0; i < fNumPlanes; i++)
{
// Since fN is an hsVector3, it will only apply the rotational aspect of the transform...
fWorldPlanes[i].fN = l2w * fLocalPlanes[i].fN;
planePt.Set(&(fLocalPlanes[i].fN * fLocalPlanes[i].fD));
fWorldPlanes[i].fD = -(l2w * planePt).InnerProduct(fWorldPlanes[i].fN);
}
}
void plConvexVolume::SetNumPlanesAndClear(const UInt32 num)
{
IClear();
//fFlags = TRACKED_NEW UInt32[num];
fLocalPlanes = TRACKED_NEW hsPlane3[num];
fWorldPlanes = TRACKED_NEW hsPlane3[num];
fNumPlanes = num;
}
void plConvexVolume::SetPlane(const hsPlane3 &plane, const UInt32 index)
{
fLocalPlanes[index] = plane;
}
hsBool plConvexVolume::IsInside(const hsPoint3 &pos) const
{
int i;
for( i = 0; i < fNumPlanes; i++ )
{
if (!TestPlane(pos, fWorldPlanes[i]))
return false;
}
return true;
}
hsBool plConvexVolume::ResolvePoint(hsPoint3 &pos) const
{
hsScalar minDist = 1.e33f;
Int32 minIndex = -1;
hsScalar currDist;
int i;
for (i = 0; i < fNumPlanes; i++)
{
currDist = -fWorldPlanes[i].fD - fWorldPlanes[i].fN.InnerProduct(pos);
if (currDist < 0)
return false; // We're not inside this plane, and thus outside the volume
if (currDist < minDist)
{
minDist = currDist;
minIndex = i;
}
}
pos += (-fWorldPlanes[minIndex].fD - fWorldPlanes[minIndex].fN.InnerProduct(pos)) * fWorldPlanes[minIndex].fN;
return true;
}
hsBool plConvexVolume::BouncePoint(hsPoint3 &pos, hsVector3 &velocity, hsScalar bounce, hsScalar friction) const
{
hsScalar minDist = 1.e33f;
Int32 minIndex = -1;
hsScalar currDist;
int i;
for (i = 0; i < fNumPlanes; i++)
{
currDist = -fWorldPlanes[i].fD - fWorldPlanes[i].fN.InnerProduct(pos);
if (currDist < 0)
return false; // We're not inside this plane, and thus outside the volume
if (currDist < minDist)
{
minDist = currDist;
minIndex = i;
}
}
pos += (-fWorldPlanes[minIndex].fD - fWorldPlanes[minIndex].fN.InnerProduct(pos)) * fWorldPlanes[minIndex].fN;
hsVector3 bnc = -velocity.InnerProduct(fWorldPlanes[minIndex].fN) * fWorldPlanes[minIndex].fN;
velocity += bnc;
velocity *= 1.f - friction;
velocity += bnc * bounce;
// velocity += (velocity.InnerProduct(fWorldPlanes[minIndex].fN) * -(1.f + bounce)) * fWorldPlanes[minIndex].fN;
return true;
}
void plConvexVolume::Read(hsStream* s, hsResMgr *mgr)
{
SetNumPlanesAndClear(s->ReadSwap32());
int i;
for (i = 0; i < fNumPlanes; i++)
{
fLocalPlanes[i].Read(s);
//fFlags[i] = s->ReadSwap32();
}
}
void plConvexVolume::Write(hsStream* s, hsResMgr *mgr)
{
s->WriteSwap32(fNumPlanes);
int i;
for (i = 0; i < fNumPlanes; i++)
{
fLocalPlanes[i].Write(s);
//s->WriteSwap32(fFlags[i]);
}
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "plConvexVolume.h"
#include "hsStream.h"
plConvexVolume::plConvexVolume()
{
//fFlags = nil;
fLocalPlanes = nil;
fWorldPlanes = nil;
fNumPlanes = 0;
}
plConvexVolume::~plConvexVolume()
{
IClear();
}
void plConvexVolume::IClear()
{
//delete [] fFlags;
delete [] fLocalPlanes;
delete [] fWorldPlanes;
}
hsBool plConvexVolume::AddPlane(const hsPlane3 &plane)
{
// First check for a redundant plane (since we're convex, a comparison of normals should do)
int i;
// Start the comparison with the most recently added plane, it's most likely to match
for (i = fNumPlanes - 1; i >= 0; i--)
{
const float MIN_COS_THETA = 0.99999f; // translates to < 0.25 degree angle
// If the angle betwen the normals is close enough, count them as equal.
if (fLocalPlanes[i].fN.InnerProduct(plane.fN) >= MIN_COS_THETA)
return false; // no need to add it
}
fNumPlanes++;
//delete [] fFlags;
//fFlags = TRACKED_NEW UInt32[fNumPlanes];
hsPlane3 *tempPlanes = TRACKED_NEW hsPlane3[fNumPlanes];
for (i = 0; i < fNumPlanes - 1; i++)
{
tempPlanes[i] = fLocalPlanes[i];
}
tempPlanes[fNumPlanes - 1] = plane;
delete [] fLocalPlanes;
fLocalPlanes = tempPlanes;
delete [] fWorldPlanes;
fWorldPlanes = TRACKED_NEW hsPlane3[fNumPlanes];
return true;
}
void plConvexVolume::Update(const hsMatrix44 &l2w)
{
int i;
hsPoint3 planePt;
for (i = 0; i < fNumPlanes; i++)
{
// Since fN is an hsVector3, it will only apply the rotational aspect of the transform...
fWorldPlanes[i].fN = l2w * fLocalPlanes[i].fN;
planePt.Set(&(fLocalPlanes[i].fN * fLocalPlanes[i].fD));
fWorldPlanes[i].fD = -(l2w * planePt).InnerProduct(fWorldPlanes[i].fN);
}
}
void plConvexVolume::SetNumPlanesAndClear(const UInt32 num)
{
IClear();
//fFlags = TRACKED_NEW UInt32[num];
fLocalPlanes = TRACKED_NEW hsPlane3[num];
fWorldPlanes = TRACKED_NEW hsPlane3[num];
fNumPlanes = num;
}
void plConvexVolume::SetPlane(const hsPlane3 &plane, const UInt32 index)
{
fLocalPlanes[index] = plane;
}
hsBool plConvexVolume::IsInside(const hsPoint3 &pos) const
{
int i;
for( i = 0; i < fNumPlanes; i++ )
{
if (!TestPlane(pos, fWorldPlanes[i]))
return false;
}
return true;
}
hsBool plConvexVolume::ResolvePoint(hsPoint3 &pos) const
{
hsScalar minDist = 1.e33f;
Int32 minIndex = -1;
hsScalar currDist;
int i;
for (i = 0; i < fNumPlanes; i++)
{
currDist = -fWorldPlanes[i].fD - fWorldPlanes[i].fN.InnerProduct(pos);
if (currDist < 0)
return false; // We're not inside this plane, and thus outside the volume
if (currDist < minDist)
{
minDist = currDist;
minIndex = i;
}
}
pos += (-fWorldPlanes[minIndex].fD - fWorldPlanes[minIndex].fN.InnerProduct(pos)) * fWorldPlanes[minIndex].fN;
return true;
}
hsBool plConvexVolume::BouncePoint(hsPoint3 &pos, hsVector3 &velocity, hsScalar bounce, hsScalar friction) const
{
hsScalar minDist = 1.e33f;
Int32 minIndex = -1;
hsScalar currDist;
int i;
for (i = 0; i < fNumPlanes; i++)
{
currDist = -fWorldPlanes[i].fD - fWorldPlanes[i].fN.InnerProduct(pos);
if (currDist < 0)
return false; // We're not inside this plane, and thus outside the volume
if (currDist < minDist)
{
minDist = currDist;
minIndex = i;
}
}
pos += (-fWorldPlanes[minIndex].fD - fWorldPlanes[minIndex].fN.InnerProduct(pos)) * fWorldPlanes[minIndex].fN;
hsVector3 bnc = -velocity.InnerProduct(fWorldPlanes[minIndex].fN) * fWorldPlanes[minIndex].fN;
velocity += bnc;
velocity *= 1.f - friction;
velocity += bnc * bounce;
// velocity += (velocity.InnerProduct(fWorldPlanes[minIndex].fN) * -(1.f + bounce)) * fWorldPlanes[minIndex].fN;
return true;
}
void plConvexVolume::Read(hsStream* s, hsResMgr *mgr)
{
SetNumPlanesAndClear(s->ReadSwap32());
int i;
for (i = 0; i < fNumPlanes; i++)
{
fLocalPlanes[i].Read(s);
//fFlags[i] = s->ReadSwap32();
}
}
void plConvexVolume::Write(hsStream* s, hsResMgr *mgr)
{
s->WriteSwap32(fNumPlanes);
int i;
for (i = 0; i < fNumPlanes; i++)
{
fLocalPlanes[i].Write(s);
//s->WriteSwap32(fFlags[i]);
}
}

View File

@ -1,87 +1,87 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plConvexVolume_inc
#define plConvexVolume_inc
#include "pnSceneObject/plObjInterface.h"
struct hsPlane3;
struct hsPoint3;
struct hsMatrix44;
class hsResMgr;
// A convex volume defined by several boundary planes
// For now it assumes the user won't add planes that make it concave
class plConvexVolume : public plCreatable
{
public:
plConvexVolume();
~plConvexVolume();
CLASSNAME_REGISTER( plConvexVolume );
GETINTERFACE_ANY( plConvexVolume, plCreatable );
void Update(const hsMatrix44 &l2w);
hsBool AddPlane(const hsPlane3 &plane);
void SetNumPlanesAndClear(const UInt32 num);
void SetPlane(const hsPlane3 &plane, const UInt32 index);
// If you only care about the test, call this. Otherwise call ResolvePoint.
hsBool IsInside(const hsPoint3 &pos) const;
// returns true if the point was inside the volume, and thus moved outward.
hsBool ResolvePoint(hsPoint3 &pos) const;
// returns true if the point was inside and pos and velocity updated to bounce off offending plane.
// input bounce==1.f for perfect bounce, bounce==0 to slide.
hsBool BouncePoint(hsPoint3 &pos, hsVector3 &velocity, hsScalar bounce, hsScalar friction) const;
inline hsBool TestPlane(const hsPoint3 &pos, const hsPlane3 &plane) const; // Is the point inside the plane?
virtual void Read(hsStream* s, hsResMgr *mgr);
virtual void Write(hsStream* s, hsResMgr *mgr);
//virtual hsBool MsgReceive(plMessage* msg);
protected:
void IClear();
hsPlane3 *fLocalPlanes;
hsPlane3 *fWorldPlanes;
UInt32 fNumPlanes;
};
inline hsBool plConvexVolume::TestPlane(const hsPoint3 &pos, const hsPlane3 &plane) const
{
hsScalar dis = plane.fN.InnerProduct(pos);
dis += plane.fD;
if( dis >= 0.f )
return false;
return true;
}
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plConvexVolume_inc
#define plConvexVolume_inc
#include "pnSceneObject/plObjInterface.h"
struct hsPlane3;
struct hsPoint3;
struct hsMatrix44;
class hsResMgr;
// A convex volume defined by several boundary planes
// For now it assumes the user won't add planes that make it concave
class plConvexVolume : public plCreatable
{
public:
plConvexVolume();
~plConvexVolume();
CLASSNAME_REGISTER( plConvexVolume );
GETINTERFACE_ANY( plConvexVolume, plCreatable );
void Update(const hsMatrix44 &l2w);
hsBool AddPlane(const hsPlane3 &plane);
void SetNumPlanesAndClear(const UInt32 num);
void SetPlane(const hsPlane3 &plane, const UInt32 index);
// If you only care about the test, call this. Otherwise call ResolvePoint.
hsBool IsInside(const hsPoint3 &pos) const;
// returns true if the point was inside the volume, and thus moved outward.
hsBool ResolvePoint(hsPoint3 &pos) const;
// returns true if the point was inside and pos and velocity updated to bounce off offending plane.
// input bounce==1.f for perfect bounce, bounce==0 to slide.
hsBool BouncePoint(hsPoint3 &pos, hsVector3 &velocity, hsScalar bounce, hsScalar friction) const;
inline hsBool TestPlane(const hsPoint3 &pos, const hsPlane3 &plane) const; // Is the point inside the plane?
virtual void Read(hsStream* s, hsResMgr *mgr);
virtual void Write(hsStream* s, hsResMgr *mgr);
//virtual hsBool MsgReceive(plMessage* msg);
protected:
void IClear();
hsPlane3 *fLocalPlanes;
hsPlane3 *fWorldPlanes;
UInt32 fNumPlanes;
};
inline hsBool plConvexVolume::TestPlane(const hsPoint3 &pos, const hsPlane3 &plane) const
{
hsScalar dis = plane.fN.InnerProduct(pos);
dis += plane.fD;
if( dis >= 0.f )
return false;
return true;
}
#endif

View File

@ -1,82 +1,82 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plEffectTargetInfo_inc
#define plEffectTargetInfo_inc
#include "hsTypes.h"
struct hsPoint3;
class plPipeline;
class plParticleSystem;
// This is the rendering context passed into an effect to let it cache up
// anything it needs to compute that will be the same for all particles.
// Not a lot of context to go on to begin with, but this will let that
// expand without any interface changes.
class plParticleContext
{
public:
plPipeline* fPipeline;
plParticleSystem* fSystem;
double fSecs;
hsScalar fDelSecs;
};
// This is just a collection of arrays and strides that a plParticleEffect object will reference and modify
// in the course of doing its job.
class plEffectTargetInfo
{
public:
// Byte arrays. Declared as type UInt8 so that adding the stride to the pointer is guaranteed to advance
// the exact number of bytes.
UInt8 *fPos;
UInt8 *fVelocity;
UInt8 *fInvMass;
UInt8 *fAcceleration;
UInt8 *fColor;
UInt8 *fRadsPerSec;
UInt8 *fMiscFlags;
UInt32 fPosStride;
UInt32 fVelocityStride;
UInt32 fInvMassStride;
UInt32 fAccelerationStride;
UInt32 fColorStride;
UInt32 fRadsPerSecStride;
UInt32 fMiscFlagsStride;
plParticleContext fContext;
UInt32 fNumValidParticles;
UInt32 fFirstNewParticle;
// We're going to need some sort of connectivity data for constraint satisfaction, but at least we have
// a system that allows that to be added in smoothly when it's needed, so for now, let's get the main
// goop working.
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plEffectTargetInfo_inc
#define plEffectTargetInfo_inc
#include "hsTypes.h"
struct hsPoint3;
class plPipeline;
class plParticleSystem;
// This is the rendering context passed into an effect to let it cache up
// anything it needs to compute that will be the same for all particles.
// Not a lot of context to go on to begin with, but this will let that
// expand without any interface changes.
class plParticleContext
{
public:
plPipeline* fPipeline;
plParticleSystem* fSystem;
double fSecs;
hsScalar fDelSecs;
};
// This is just a collection of arrays and strides that a plParticleEffect object will reference and modify
// in the course of doing its job.
class plEffectTargetInfo
{
public:
// Byte arrays. Declared as type UInt8 so that adding the stride to the pointer is guaranteed to advance
// the exact number of bytes.
UInt8 *fPos;
UInt8 *fVelocity;
UInt8 *fInvMass;
UInt8 *fAcceleration;
UInt8 *fColor;
UInt8 *fRadsPerSec;
UInt8 *fMiscFlags;
UInt32 fPosStride;
UInt32 fVelocityStride;
UInt32 fInvMassStride;
UInt32 fAccelerationStride;
UInt32 fColorStride;
UInt32 fRadsPerSecStride;
UInt32 fMiscFlagsStride;
plParticleContext fContext;
UInt32 fNumValidParticles;
UInt32 fFirstNewParticle;
// We're going to need some sort of connectivity data for constraint satisfaction, but at least we have
// a system that allows that to be added in smoothly when it's needed, so for now, let's get the main
// goop working.
};
#endif

View File

@ -1,98 +1,98 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticle_inc
#define plParticle_inc
#include "hsGeometry3.h"
#include "hsColorRGBA.h"
// The meat of the particle. These classes, in combination with the plParticleEmitter that spawned it,
// should contain everything specific to a particle, necessary to build a renderable poly to represent a
// particular particle. (The emitter is necessary for properties (like texture) that are common among all
// particles that originated from the same emitter.
// For any reference in this object to a particle's poly vertices, the structure is as follows:
/*
|---| "HSize"
V3-----V2 -
| / | | "VSize"
| / | |
| P | -
| / |
| / | ("P" is the current position of the particle)
V0-----V1
So the vertices are arranged counter-clockwise, starting in the lower-left corner. Order all other attributes
accordingly.
*/
// The class plParticleCore should ONLY contain data necessary for the Drawable to create renderable polys
// Everything else goes into plParticleExt.
// plParticleEmitter is depending on the order that member variables appear in these classes, so
// DON'T MODIFY THEM WITHOUT MAKING SURE THE CONSTRUCTOR TO plParticleEmitter PROPERLY COMPUTES
// BASE ADDRESSES AND STRIDES!
// No initialization on construct. In nearly all cases, a default value won't be appropriate
// so there's no sense doing extra memory writes
class plParticleCore
{
public:
hsPoint3 fPos;
UInt32 fColor; // Particle opacity goes into the color's alpha.
hsPoint3 fOrientation; // fMiscFlags determines how this should be used.
hsVector3 fNormal;
hsScalar fHSize, fVSize; // distance from the heart of the particle to the borders of its poly.
hsPoint3 fUVCoords[4];
};
class plParticleExt
{
public:
//hsPoint3 fOldPos;
hsVector3 fVelocity;
hsScalar fInvMass; // The inverse (1 / mass) is what we actually need for calculations. Storing it this
// way allows us to make an object immovable with an inverse mass of 0 (and save a divide).
hsVector3 fAcceleration; // Accumulated from multiple forces.
hsScalar fLife; // how many seconds before we recycle this? (My particle has more of a life than I do...)
hsScalar fStartLife;
hsScalar fScale;
hsScalar fRadsPerSec;
//UInt32 fOrigColor;
enum // Miscellaneous flags for particles
{
kImmortal = 0x00000001,
};
UInt32 fMiscFlags; // I know... 32 bits for a single flag...
// Feel free to change this if you've got something to pack it against.
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticle_inc
#define plParticle_inc
#include "hsGeometry3.h"
#include "hsColorRGBA.h"
// The meat of the particle. These classes, in combination with the plParticleEmitter that spawned it,
// should contain everything specific to a particle, necessary to build a renderable poly to represent a
// particular particle. (The emitter is necessary for properties (like texture) that are common among all
// particles that originated from the same emitter.
// For any reference in this object to a particle's poly vertices, the structure is as follows:
/*
|---| "HSize"
V3-----V2 -
| / | | "VSize"
| / | |
| P | -
| / |
| / | ("P" is the current position of the particle)
V0-----V1
So the vertices are arranged counter-clockwise, starting in the lower-left corner. Order all other attributes
accordingly.
*/
// The class plParticleCore should ONLY contain data necessary for the Drawable to create renderable polys
// Everything else goes into plParticleExt.
// plParticleEmitter is depending on the order that member variables appear in these classes, so
// DON'T MODIFY THEM WITHOUT MAKING SURE THE CONSTRUCTOR TO plParticleEmitter PROPERLY COMPUTES
// BASE ADDRESSES AND STRIDES!
// No initialization on construct. In nearly all cases, a default value won't be appropriate
// so there's no sense doing extra memory writes
class plParticleCore
{
public:
hsPoint3 fPos;
UInt32 fColor; // Particle opacity goes into the color's alpha.
hsPoint3 fOrientation; // fMiscFlags determines how this should be used.
hsVector3 fNormal;
hsScalar fHSize, fVSize; // distance from the heart of the particle to the borders of its poly.
hsPoint3 fUVCoords[4];
};
class plParticleExt
{
public:
//hsPoint3 fOldPos;
hsVector3 fVelocity;
hsScalar fInvMass; // The inverse (1 / mass) is what we actually need for calculations. Storing it this
// way allows us to make an object immovable with an inverse mass of 0 (and save a divide).
hsVector3 fAcceleration; // Accumulated from multiple forces.
hsScalar fLife; // how many seconds before we recycle this? (My particle has more of a life than I do...)
hsScalar fStartLife;
hsScalar fScale;
hsScalar fRadsPerSec;
//UInt32 fOrigColor;
enum // Miscellaneous flags for particles
{
kImmortal = 0x00000001,
};
UInt32 fMiscFlags; // I know... 32 bits for a single flag...
// Feel free to change this if you've got something to pack it against.
};
#endif

View File

@ -1,119 +1,119 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plParticleSystem.h"
#include "plParticleGenerator.h"
#include "plParticleApplicator.h"
#include "plAvatar/plScalarChannel.h"
#include "plAvatar/plAGModifier.h"
#include "plMessage/plParticleUpdateMsg.h"
#include "pnSceneObject/plSceneObject.h"
#define PI 3.14159
plParticleGenerator *plParticleApplicator::IGetParticleGen(plSceneObject *so)
{
UInt32 numMods = so->GetNumModifiers();
int i;
for (i = 0; i < numMods; i++)
{
const plParticleSystem *result = plParticleSystem::ConvertNoRef(so->GetModifier(i));
if (result != nil)
return result->GetExportedGenerator();
}
return nil;
}
void plParticleLifeMinApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamPartLifeMin,
chan->Value(time));
}
void plParticleLifeMaxApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamPartLifeMax,
chan->Value(time));
}
void plParticlePPSApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamParticlesPerSecond,
chan->Value(time));
}
void plParticleAngleApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamInitPitchRange,
(hsScalar)(chan->Value(time) * PI / 180.f));
}
void plParticleVelMinApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamVelMin,
chan->Value(time));
}
void plParticleVelMaxApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamVelMax,
chan->Value(time));
}
void plParticleScaleMinApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamScaleMin,
chan->Value(time) / 100.f);
}
void plParticleScaleMaxApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamScaleMax,
chan->Value(time) / 100.f);
}
void plParticleGravityApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
// IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamParticlesPerSecond,
// chan->Value(time));
}
void plParticleDragApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
// IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamParticlesPerSecond,
// chan->Value(time));
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plParticleSystem.h"
#include "plParticleGenerator.h"
#include "plParticleApplicator.h"
#include "plAvatar/plScalarChannel.h"
#include "plAvatar/plAGModifier.h"
#include "plMessage/plParticleUpdateMsg.h"
#include "pnSceneObject/plSceneObject.h"
#define PI 3.14159
plParticleGenerator *plParticleApplicator::IGetParticleGen(plSceneObject *so)
{
UInt32 numMods = so->GetNumModifiers();
int i;
for (i = 0; i < numMods; i++)
{
const plParticleSystem *result = plParticleSystem::ConvertNoRef(so->GetModifier(i));
if (result != nil)
return result->GetExportedGenerator();
}
return nil;
}
void plParticleLifeMinApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamPartLifeMin,
chan->Value(time));
}
void plParticleLifeMaxApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamPartLifeMax,
chan->Value(time));
}
void plParticlePPSApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamParticlesPerSecond,
chan->Value(time));
}
void plParticleAngleApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamInitPitchRange,
(hsScalar)(chan->Value(time) * PI / 180.f));
}
void plParticleVelMinApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamVelMin,
chan->Value(time));
}
void plParticleVelMaxApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamVelMax,
chan->Value(time));
}
void plParticleScaleMinApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamScaleMin,
chan->Value(time) / 100.f);
}
void plParticleScaleMaxApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamScaleMax,
chan->Value(time) / 100.f);
}
void plParticleGravityApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
// IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamParticlesPerSecond,
// chan->Value(time));
}
void plParticleDragApplicator::IApply(const plAGModifier *mod, double time)
{
plScalarChannel *chan = plScalarChannel::ConvertNoRef(fChannel);
// IGetParticleGen(mod->GetTarget(0))->UpdateParam(plParticleUpdateMsg::kParamParticlesPerSecond,
// chan->Value(time));
}

View File

@ -1,145 +1,145 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLPARTICLEAPPLICATOR_INC
#define PLPARTICLEAPPLICATOR_INC
#include "plAvatar/plAGChannel.h"
#include "plAvatar/plAGApplicator.h"
class plParticleSystem;
class plParticleApplicator : public plAGApplicator
{
protected:
plParticleGenerator *IGetParticleGen(plSceneObject *so);
virtual void IApply(const plAGModifier *mod, double time) = 0;
public:
CLASSNAME_REGISTER( plParticleApplicator );
GETINTERFACE_ANY( plParticleApplicator, plAGApplicator );
};
class plParticleLifeMinApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleLifeMinApplicator );
GETINTERFACE_ANY( plParticleLifeMinApplicator, plAGApplicator );
};
class plParticleLifeMaxApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleLifeMaxApplicator );
GETINTERFACE_ANY( plParticleLifeMaxApplicator, plAGApplicator );
};
class plParticlePPSApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticlePPSApplicator );
GETINTERFACE_ANY( plParticlePPSApplicator, plAGApplicator );
};
class plParticleAngleApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleAngleApplicator );
GETINTERFACE_ANY( plParticleAngleApplicator, plAGApplicator );
};
class plParticleVelMinApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleVelMinApplicator );
GETINTERFACE_ANY( plParticleVelMinApplicator, plAGApplicator );
};
class plParticleVelMaxApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleVelMaxApplicator );
GETINTERFACE_ANY( plParticleVelMaxApplicator, plAGApplicator );
};
class plParticleScaleMinApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleScaleMinApplicator );
GETINTERFACE_ANY( plParticleScaleMinApplicator, plAGApplicator );
};
class plParticleScaleMaxApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleScaleMaxApplicator );
GETINTERFACE_ANY( plParticleScaleMaxApplicator, plAGApplicator );
};
class plParticleGravityApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleGravityApplicator );
GETINTERFACE_ANY( plParticleGravityApplicator, plAGApplicator );
};
class plParticleDragApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleDragApplicator );
GETINTERFACE_ANY( plParticleDragApplicator, plAGApplicator );
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLPARTICLEAPPLICATOR_INC
#define PLPARTICLEAPPLICATOR_INC
#include "plAvatar/plAGChannel.h"
#include "plAvatar/plAGApplicator.h"
class plParticleSystem;
class plParticleApplicator : public plAGApplicator
{
protected:
plParticleGenerator *IGetParticleGen(plSceneObject *so);
virtual void IApply(const plAGModifier *mod, double time) = 0;
public:
CLASSNAME_REGISTER( plParticleApplicator );
GETINTERFACE_ANY( plParticleApplicator, plAGApplicator );
};
class plParticleLifeMinApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleLifeMinApplicator );
GETINTERFACE_ANY( plParticleLifeMinApplicator, plAGApplicator );
};
class plParticleLifeMaxApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleLifeMaxApplicator );
GETINTERFACE_ANY( plParticleLifeMaxApplicator, plAGApplicator );
};
class plParticlePPSApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticlePPSApplicator );
GETINTERFACE_ANY( plParticlePPSApplicator, plAGApplicator );
};
class plParticleAngleApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleAngleApplicator );
GETINTERFACE_ANY( plParticleAngleApplicator, plAGApplicator );
};
class plParticleVelMinApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleVelMinApplicator );
GETINTERFACE_ANY( plParticleVelMinApplicator, plAGApplicator );
};
class plParticleVelMaxApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleVelMaxApplicator );
GETINTERFACE_ANY( plParticleVelMaxApplicator, plAGApplicator );
};
class plParticleScaleMinApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleScaleMinApplicator );
GETINTERFACE_ANY( plParticleScaleMinApplicator, plAGApplicator );
};
class plParticleScaleMaxApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleScaleMaxApplicator );
GETINTERFACE_ANY( plParticleScaleMaxApplicator, plAGApplicator );
};
class plParticleGravityApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleGravityApplicator );
GETINTERFACE_ANY( plParticleGravityApplicator, plAGApplicator );
};
class plParticleDragApplicator : public plParticleApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plParticleDragApplicator );
GETINTERFACE_ANY( plParticleDragApplicator, plAGApplicator );
};
#endif

View File

@ -1,73 +1,73 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleCreatable_inc
#define plParticleCreatable_inc
#include "pnFactory/plCreator.h"
#include "plParticleSystem.h"
#include "plParticleEffect.h"
#include "plParticleEmitter.h"
#include "plParticleGenerator.h"
#include "plParticleSystem.h"
#include "plParticleApplicator.h"
#include "plParticleSDLMod.h"
#include "plConvexVolume.h"
#include "plBoundInterface.h"
REGISTER_CREATABLE( plParticleSystem );
REGISTER_NONCREATABLE( plParticleEffect );
REGISTER_NONCREATABLE( plParticleCollisionEffect );
REGISTER_CREATABLE( plParticleCollisionEffectBeat );
REGISTER_CREATABLE( plParticleCollisionEffectDie );
REGISTER_CREATABLE( plParticleCollisionEffectBounce );
REGISTER_CREATABLE( plParticleFadeVolumeEffect );
REGISTER_NONCREATABLE( plParticleGenerator );
REGISTER_CREATABLE( plSimpleParticleGenerator );
REGISTER_CREATABLE( plOneTimeParticleGenerator );
REGISTER_CREATABLE( plParticleEmitter );
REGISTER_CREATABLE( plConvexVolume );
REGISTER_CREATABLE( plBoundInterface );
REGISTER_NONCREATABLE( plParticleApplicator );
REGISTER_CREATABLE( plParticleLifeMinApplicator );
REGISTER_CREATABLE( plParticleLifeMaxApplicator );
REGISTER_CREATABLE( plParticlePPSApplicator );
REGISTER_CREATABLE( plParticleAngleApplicator );
REGISTER_CREATABLE( plParticleVelMinApplicator );
REGISTER_CREATABLE( plParticleVelMaxApplicator );
REGISTER_CREATABLE( plParticleScaleMinApplicator );
REGISTER_CREATABLE( plParticleScaleMaxApplicator );
//REGISTER_CREATABLE( plParticleGravityApplicator );
//REGISTER_CREATABLE( plParticleDragApplicator );
REGISTER_NONCREATABLE( plParticleWindEffect );
REGISTER_CREATABLE( plParticleLocalWind );
REGISTER_CREATABLE( plParticleUniformWind );
REGISTER_CREATABLE( plParticleFlockEffect );
REGISTER_CREATABLE( plParticleFollowSystemEffect );
REGISTER_CREATABLE( plParticleSDLMod );
#endif // plParticleCreatable_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleCreatable_inc
#define plParticleCreatable_inc
#include "pnFactory/plCreator.h"
#include "plParticleSystem.h"
#include "plParticleEffect.h"
#include "plParticleEmitter.h"
#include "plParticleGenerator.h"
#include "plParticleSystem.h"
#include "plParticleApplicator.h"
#include "plParticleSDLMod.h"
#include "plConvexVolume.h"
#include "plBoundInterface.h"
REGISTER_CREATABLE( plParticleSystem );
REGISTER_NONCREATABLE( plParticleEffect );
REGISTER_NONCREATABLE( plParticleCollisionEffect );
REGISTER_CREATABLE( plParticleCollisionEffectBeat );
REGISTER_CREATABLE( plParticleCollisionEffectDie );
REGISTER_CREATABLE( plParticleCollisionEffectBounce );
REGISTER_CREATABLE( plParticleFadeVolumeEffect );
REGISTER_NONCREATABLE( plParticleGenerator );
REGISTER_CREATABLE( plSimpleParticleGenerator );
REGISTER_CREATABLE( plOneTimeParticleGenerator );
REGISTER_CREATABLE( plParticleEmitter );
REGISTER_CREATABLE( plConvexVolume );
REGISTER_CREATABLE( plBoundInterface );
REGISTER_NONCREATABLE( plParticleApplicator );
REGISTER_CREATABLE( plParticleLifeMinApplicator );
REGISTER_CREATABLE( plParticleLifeMaxApplicator );
REGISTER_CREATABLE( plParticlePPSApplicator );
REGISTER_CREATABLE( plParticleAngleApplicator );
REGISTER_CREATABLE( plParticleVelMinApplicator );
REGISTER_CREATABLE( plParticleVelMaxApplicator );
REGISTER_CREATABLE( plParticleScaleMinApplicator );
REGISTER_CREATABLE( plParticleScaleMaxApplicator );
//REGISTER_CREATABLE( plParticleGravityApplicator );
//REGISTER_CREATABLE( plParticleDragApplicator );
REGISTER_NONCREATABLE( plParticleWindEffect );
REGISTER_CREATABLE( plParticleLocalWind );
REGISTER_CREATABLE( plParticleUniformWind );
REGISTER_CREATABLE( plParticleFlockEffect );
REGISTER_CREATABLE( plParticleFollowSystemEffect );
REGISTER_CREATABLE( plParticleSDLMod );
#endif // plParticleCreatable_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,340 +1,340 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleEffect_inc
#define plParticleEffect_inc
#include "pnKeyedObject/hsKeyedObject.h"
#include "hsMatrix44.h"
class plEffectTargetInfo;
class plConvexVolume;
class hsResMgr;
class plSceneObject;
class plParticleEffect : public hsKeyedObject
{
public:
CLASSNAME_REGISTER( plParticleEffect );
GETINTERFACE_ANY( plParticleEffect, hsKeyedObject );
// Order is:
// PrepareEffect is called with a given target (including valid
// ParticleContext).
// ApplyEffect is called some once for each particle (maybe zero times).
// It can return true to kill a particle.
// Target and Context passed in with Prepare will be
// guaranteed to remain valid until,
// EndEffect marks no more particles will be processed with the above
// context (invalidating anything cached).
// Defaults for Prepare and End are no-ops.
virtual void PrepareEffect(const plEffectTargetInfo& target) {}
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i) = 0;
virtual void EndEffect(const plEffectTargetInfo& target) {}
};
class plParticleCollisionEffect : public plParticleEffect
{
public:
plParticleCollisionEffect();
~plParticleCollisionEffect();
CLASSNAME_REGISTER( plParticleCollisionEffect );
GETINTERFACE_ANY( plParticleCollisionEffect, plParticleEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
virtual hsBool MsgReceive(plMessage *msg);
protected:
plSceneObject *fSceneObj;
plConvexVolume *fBounds;
};
// Default particle blocker. Doesn't affect particle's velocity,
// so it'll keep "beat"ing on the deflector until the velocity
// dotted with the deflector normal slides it off an edge.
class plParticleCollisionEffectBeat : public plParticleCollisionEffect
{
public:
plParticleCollisionEffectBeat();
CLASSNAME_REGISTER( plParticleCollisionEffectBeat );
GETINTERFACE_ANY( plParticleCollisionEffectBeat, plParticleCollisionEffect );
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
};
// This particle blocker just kills any particles that hit it.
class plParticleCollisionEffectDie : public plParticleCollisionEffect
{
public:
plParticleCollisionEffectDie();
CLASSNAME_REGISTER( plParticleCollisionEffectDie );
GETINTERFACE_ANY( plParticleCollisionEffectDie, plParticleCollisionEffect );
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
};
class plParticleCollisionEffectBounce : public plParticleCollisionEffect
{
protected:
hsScalar fBounce;
hsScalar fFriction;
public:
plParticleCollisionEffectBounce();
CLASSNAME_REGISTER( plParticleCollisionEffectBounce );
GETINTERFACE_ANY( plParticleCollisionEffectBounce, plParticleCollisionEffect );
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
void SetBounce(hsScalar b) { fBounce = b; }
hsScalar GetBounce() const { return fBounce; }
void SetFriction(hsScalar f) { fFriction = f; }
hsScalar GetFriction() const { return fFriction; }
};
class plParticleFadeVolumeEffect : public plParticleEffect
{
protected:
// Some cached properties. These will be the same for all
// particles between matching PrepareEffect and EndEffect calls.
hsPoint3 fMax;
hsPoint3 fMin;
hsPoint3 fNorm;
public:
plParticleFadeVolumeEffect();
~plParticleFadeVolumeEffect();
CLASSNAME_REGISTER( plParticleFadeVolumeEffect );
GETINTERFACE_ANY( plParticleFadeVolumeEffect, plParticleEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
//virtual hsBool MsgReceive(plMessage *msg);
hsScalar fLength;
hsBool fIgnoreZ;
};
class plParticleWindEffect : public plParticleEffect
{
protected:
// The properties that define the wind. These might/should be animatable.
hsScalar fStrength;
hsScalar fConstancy;
hsScalar fSwirl;
hsBool fHorizontal;
hsVector3 fRefDir;
// Some cached properties. These will be the same for all
// particles between matching PrepareEffect and EndEffect calls.
// These define the current state of the wind.
hsVector3 fWindVec;
hsVector3 fRandDir;
hsVector3 fDir;
double fLastDirSecs;
public:
plParticleWindEffect();
~plParticleWindEffect();
CLASSNAME_REGISTER( plParticleWindEffect );
GETINTERFACE_ANY( plParticleWindEffect, plParticleEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i) = 0;
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
void SetStrength(hsScalar v) { fStrength = v; }
hsScalar GetStrength() const { return fStrength; }
void SetConstancy(hsScalar c) { fConstancy = c; }
hsScalar GetConstancy() const { return fConstancy; }
void SetSwirl(hsScalar s) { fSwirl = s; }
hsScalar GetSwirl() const { return fSwirl; }
void SetHorizontal(hsBool on) { fHorizontal = on; }
hsBool GetHorizontal() const { return fHorizontal; }
void SetRefDirection(const hsVector3& v);
const hsVector3& GetRefDirection() const { return fRefDir; }
};
class plParticleLocalWind : public plParticleWindEffect
{
protected:
hsVector3 fScale;
hsScalar fSpeed;
hsVector3 fPhase;
hsVector3 fInvScale;
double fLastPhaseSecs;
public:
plParticleLocalWind();
~plParticleLocalWind();
CLASSNAME_REGISTER( plParticleLocalWind );
GETINTERFACE_ANY( plParticleLocalWind, plParticleWindEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
void SetScale(const hsVector3& v) { fScale = v; }
const hsVector3& GetScale() const { return fScale; }
void SetSpeed(hsScalar v) { fSpeed = v; }
hsScalar GetSpeed() const { return fSpeed; }
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
};
class plParticleUniformWind : public plParticleWindEffect
{
protected:
hsScalar fFreqMin;
hsScalar fFreqMax;
hsScalar fFreqCurr;
hsScalar fFreqRate;
double fCurrPhase;
double fLastFreqSecs;
hsScalar fCurrentStrength;
public:
plParticleUniformWind();
~plParticleUniformWind();
CLASSNAME_REGISTER( plParticleUniformWind );
GETINTERFACE_ANY( plParticleUniformWind, plParticleWindEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
void SetFrequencyRange(hsScalar minSecsPerCycle, hsScalar maxSecsPerCycle);
void SetFrequencyRate(hsScalar secsPerCycle);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
};
class plParticleInfluenceInfo
{
public:
hsVector3 fAvgVel;
hsVector3 fRepDir;
};
class plParticleFlockEffect : public plParticleEffect
{
//protected:
protected:
hsPoint3 fTargetOffset; // Worldspace offset from our target to get the true goal
hsPoint3 fDissenterTarget; // Where to particles go when they get scared and leave us?
hsScalar fInfAvgRadSq; // Square of the radius of influence for average velocity matching.
hsScalar fInfRepRadSq; // Same, for repelling from neighbors.
hsScalar fAvgVelStr; // How strongly are we influenced by average dir?
hsScalar fRepDirStr; // Same for repelling
hsScalar fGoalOrbitStr; // Same for the goal (when we're within the desired distance)
hsScalar fGoalChaseStr; // Same for the goal (when we're too far away, and chasing it)
hsScalar fGoalDistSq;
hsScalar fFullChaseDistSq;
hsScalar fMaxOrbitSpeed;
hsScalar fMaxChaseSpeed;
UInt16 fMaxParticles;
hsScalar *fDistSq; // Table of distances from particle to particle
plParticleInfluenceInfo *fInfluences;
void IUpdateDistances(const plEffectTargetInfo &target);
void IUpdateInfluences(const plEffectTargetInfo &target);
public:
plParticleFlockEffect();
~plParticleFlockEffect();
CLASSNAME_REGISTER( plParticleFlockEffect );
GETINTERFACE_ANY( plParticleFlockEffect, plParticleEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
void SetTargetOffset(const hsPoint3 &offset) { fTargetOffset = offset; }
void SetDissenterTarget(const hsPoint3 &target) { fDissenterTarget = target; }
void SetInfluenceAvgRadius(hsScalar val) { fInfAvgRadSq = val * val; }
void SetInfluenceRepelRadius(hsScalar val) { fInfRepRadSq = val * val; }
void SetGoalRadius(hsScalar val) { fGoalDistSq = val * val; }
void SetFullChaseRadius(hsScalar val) { fFullChaseDistSq = val * val; }
void SetConformStr(hsScalar val) { fAvgVelStr = val; }
void SetRepelStr(hsScalar val) { fRepDirStr = val; }
void SetGoalOrbitStr(hsScalar val) { fGoalOrbitStr = val; }
void SetGoalChaseStr(hsScalar val) { fGoalChaseStr = val; }
void SetMaxOrbitSpeed(hsScalar val) { fMaxOrbitSpeed = val; }
void SetMaxChaseSpeed(hsScalar val) { fMaxChaseSpeed = val; }
void SetMaxParticles(UInt16 num);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
virtual hsBool MsgReceive(plMessage *msg);
};
class plParticleFollowSystemEffect : public plParticleEffect
{
public:
CLASSNAME_REGISTER( plParticleFollowSystemEffect );
GETINTERFACE_ANY( plParticleFollowSystemEffect, plParticleEffect );
plParticleFollowSystemEffect();
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
virtual void EndEffect(const plEffectTargetInfo& target);
protected:
hsMatrix44 fOldW2L;
hsBool fEvalThisFrame;
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleEffect_inc
#define plParticleEffect_inc
#include "pnKeyedObject/hsKeyedObject.h"
#include "hsMatrix44.h"
class plEffectTargetInfo;
class plConvexVolume;
class hsResMgr;
class plSceneObject;
class plParticleEffect : public hsKeyedObject
{
public:
CLASSNAME_REGISTER( plParticleEffect );
GETINTERFACE_ANY( plParticleEffect, hsKeyedObject );
// Order is:
// PrepareEffect is called with a given target (including valid
// ParticleContext).
// ApplyEffect is called some once for each particle (maybe zero times).
// It can return true to kill a particle.
// Target and Context passed in with Prepare will be
// guaranteed to remain valid until,
// EndEffect marks no more particles will be processed with the above
// context (invalidating anything cached).
// Defaults for Prepare and End are no-ops.
virtual void PrepareEffect(const plEffectTargetInfo& target) {}
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i) = 0;
virtual void EndEffect(const plEffectTargetInfo& target) {}
};
class plParticleCollisionEffect : public plParticleEffect
{
public:
plParticleCollisionEffect();
~plParticleCollisionEffect();
CLASSNAME_REGISTER( plParticleCollisionEffect );
GETINTERFACE_ANY( plParticleCollisionEffect, plParticleEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
virtual hsBool MsgReceive(plMessage *msg);
protected:
plSceneObject *fSceneObj;
plConvexVolume *fBounds;
};
// Default particle blocker. Doesn't affect particle's velocity,
// so it'll keep "beat"ing on the deflector until the velocity
// dotted with the deflector normal slides it off an edge.
class plParticleCollisionEffectBeat : public plParticleCollisionEffect
{
public:
plParticleCollisionEffectBeat();
CLASSNAME_REGISTER( plParticleCollisionEffectBeat );
GETINTERFACE_ANY( plParticleCollisionEffectBeat, plParticleCollisionEffect );
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
};
// This particle blocker just kills any particles that hit it.
class plParticleCollisionEffectDie : public plParticleCollisionEffect
{
public:
plParticleCollisionEffectDie();
CLASSNAME_REGISTER( plParticleCollisionEffectDie );
GETINTERFACE_ANY( plParticleCollisionEffectDie, plParticleCollisionEffect );
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
};
class plParticleCollisionEffectBounce : public plParticleCollisionEffect
{
protected:
hsScalar fBounce;
hsScalar fFriction;
public:
plParticleCollisionEffectBounce();
CLASSNAME_REGISTER( plParticleCollisionEffectBounce );
GETINTERFACE_ANY( plParticleCollisionEffectBounce, plParticleCollisionEffect );
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
void SetBounce(hsScalar b) { fBounce = b; }
hsScalar GetBounce() const { return fBounce; }
void SetFriction(hsScalar f) { fFriction = f; }
hsScalar GetFriction() const { return fFriction; }
};
class plParticleFadeVolumeEffect : public plParticleEffect
{
protected:
// Some cached properties. These will be the same for all
// particles between matching PrepareEffect and EndEffect calls.
hsPoint3 fMax;
hsPoint3 fMin;
hsPoint3 fNorm;
public:
plParticleFadeVolumeEffect();
~plParticleFadeVolumeEffect();
CLASSNAME_REGISTER( plParticleFadeVolumeEffect );
GETINTERFACE_ANY( plParticleFadeVolumeEffect, plParticleEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
//virtual hsBool MsgReceive(plMessage *msg);
hsScalar fLength;
hsBool fIgnoreZ;
};
class plParticleWindEffect : public plParticleEffect
{
protected:
// The properties that define the wind. These might/should be animatable.
hsScalar fStrength;
hsScalar fConstancy;
hsScalar fSwirl;
hsBool fHorizontal;
hsVector3 fRefDir;
// Some cached properties. These will be the same for all
// particles between matching PrepareEffect and EndEffect calls.
// These define the current state of the wind.
hsVector3 fWindVec;
hsVector3 fRandDir;
hsVector3 fDir;
double fLastDirSecs;
public:
plParticleWindEffect();
~plParticleWindEffect();
CLASSNAME_REGISTER( plParticleWindEffect );
GETINTERFACE_ANY( plParticleWindEffect, plParticleEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i) = 0;
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
void SetStrength(hsScalar v) { fStrength = v; }
hsScalar GetStrength() const { return fStrength; }
void SetConstancy(hsScalar c) { fConstancy = c; }
hsScalar GetConstancy() const { return fConstancy; }
void SetSwirl(hsScalar s) { fSwirl = s; }
hsScalar GetSwirl() const { return fSwirl; }
void SetHorizontal(hsBool on) { fHorizontal = on; }
hsBool GetHorizontal() const { return fHorizontal; }
void SetRefDirection(const hsVector3& v);
const hsVector3& GetRefDirection() const { return fRefDir; }
};
class plParticleLocalWind : public plParticleWindEffect
{
protected:
hsVector3 fScale;
hsScalar fSpeed;
hsVector3 fPhase;
hsVector3 fInvScale;
double fLastPhaseSecs;
public:
plParticleLocalWind();
~plParticleLocalWind();
CLASSNAME_REGISTER( plParticleLocalWind );
GETINTERFACE_ANY( plParticleLocalWind, plParticleWindEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
void SetScale(const hsVector3& v) { fScale = v; }
const hsVector3& GetScale() const { return fScale; }
void SetSpeed(hsScalar v) { fSpeed = v; }
hsScalar GetSpeed() const { return fSpeed; }
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
};
class plParticleUniformWind : public plParticleWindEffect
{
protected:
hsScalar fFreqMin;
hsScalar fFreqMax;
hsScalar fFreqCurr;
hsScalar fFreqRate;
double fCurrPhase;
double fLastFreqSecs;
hsScalar fCurrentStrength;
public:
plParticleUniformWind();
~plParticleUniformWind();
CLASSNAME_REGISTER( plParticleUniformWind );
GETINTERFACE_ANY( plParticleUniformWind, plParticleWindEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
void SetFrequencyRange(hsScalar minSecsPerCycle, hsScalar maxSecsPerCycle);
void SetFrequencyRate(hsScalar secsPerCycle);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
};
class plParticleInfluenceInfo
{
public:
hsVector3 fAvgVel;
hsVector3 fRepDir;
};
class plParticleFlockEffect : public plParticleEffect
{
//protected:
protected:
hsPoint3 fTargetOffset; // Worldspace offset from our target to get the true goal
hsPoint3 fDissenterTarget; // Where to particles go when they get scared and leave us?
hsScalar fInfAvgRadSq; // Square of the radius of influence for average velocity matching.
hsScalar fInfRepRadSq; // Same, for repelling from neighbors.
hsScalar fAvgVelStr; // How strongly are we influenced by average dir?
hsScalar fRepDirStr; // Same for repelling
hsScalar fGoalOrbitStr; // Same for the goal (when we're within the desired distance)
hsScalar fGoalChaseStr; // Same for the goal (when we're too far away, and chasing it)
hsScalar fGoalDistSq;
hsScalar fFullChaseDistSq;
hsScalar fMaxOrbitSpeed;
hsScalar fMaxChaseSpeed;
UInt16 fMaxParticles;
hsScalar *fDistSq; // Table of distances from particle to particle
plParticleInfluenceInfo *fInfluences;
void IUpdateDistances(const plEffectTargetInfo &target);
void IUpdateInfluences(const plEffectTargetInfo &target);
public:
plParticleFlockEffect();
~plParticleFlockEffect();
CLASSNAME_REGISTER( plParticleFlockEffect );
GETINTERFACE_ANY( plParticleFlockEffect, plParticleEffect );
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
void SetTargetOffset(const hsPoint3 &offset) { fTargetOffset = offset; }
void SetDissenterTarget(const hsPoint3 &target) { fDissenterTarget = target; }
void SetInfluenceAvgRadius(hsScalar val) { fInfAvgRadSq = val * val; }
void SetInfluenceRepelRadius(hsScalar val) { fInfRepRadSq = val * val; }
void SetGoalRadius(hsScalar val) { fGoalDistSq = val * val; }
void SetFullChaseRadius(hsScalar val) { fFullChaseDistSq = val * val; }
void SetConformStr(hsScalar val) { fAvgVelStr = val; }
void SetRepelStr(hsScalar val) { fRepDirStr = val; }
void SetGoalOrbitStr(hsScalar val) { fGoalOrbitStr = val; }
void SetGoalChaseStr(hsScalar val) { fGoalChaseStr = val; }
void SetMaxOrbitSpeed(hsScalar val) { fMaxOrbitSpeed = val; }
void SetMaxChaseSpeed(hsScalar val) { fMaxChaseSpeed = val; }
void SetMaxParticles(UInt16 num);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
virtual hsBool MsgReceive(plMessage *msg);
};
class plParticleFollowSystemEffect : public plParticleEffect
{
public:
CLASSNAME_REGISTER( plParticleFollowSystemEffect );
GETINTERFACE_ANY( plParticleFollowSystemEffect, plParticleEffect );
plParticleFollowSystemEffect();
virtual void PrepareEffect(const plEffectTargetInfo& target);
virtual hsBool ApplyEffect(const plEffectTargetInfo& target, Int32 i);
virtual void EndEffect(const plEffectTargetInfo& target);
protected:
hsMatrix44 fOldW2L;
hsBool fEvalThisFrame;
};
#endif

View File

@ -1,143 +1,143 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleEmitter_inc
#define plParticleEmitter_inc
#include "hsGeometry3.h"
#include "hsBounds.h"
#include "pnNetCommon/plSynchedValue.h"
#include "hsColorRGBA.h"
class hsBounds3Ext;
class plParticleSystem;
class plParticleCore;
class plParticleExt;
class plParticleGenerator;
class plSimpleParticleGenerator;
class hsResMgr;
#include "plEffectTargetInfo.h"
// This just holds a bunch of parameters for an emission location. A particle system can have several of these
class plParticleEmitter : public plCreatable
{
friend plParticleSystem;
friend plSimpleParticleGenerator;
public:
plParticleEmitter();
~plParticleEmitter();
void Init(plParticleSystem *system, UInt32 maxParticles, UInt32 spanIndex, UInt32 miscFlags,
plParticleGenerator *gen = nil);
void Clone(plParticleEmitter* src, UInt32 spanIndex);
plParticleCore *GetParticleArray() const { return fParticleCores; }
UInt32 GetParticleCount() const { return fNumValidParticles; }
UInt32 GetNumTiles() const;
const hsBounds3Ext &GetBoundingBox() const { return fBoundBox; }
UInt32 GetSpanIndex() const { return fSpanIndex; }
const hsMatrix44 &GetLocalToWorld() const;
void AddParticle(hsPoint3 &pos, hsVector3 &velocity, UInt32 tileIndex,
hsScalar hSize, hsScalar vSize, hsScalar scale, hsScalar invMass, hsScalar life,
hsPoint3 &orientation, UInt32 miscFlags, hsScalar radsPerSec=0);
void WipeExistingParticles();
void KillParticles(hsScalar num, hsScalar timeToDie, UInt8 flags);
UInt16 StealParticlesFrom(plParticleEmitter *victim, UInt16 num); // returns the number actually stolen
void TranslateAllParticles(hsPoint3 &amount); // Used to recenter the system when linking between ages.
void UpdateGenerator(UInt32 paramID, hsScalar paramValue);
static UInt32 CreateHexColor(const hsColorRGBA &color);
static UInt32 CreateHexColor(const hsScalar r, const hsScalar g, const hsScalar b, const hsScalar a);
void OverrideLocalToWorld(const hsMatrix44& l2w);
void UnOverrideLocalToWorld() { fMiscFlags &= ~kOverrideLocalToWorld; }
hsBool LocalToWorldOverridden() const { return 0 != (fMiscFlags & kOverrideLocalToWorld); }
void SetTimeToLive(hsScalar dt) { fTimeToLive = dt; }
hsScalar GetTimeToLive() const { return fTimeToLive; } // 0 time to live is never turn off.
CLASSNAME_REGISTER( plParticleEmitter );
GETINTERFACE_ANY( plParticleEmitter, plCreatable);
virtual void Read(hsStream* s, hsResMgr *mgr);
virtual void Write(hsStream* s, hsResMgr *mgr);
enum // Miscellaneous flags
{
kMatIsEmissive = 0x00000001,
kNormalUp = 0x00000010,
kNormalVelUpVel = 0x00000020,
kNormalFromCenter = 0x00000040,
kNormalDynamicMask = kNormalVelUpVel | kNormalFromCenter, // precalc methods that need updating each frame
kNormalPrecalcMask = kNormalDynamicMask | kNormalUp, // All types where emitter precalculates the normal
kNormalViewFacing = 0x00000100,
kNormalNearestLight = 0x00000200,
kNeedsUpdate = 0x01000000,
kBorrowedGenerator = 0x02000000,
kOverrideLocalToWorld = 0x04000000,
kOnReserve = 0x08000000,
kOrientationUp = 0x10000000,
kOrientationVelocityBased = 0x20000000,
kOrientationVelocityStretch = 0x40000000,
kOrientationVelocityFlow = 0x80000000,
kOrientationVelocityMask = kOrientationVelocityBased | kOrientationVelocityStretch | kOrientationVelocityFlow, // Velocity dependent
kOrientationMask = kOrientationUp | kOrientationVelocityMask,
};
UInt32 fMiscFlags;
protected:
plParticleSystem *fSystem; // The particle system this belongs to.
plParticleCore *fParticleCores; // The particle pool, created on init, initialized as needed, and recycled.
plParticleExt *fParticleExts; // Same mapping as the Core pool. Contains extra info the render pipeline
// doesn't need.
plParticleGenerator *fGenerator; // Optional auto generator (have this be nil if you don't want auto-generation)
UInt32 fSpanIndex; // Index of the span that this emitter uses.
UInt32 fNumValidParticles;
UInt32 fMaxParticles;
hsBounds3Ext fBoundBox;
plEffectTargetInfo fTargetInfo; // A collection of pointers and strides that plParticleEffects will manipulate.
hsColorRGBA fColor;
hsMatrix44 fLocalToWorld;
hsScalar fTimeToLive;
void IClear();
void ISetupParticleMem();
void ISetSystem(plParticleSystem *sys) { fSystem = sys; }
hsBool IUpdate(hsScalar delta);
void IUpdateParticles(hsScalar delta);
void IUpdateBoundsAndNormals(hsScalar delta);
void IRemoveParticle(UInt32 index);
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleEmitter_inc
#define plParticleEmitter_inc
#include "hsGeometry3.h"
#include "hsBounds.h"
#include "pnNetCommon/plSynchedValue.h"
#include "hsColorRGBA.h"
class hsBounds3Ext;
class plParticleSystem;
class plParticleCore;
class plParticleExt;
class plParticleGenerator;
class plSimpleParticleGenerator;
class hsResMgr;
#include "plEffectTargetInfo.h"
// This just holds a bunch of parameters for an emission location. A particle system can have several of these
class plParticleEmitter : public plCreatable
{
friend plParticleSystem;
friend plSimpleParticleGenerator;
public:
plParticleEmitter();
~plParticleEmitter();
void Init(plParticleSystem *system, UInt32 maxParticles, UInt32 spanIndex, UInt32 miscFlags,
plParticleGenerator *gen = nil);
void Clone(plParticleEmitter* src, UInt32 spanIndex);
plParticleCore *GetParticleArray() const { return fParticleCores; }
UInt32 GetParticleCount() const { return fNumValidParticles; }
UInt32 GetNumTiles() const;
const hsBounds3Ext &GetBoundingBox() const { return fBoundBox; }
UInt32 GetSpanIndex() const { return fSpanIndex; }
const hsMatrix44 &GetLocalToWorld() const;
void AddParticle(hsPoint3 &pos, hsVector3 &velocity, UInt32 tileIndex,
hsScalar hSize, hsScalar vSize, hsScalar scale, hsScalar invMass, hsScalar life,
hsPoint3 &orientation, UInt32 miscFlags, hsScalar radsPerSec=0);
void WipeExistingParticles();
void KillParticles(hsScalar num, hsScalar timeToDie, UInt8 flags);
UInt16 StealParticlesFrom(plParticleEmitter *victim, UInt16 num); // returns the number actually stolen
void TranslateAllParticles(hsPoint3 &amount); // Used to recenter the system when linking between ages.
void UpdateGenerator(UInt32 paramID, hsScalar paramValue);
static UInt32 CreateHexColor(const hsColorRGBA &color);
static UInt32 CreateHexColor(const hsScalar r, const hsScalar g, const hsScalar b, const hsScalar a);
void OverrideLocalToWorld(const hsMatrix44& l2w);
void UnOverrideLocalToWorld() { fMiscFlags &= ~kOverrideLocalToWorld; }
hsBool LocalToWorldOverridden() const { return 0 != (fMiscFlags & kOverrideLocalToWorld); }
void SetTimeToLive(hsScalar dt) { fTimeToLive = dt; }
hsScalar GetTimeToLive() const { return fTimeToLive; } // 0 time to live is never turn off.
CLASSNAME_REGISTER( plParticleEmitter );
GETINTERFACE_ANY( plParticleEmitter, plCreatable);
virtual void Read(hsStream* s, hsResMgr *mgr);
virtual void Write(hsStream* s, hsResMgr *mgr);
enum // Miscellaneous flags
{
kMatIsEmissive = 0x00000001,
kNormalUp = 0x00000010,
kNormalVelUpVel = 0x00000020,
kNormalFromCenter = 0x00000040,
kNormalDynamicMask = kNormalVelUpVel | kNormalFromCenter, // precalc methods that need updating each frame
kNormalPrecalcMask = kNormalDynamicMask | kNormalUp, // All types where emitter precalculates the normal
kNormalViewFacing = 0x00000100,
kNormalNearestLight = 0x00000200,
kNeedsUpdate = 0x01000000,
kBorrowedGenerator = 0x02000000,
kOverrideLocalToWorld = 0x04000000,
kOnReserve = 0x08000000,
kOrientationUp = 0x10000000,
kOrientationVelocityBased = 0x20000000,
kOrientationVelocityStretch = 0x40000000,
kOrientationVelocityFlow = 0x80000000,
kOrientationVelocityMask = kOrientationVelocityBased | kOrientationVelocityStretch | kOrientationVelocityFlow, // Velocity dependent
kOrientationMask = kOrientationUp | kOrientationVelocityMask,
};
UInt32 fMiscFlags;
protected:
plParticleSystem *fSystem; // The particle system this belongs to.
plParticleCore *fParticleCores; // The particle pool, created on init, initialized as needed, and recycled.
plParticleExt *fParticleExts; // Same mapping as the Core pool. Contains extra info the render pipeline
// doesn't need.
plParticleGenerator *fGenerator; // Optional auto generator (have this be nil if you don't want auto-generation)
UInt32 fSpanIndex; // Index of the span that this emitter uses.
UInt32 fNumValidParticles;
UInt32 fMaxParticles;
hsBounds3Ext fBoundBox;
plEffectTargetInfo fTargetInfo; // A collection of pointers and strides that plParticleEffects will manipulate.
hsColorRGBA fColor;
hsMatrix44 fLocalToWorld;
hsScalar fTimeToLive;
void IClear();
void ISetupParticleMem();
void ISetSystem(plParticleSystem *sys) { fSystem = sys; }
hsBool IUpdate(hsScalar delta);
void IUpdateParticles(hsScalar delta);
void IUpdateBoundsAndNormals(hsScalar delta);
void IRemoveParticle(UInt32 index);
};
#endif

View File

@ -1,438 +1,438 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsGeometry3.h"
#include "hsStream.h"
#include "hsFastMath.h"
#include "hsUtils.h"
#include "plParticle.h"
#include "plParticleSystem.h"
#include "plParticleEmitter.h"
#include "plParticleGenerator.h"
#include "hsColorRGBA.h"
#include "plMessage/plParticleUpdateMsg.h"
#include "plInterp/plController.h"
#include "hsResMgr.h"
#include "plMath/plRandom.h"
static const hsScalar DEFAULT_INVERSE_MASS = 1.f;
static plRandom sRandom;
const void plParticleGenerator::ComputeDirection(float pitch, float yaw, hsVector3 &direction)
{
hsScalar cosPitch, sinPitch;
hsScalar cosYaw, sinYaw;
hsFastMath::SinCos(pitch, sinPitch, cosPitch);
hsFastMath::SinCos(yaw, sinYaw, cosYaw);
direction.Set(-sinYaw * cosPitch, sinPitch, cosPitch * cosYaw);
}
// Inverse function of ComputeDirection. Give it a normalized vector, and it will tell you a
// pitch and yaw (angles for the unit Z vector) to get there.
const void plParticleGenerator::ComputePitchYaw(float &pitch, float &yaw, const hsVector3 &dir)
{
const float PI = 3.14159f;
pitch = asin(dir.fY);
float cos_pitch = cos(pitch);
if (cos_pitch == 0)
{
yaw = 0;
return;
}
float inv = -dir.fX / cos_pitch;
if (inv > 1.0f)
inv = 1.0f;
if (inv < -1.0f)
inv = -1.0f;
yaw = asin(inv);
if (dir.fZ < 0)
yaw = PI - yaw;
}
plSimpleParticleGenerator::plSimpleParticleGenerator()
{
}
plSimpleParticleGenerator::~plSimpleParticleGenerator()
{
delete [] fInitPos;
delete [] fInitPitch;
delete [] fInitYaw;
}
void plSimpleParticleGenerator::Init(hsScalar genLife, hsScalar partLifeMin, hsScalar partLifeMax,
hsScalar particlesPerSecond, UInt32 numSources, hsPoint3 *initPos,
hsScalar *initPitch, hsScalar *initYaw, hsScalar angleRange,
hsScalar initVelMin, hsScalar initVelMax,
hsScalar xSize, hsScalar ySize,
hsScalar scaleMin, hsScalar scaleMax,
hsScalar massRange, hsScalar radsPerSecRange)
{
fGenLife = genLife;
fPartLifeMin = partLifeMin;
fPartLifeMax = partLifeMax;
fParticlesPerSecond = particlesPerSecond;
fNumSources = numSources;
fInitPos = initPos;
fInitPitch = initPitch;
fInitYaw = initYaw;
fAngleRange = angleRange;
fVelMin = initVelMin;
fVelMax = initVelMax;
fXSize = xSize;
fYSize = ySize;
fScaleMin = scaleMin;
fScaleMax = scaleMax;
fPartInvMassMin = 1.f / (DEFAULT_INVERSE_MASS + massRange);
fPartInvMassRange = 1.f / DEFAULT_INVERSE_MASS - fPartInvMassMin;
fPartRadsPerSecRange = radsPerSecRange;
fParticleSum = 0;
fMiscFlags = 0;
if (fGenLife < 0) fMiscFlags |= kImmortal;
}
hsBool plSimpleParticleGenerator::AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced /* = 0 */)
{
Int32 numNewParticles;
if (numForced == 0)
{
fGenLife -= dt;
if ((fGenLife < 0 && !(fMiscFlags & kImmortal)) || (fMiscFlags & kDisabled))
return true; // Leave it around so that a message can bring it back to life.
fParticleSum += fParticlesPerSecond * dt;
numNewParticles = (Int32)fParticleSum;
if (numNewParticles <= 0 || fParticlesPerSecond == 0)
return true;
}
else
{
numNewParticles = numForced;
}
UInt32 miscFlags = 0;
hsPoint3 currStart;
fParticleSum -= numNewParticles;
hsPoint3 orientation;
hsVector3 initDirection;
hsScalar vel = (fVelMax + fVelMin) * 0.5f;
hsScalar velRange = vel - fVelMin;
hsScalar initVelocity;
hsScalar initLife;
hsScalar life = (fPartLifeMax + fPartLifeMin) * 0.5f;
hsScalar lifeRange = life - fPartLifeMin;
hsScalar currSizeVar;
hsScalar scale = (fScaleMax + fScaleMin) * 0.5f;
hsScalar scaleRange = scale - fScaleMin;
hsScalar radsPerSec = 0;
UInt32 tile;
UInt32 sourceIndex;
const hsScalar lifeDiff = dt / numNewParticles;
hsScalar lifeSoFar;
int i;
for (i = 0, lifeSoFar = 0; i < numNewParticles; i++, lifeSoFar += lifeDiff)
{
initLife = life + lifeRange * sRandom.RandMinusOneToOne() - lifeSoFar;
// Careful here... if we're supposed to generate immortal particles, we do so
// by giving them a negative life. This is different that generating one with
// a positive lifetime that is now negative because of "lifeSoFar". The if is
// saying "if it's dead, but it was alive before we took away lifeSoFar, ignore it"
if (initLife <= 0 && initLife + lifeSoFar >= 0)
continue;
sourceIndex = (UInt32)(sRandom.RandZeroToOne() * fNumSources);
ComputeDirection(fInitPitch[sourceIndex] + fAngleRange * sRandom.RandMinusOneToOne(),
fInitYaw[sourceIndex] + fAngleRange * sRandom.RandMinusOneToOne(), initDirection);
initDirection = emitter->GetLocalToWorld() * initDirection;
initVelocity = (vel + velRange * sRandom.RandMinusOneToOne());
currStart = (emitter->GetLocalToWorld() * fInitPos[sourceIndex])
+ (initDirection * initVelocity * lifeSoFar) // Vo * t
+ (emitter->fSystem->fAccel * lifeSoFar * lifeSoFar); // at^2
if (emitter->fMiscFlags & emitter->kOrientationUp)
orientation.Set(0.0f, -1.0f, 0.0f);
else
orientation.Set(&initDirection);
tile = (UInt32)(sRandom.RandZeroToOne() * emitter->GetNumTiles());
currSizeVar = scale + scaleRange * sRandom.RandMinusOneToOne();
hsScalar invMass = fPartInvMassMin;
// Might be faster to just do the math instead of checking for zero...
if( fPartInvMassRange > 0 )
invMass += fPartInvMassRange * sRandom.RandZeroToOne();
if( fPartRadsPerSecRange > 0 )
radsPerSec = fPartRadsPerSecRange * sRandom.RandMinusOneToOne();
emitter->AddParticle(currStart, initDirection * initVelocity, tile, fXSize, fYSize, currSizeVar,
invMass, initLife, orientation, miscFlags, radsPerSec);
}
return true;
}
void plSimpleParticleGenerator::UpdateParam(UInt32 paramID, hsScalar paramValue)
{
switch (paramID)
{
case plParticleUpdateMsg::kParamParticlesPerSecond:
fParticlesPerSecond = paramValue;
break;
case plParticleUpdateMsg::kParamInitPitchRange:
case plParticleUpdateMsg::kParamInitYawRange:
fAngleRange = paramValue;
break;
// case plParticleUpdateMsg::kParamInitVel:
// fInitVel = paramValue;
// break;
// case plParticleUpdateMsg::kParamInitVelRange:
// fInitVelRange = paramValue;
// break;
case plParticleUpdateMsg::kParamVelMin:
fVelMin = paramValue;
break;
case plParticleUpdateMsg::kParamVelMax:
fVelMax = paramValue;
break;
case plParticleUpdateMsg::kParamXSize:
fXSize = paramValue;
break;
case plParticleUpdateMsg::kParamYSize:
fYSize = paramValue;
break;
// case plParticleUpdateMsg::kParamSizeRange:
// fSizeRange = paramValue;
// break;
case plParticleUpdateMsg::kParamScaleMin:
fScaleMin = paramValue;
break;
case plParticleUpdateMsg::kParamScaleMax:
fScaleMax = paramValue;
break;
case plParticleUpdateMsg::kParamGenLife:
fGenLife = paramValue;
if (fGenLife < 0)
fMiscFlags |= kImmortal;
else
fMiscFlags &= ~kImmortal;
break;
// case plParticleUpdateMsg::kParamPartLife:
// fPartLife = paramValue;
// if (fPartLife < 0)
// fPartLifeRange = 0;
// break;
// case plParticleUpdateMsg::kParamPartLifeRange:
// fPartLifeRange = paramValue;
// break;
case plParticleUpdateMsg::kParamPartLifeMin:
fPartLifeMin = paramValue;
break;
case plParticleUpdateMsg::kParamPartLifeMax:
fPartLifeMax = paramValue;
break;
case plParticleUpdateMsg::kParamEnabled:
if (paramValue == 0.f)
fMiscFlags |= kDisabled;
else
fMiscFlags &= ~kDisabled;
break;
default:
break;
}
}
void plSimpleParticleGenerator::Read(hsStream* s, hsResMgr *mgr)
{
hsScalar genLife = s->ReadSwapScalar();
hsScalar partLifeMin = s->ReadSwapScalar();
hsScalar partLifeMax = s->ReadSwapScalar();
hsScalar pps = s->ReadSwapScalar();
UInt32 numSources = s->ReadSwap32();
hsPoint3 *pos = TRACKED_NEW hsPoint3[numSources];
hsScalar *pitch = TRACKED_NEW hsScalar[numSources];
hsScalar *yaw = TRACKED_NEW hsScalar[numSources];
int i;
for (i = 0; i < numSources; i++)
{
pos[i].Read(s);
pitch[i] = s->ReadSwapScalar();
yaw[i] = s->ReadSwapScalar();
}
hsScalar angleRange = s->ReadSwapScalar();
hsScalar velMin = s->ReadSwapScalar();
hsScalar velMax = s->ReadSwapScalar();
hsScalar xSize = s->ReadSwapScalar();
hsScalar ySize = s->ReadSwapScalar();
hsScalar scaleMin = s->ReadSwapScalar();
hsScalar scaleMax = s->ReadSwapScalar();
hsScalar massRange = s->ReadSwapScalar();
hsScalar radsPerSec = s->ReadSwapScalar();
Init(genLife, partLifeMin, partLifeMax, pps, numSources, pos, pitch, yaw, angleRange, velMin, velMax,
xSize, ySize, scaleMin, scaleMax, massRange, radsPerSec);
}
void plSimpleParticleGenerator::Write(hsStream* s, hsResMgr *mgr)
{
s->WriteSwapScalar(fGenLife);
s->WriteSwapScalar(fPartLifeMin);
s->WriteSwapScalar(fPartLifeMax);
s->WriteSwapScalar(fParticlesPerSecond);
s->WriteSwap32(fNumSources);
int i;
for (i = 0; i < fNumSources; i++)
{
fInitPos[i].Write(s);
s->WriteSwapScalar(fInitPitch[i]);
s->WriteSwapScalar(fInitYaw[i]);
}
s->WriteSwapScalar(fAngleRange);
s->WriteSwapScalar(fVelMin);
s->WriteSwapScalar(fVelMax);
s->WriteSwapScalar(fXSize);
s->WriteSwapScalar(fYSize);
s->WriteSwapScalar(fScaleMin);
s->WriteSwapScalar(fScaleMax);
hsScalar massRange = 1.f / fPartInvMassMin - DEFAULT_INVERSE_MASS;
s->WriteSwapScalar(massRange);
s->WriteSwapScalar(fPartRadsPerSecRange);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
plOneTimeParticleGenerator::plOneTimeParticleGenerator()
{
}
plOneTimeParticleGenerator::~plOneTimeParticleGenerator()
{
delete [] fPosition;
delete [] fDirection;
}
void plOneTimeParticleGenerator::Init(hsScalar count, hsPoint3 *pointArray, hsVector3 *dirArray,
hsScalar xSize, hsScalar ySize, hsScalar scaleMin, hsScalar scaleMax, hsScalar radsPerSecRange)
{
fCount = count;
fPosition = pointArray;
fDirection = dirArray;
fXSize = xSize;
fYSize = ySize;
fScaleMin = scaleMin;
fScaleMax = scaleMax;
fPartRadsPerSecRange = radsPerSecRange;
}
// The numForced param is required by the parent class, but ignored by this particular generator
hsBool plOneTimeParticleGenerator::AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced /* = 0 */)
{
hsScalar currSizeVar;
hsScalar scale = (fScaleMax + fScaleMin) / 2;
hsScalar scaleRange = scale - fScaleMin;
hsScalar tile;
hsPoint3 currStart;
hsPoint3 orientation;
hsVector3 initDirection;
hsVector3 zeroVel(0.f, 0.f, 0.f);
hsScalar radsPerSec = 0;
int i;
for (i = 0; i < fCount; i++)
{
currStart = emitter->GetLocalToWorld() * fPosition[i];
initDirection = emitter->GetLocalToWorld() * fDirection[i];
if (emitter->fMiscFlags & emitter->kOrientationUp)
orientation.Set(0.0f, -1.0f, 0.0f);
else
orientation.Set(&initDirection);
tile = (hsScalar)(sRandom.Rand() % emitter->GetNumTiles());
currSizeVar = scale + scaleRange * sRandom.RandMinusOneToOne();
if( fPartRadsPerSecRange > 0 )
radsPerSec = fPartRadsPerSecRange * sRandom.RandMinusOneToOne();
emitter->AddParticle(currStart, zeroVel, (UInt32)tile, fXSize, fYSize, currSizeVar,
DEFAULT_INVERSE_MASS, -1, orientation, 0, radsPerSec);
}
emitter->fMiscFlags &= ~plParticleEmitter::kNeedsUpdate;
return false; // We've done our one-time job. Let the emitter know to delete us.
}
void plOneTimeParticleGenerator::Read(hsStream* s, hsResMgr *mgr)
{
UInt32 count = s->ReadSwap32();
hsScalar xSize = s->ReadSwapScalar();
hsScalar ySize = s->ReadSwapScalar();
hsScalar scaleMin = s->ReadSwapScalar();
hsScalar scaleMax = s->ReadSwapScalar();
hsScalar radsPerSecRange = s->ReadSwapScalar();
hsPoint3 *pos = TRACKED_NEW hsPoint3[count];
hsVector3 *dir = TRACKED_NEW hsVector3[count];
int i;
for (i = 0; i < count; i++)
{
pos[i].Read(s);
dir[i].Read(s);
}
Init((hsScalar)count, pos, dir, xSize, ySize, scaleMin, scaleMax, radsPerSecRange);
}
void plOneTimeParticleGenerator::Write(hsStream* s, hsResMgr *mgr)
{
s->WriteSwap32((UInt32)fCount);
s->WriteSwapScalar(fXSize);
s->WriteSwapScalar(fYSize);
s->WriteSwapScalar(fScaleMin);
s->WriteSwapScalar(fScaleMax);
s->WriteSwapScalar(fPartRadsPerSecRange);
int i;
for (i = 0; i < fCount; i++)
{
fPosition[i].Write(s);
fDirection[i].Write(s);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsGeometry3.h"
#include "hsStream.h"
#include "hsFastMath.h"
#include "hsUtils.h"
#include "plParticle.h"
#include "plParticleSystem.h"
#include "plParticleEmitter.h"
#include "plParticleGenerator.h"
#include "hsColorRGBA.h"
#include "plMessage/plParticleUpdateMsg.h"
#include "plInterp/plController.h"
#include "hsResMgr.h"
#include "plMath/plRandom.h"
static const hsScalar DEFAULT_INVERSE_MASS = 1.f;
static plRandom sRandom;
const void plParticleGenerator::ComputeDirection(float pitch, float yaw, hsVector3 &direction)
{
hsScalar cosPitch, sinPitch;
hsScalar cosYaw, sinYaw;
hsFastMath::SinCos(pitch, sinPitch, cosPitch);
hsFastMath::SinCos(yaw, sinYaw, cosYaw);
direction.Set(-sinYaw * cosPitch, sinPitch, cosPitch * cosYaw);
}
// Inverse function of ComputeDirection. Give it a normalized vector, and it will tell you a
// pitch and yaw (angles for the unit Z vector) to get there.
const void plParticleGenerator::ComputePitchYaw(float &pitch, float &yaw, const hsVector3 &dir)
{
const float PI = 3.14159f;
pitch = asin(dir.fY);
float cos_pitch = cos(pitch);
if (cos_pitch == 0)
{
yaw = 0;
return;
}
float inv = -dir.fX / cos_pitch;
if (inv > 1.0f)
inv = 1.0f;
if (inv < -1.0f)
inv = -1.0f;
yaw = asin(inv);
if (dir.fZ < 0)
yaw = PI - yaw;
}
plSimpleParticleGenerator::plSimpleParticleGenerator()
{
}
plSimpleParticleGenerator::~plSimpleParticleGenerator()
{
delete [] fInitPos;
delete [] fInitPitch;
delete [] fInitYaw;
}
void plSimpleParticleGenerator::Init(hsScalar genLife, hsScalar partLifeMin, hsScalar partLifeMax,
hsScalar particlesPerSecond, UInt32 numSources, hsPoint3 *initPos,
hsScalar *initPitch, hsScalar *initYaw, hsScalar angleRange,
hsScalar initVelMin, hsScalar initVelMax,
hsScalar xSize, hsScalar ySize,
hsScalar scaleMin, hsScalar scaleMax,
hsScalar massRange, hsScalar radsPerSecRange)
{
fGenLife = genLife;
fPartLifeMin = partLifeMin;
fPartLifeMax = partLifeMax;
fParticlesPerSecond = particlesPerSecond;
fNumSources = numSources;
fInitPos = initPos;
fInitPitch = initPitch;
fInitYaw = initYaw;
fAngleRange = angleRange;
fVelMin = initVelMin;
fVelMax = initVelMax;
fXSize = xSize;
fYSize = ySize;
fScaleMin = scaleMin;
fScaleMax = scaleMax;
fPartInvMassMin = 1.f / (DEFAULT_INVERSE_MASS + massRange);
fPartInvMassRange = 1.f / DEFAULT_INVERSE_MASS - fPartInvMassMin;
fPartRadsPerSecRange = radsPerSecRange;
fParticleSum = 0;
fMiscFlags = 0;
if (fGenLife < 0) fMiscFlags |= kImmortal;
}
hsBool plSimpleParticleGenerator::AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced /* = 0 */)
{
Int32 numNewParticles;
if (numForced == 0)
{
fGenLife -= dt;
if ((fGenLife < 0 && !(fMiscFlags & kImmortal)) || (fMiscFlags & kDisabled))
return true; // Leave it around so that a message can bring it back to life.
fParticleSum += fParticlesPerSecond * dt;
numNewParticles = (Int32)fParticleSum;
if (numNewParticles <= 0 || fParticlesPerSecond == 0)
return true;
}
else
{
numNewParticles = numForced;
}
UInt32 miscFlags = 0;
hsPoint3 currStart;
fParticleSum -= numNewParticles;
hsPoint3 orientation;
hsVector3 initDirection;
hsScalar vel = (fVelMax + fVelMin) * 0.5f;
hsScalar velRange = vel - fVelMin;
hsScalar initVelocity;
hsScalar initLife;
hsScalar life = (fPartLifeMax + fPartLifeMin) * 0.5f;
hsScalar lifeRange = life - fPartLifeMin;
hsScalar currSizeVar;
hsScalar scale = (fScaleMax + fScaleMin) * 0.5f;
hsScalar scaleRange = scale - fScaleMin;
hsScalar radsPerSec = 0;
UInt32 tile;
UInt32 sourceIndex;
const hsScalar lifeDiff = dt / numNewParticles;
hsScalar lifeSoFar;
int i;
for (i = 0, lifeSoFar = 0; i < numNewParticles; i++, lifeSoFar += lifeDiff)
{
initLife = life + lifeRange * sRandom.RandMinusOneToOne() - lifeSoFar;
// Careful here... if we're supposed to generate immortal particles, we do so
// by giving them a negative life. This is different that generating one with
// a positive lifetime that is now negative because of "lifeSoFar". The if is
// saying "if it's dead, but it was alive before we took away lifeSoFar, ignore it"
if (initLife <= 0 && initLife + lifeSoFar >= 0)
continue;
sourceIndex = (UInt32)(sRandom.RandZeroToOne() * fNumSources);
ComputeDirection(fInitPitch[sourceIndex] + fAngleRange * sRandom.RandMinusOneToOne(),
fInitYaw[sourceIndex] + fAngleRange * sRandom.RandMinusOneToOne(), initDirection);
initDirection = emitter->GetLocalToWorld() * initDirection;
initVelocity = (vel + velRange * sRandom.RandMinusOneToOne());
currStart = (emitter->GetLocalToWorld() * fInitPos[sourceIndex])
+ (initDirection * initVelocity * lifeSoFar) // Vo * t
+ (emitter->fSystem->fAccel * lifeSoFar * lifeSoFar); // at^2
if (emitter->fMiscFlags & emitter->kOrientationUp)
orientation.Set(0.0f, -1.0f, 0.0f);
else
orientation.Set(&initDirection);
tile = (UInt32)(sRandom.RandZeroToOne() * emitter->GetNumTiles());
currSizeVar = scale + scaleRange * sRandom.RandMinusOneToOne();
hsScalar invMass = fPartInvMassMin;
// Might be faster to just do the math instead of checking for zero...
if( fPartInvMassRange > 0 )
invMass += fPartInvMassRange * sRandom.RandZeroToOne();
if( fPartRadsPerSecRange > 0 )
radsPerSec = fPartRadsPerSecRange * sRandom.RandMinusOneToOne();
emitter->AddParticle(currStart, initDirection * initVelocity, tile, fXSize, fYSize, currSizeVar,
invMass, initLife, orientation, miscFlags, radsPerSec);
}
return true;
}
void plSimpleParticleGenerator::UpdateParam(UInt32 paramID, hsScalar paramValue)
{
switch (paramID)
{
case plParticleUpdateMsg::kParamParticlesPerSecond:
fParticlesPerSecond = paramValue;
break;
case plParticleUpdateMsg::kParamInitPitchRange:
case plParticleUpdateMsg::kParamInitYawRange:
fAngleRange = paramValue;
break;
// case plParticleUpdateMsg::kParamInitVel:
// fInitVel = paramValue;
// break;
// case plParticleUpdateMsg::kParamInitVelRange:
// fInitVelRange = paramValue;
// break;
case plParticleUpdateMsg::kParamVelMin:
fVelMin = paramValue;
break;
case plParticleUpdateMsg::kParamVelMax:
fVelMax = paramValue;
break;
case plParticleUpdateMsg::kParamXSize:
fXSize = paramValue;
break;
case plParticleUpdateMsg::kParamYSize:
fYSize = paramValue;
break;
// case plParticleUpdateMsg::kParamSizeRange:
// fSizeRange = paramValue;
// break;
case plParticleUpdateMsg::kParamScaleMin:
fScaleMin = paramValue;
break;
case plParticleUpdateMsg::kParamScaleMax:
fScaleMax = paramValue;
break;
case plParticleUpdateMsg::kParamGenLife:
fGenLife = paramValue;
if (fGenLife < 0)
fMiscFlags |= kImmortal;
else
fMiscFlags &= ~kImmortal;
break;
// case plParticleUpdateMsg::kParamPartLife:
// fPartLife = paramValue;
// if (fPartLife < 0)
// fPartLifeRange = 0;
// break;
// case plParticleUpdateMsg::kParamPartLifeRange:
// fPartLifeRange = paramValue;
// break;
case plParticleUpdateMsg::kParamPartLifeMin:
fPartLifeMin = paramValue;
break;
case plParticleUpdateMsg::kParamPartLifeMax:
fPartLifeMax = paramValue;
break;
case plParticleUpdateMsg::kParamEnabled:
if (paramValue == 0.f)
fMiscFlags |= kDisabled;
else
fMiscFlags &= ~kDisabled;
break;
default:
break;
}
}
void plSimpleParticleGenerator::Read(hsStream* s, hsResMgr *mgr)
{
hsScalar genLife = s->ReadSwapScalar();
hsScalar partLifeMin = s->ReadSwapScalar();
hsScalar partLifeMax = s->ReadSwapScalar();
hsScalar pps = s->ReadSwapScalar();
UInt32 numSources = s->ReadSwap32();
hsPoint3 *pos = TRACKED_NEW hsPoint3[numSources];
hsScalar *pitch = TRACKED_NEW hsScalar[numSources];
hsScalar *yaw = TRACKED_NEW hsScalar[numSources];
int i;
for (i = 0; i < numSources; i++)
{
pos[i].Read(s);
pitch[i] = s->ReadSwapScalar();
yaw[i] = s->ReadSwapScalar();
}
hsScalar angleRange = s->ReadSwapScalar();
hsScalar velMin = s->ReadSwapScalar();
hsScalar velMax = s->ReadSwapScalar();
hsScalar xSize = s->ReadSwapScalar();
hsScalar ySize = s->ReadSwapScalar();
hsScalar scaleMin = s->ReadSwapScalar();
hsScalar scaleMax = s->ReadSwapScalar();
hsScalar massRange = s->ReadSwapScalar();
hsScalar radsPerSec = s->ReadSwapScalar();
Init(genLife, partLifeMin, partLifeMax, pps, numSources, pos, pitch, yaw, angleRange, velMin, velMax,
xSize, ySize, scaleMin, scaleMax, massRange, radsPerSec);
}
void plSimpleParticleGenerator::Write(hsStream* s, hsResMgr *mgr)
{
s->WriteSwapScalar(fGenLife);
s->WriteSwapScalar(fPartLifeMin);
s->WriteSwapScalar(fPartLifeMax);
s->WriteSwapScalar(fParticlesPerSecond);
s->WriteSwap32(fNumSources);
int i;
for (i = 0; i < fNumSources; i++)
{
fInitPos[i].Write(s);
s->WriteSwapScalar(fInitPitch[i]);
s->WriteSwapScalar(fInitYaw[i]);
}
s->WriteSwapScalar(fAngleRange);
s->WriteSwapScalar(fVelMin);
s->WriteSwapScalar(fVelMax);
s->WriteSwapScalar(fXSize);
s->WriteSwapScalar(fYSize);
s->WriteSwapScalar(fScaleMin);
s->WriteSwapScalar(fScaleMax);
hsScalar massRange = 1.f / fPartInvMassMin - DEFAULT_INVERSE_MASS;
s->WriteSwapScalar(massRange);
s->WriteSwapScalar(fPartRadsPerSecRange);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
plOneTimeParticleGenerator::plOneTimeParticleGenerator()
{
}
plOneTimeParticleGenerator::~plOneTimeParticleGenerator()
{
delete [] fPosition;
delete [] fDirection;
}
void plOneTimeParticleGenerator::Init(hsScalar count, hsPoint3 *pointArray, hsVector3 *dirArray,
hsScalar xSize, hsScalar ySize, hsScalar scaleMin, hsScalar scaleMax, hsScalar radsPerSecRange)
{
fCount = count;
fPosition = pointArray;
fDirection = dirArray;
fXSize = xSize;
fYSize = ySize;
fScaleMin = scaleMin;
fScaleMax = scaleMax;
fPartRadsPerSecRange = radsPerSecRange;
}
// The numForced param is required by the parent class, but ignored by this particular generator
hsBool plOneTimeParticleGenerator::AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced /* = 0 */)
{
hsScalar currSizeVar;
hsScalar scale = (fScaleMax + fScaleMin) / 2;
hsScalar scaleRange = scale - fScaleMin;
hsScalar tile;
hsPoint3 currStart;
hsPoint3 orientation;
hsVector3 initDirection;
hsVector3 zeroVel(0.f, 0.f, 0.f);
hsScalar radsPerSec = 0;
int i;
for (i = 0; i < fCount; i++)
{
currStart = emitter->GetLocalToWorld() * fPosition[i];
initDirection = emitter->GetLocalToWorld() * fDirection[i];
if (emitter->fMiscFlags & emitter->kOrientationUp)
orientation.Set(0.0f, -1.0f, 0.0f);
else
orientation.Set(&initDirection);
tile = (hsScalar)(sRandom.Rand() % emitter->GetNumTiles());
currSizeVar = scale + scaleRange * sRandom.RandMinusOneToOne();
if( fPartRadsPerSecRange > 0 )
radsPerSec = fPartRadsPerSecRange * sRandom.RandMinusOneToOne();
emitter->AddParticle(currStart, zeroVel, (UInt32)tile, fXSize, fYSize, currSizeVar,
DEFAULT_INVERSE_MASS, -1, orientation, 0, radsPerSec);
}
emitter->fMiscFlags &= ~plParticleEmitter::kNeedsUpdate;
return false; // We've done our one-time job. Let the emitter know to delete us.
}
void plOneTimeParticleGenerator::Read(hsStream* s, hsResMgr *mgr)
{
UInt32 count = s->ReadSwap32();
hsScalar xSize = s->ReadSwapScalar();
hsScalar ySize = s->ReadSwapScalar();
hsScalar scaleMin = s->ReadSwapScalar();
hsScalar scaleMax = s->ReadSwapScalar();
hsScalar radsPerSecRange = s->ReadSwapScalar();
hsPoint3 *pos = TRACKED_NEW hsPoint3[count];
hsVector3 *dir = TRACKED_NEW hsVector3[count];
int i;
for (i = 0; i < count; i++)
{
pos[i].Read(s);
dir[i].Read(s);
}
Init((hsScalar)count, pos, dir, xSize, ySize, scaleMin, scaleMax, radsPerSecRange);
}
void plOneTimeParticleGenerator::Write(hsStream* s, hsResMgr *mgr)
{
s->WriteSwap32((UInt32)fCount);
s->WriteSwapScalar(fXSize);
s->WriteSwapScalar(fYSize);
s->WriteSwapScalar(fScaleMin);
s->WriteSwapScalar(fScaleMax);
s->WriteSwapScalar(fPartRadsPerSecRange);
int i;
for (i = 0; i < fCount; i++)
{
fPosition[i].Write(s);
fDirection[i].Write(s);
}
}

View File

@ -1,132 +1,132 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleGenerator_inc
#define plParticleGenerator_inc
#include "hsGeometry3.h"
#include "pnNetCommon/plSynchedValue.h"
class plParticleEmitter;
class plScalarController;
// This class is responsible for all the details of automatically generating particles for a plParticleEmitter.
// It gets a change in time, and must do whatever necessary to generate the appropriate number of particles
// for that timespan
class plParticleGenerator : public plCreatable
{
public:
// returns false if it's done generating particles and is safe to delete.
virtual hsBool AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced = 0) = 0;
virtual void UpdateParam(UInt32 paramID, hsScalar paramValue) = 0;
CLASSNAME_REGISTER( plParticleGenerator );
GETINTERFACE_ANY( plParticleGenerator, plCreatable );
static const void ComputeDirection(float pitch, float yaw, hsVector3 &direction);
static const void ComputePitchYaw(float &pitch, float &yaw, const hsVector3 &dir);
static inline float GetRandomVar() { return 2.0f * (float)hsRand() / RAND_MAX - 1; } // returns a num between +/- 1.0
};
class plSimpleParticleGenerator : public plParticleGenerator
{
public:
plSimpleParticleGenerator();
~plSimpleParticleGenerator();
void Init(hsScalar genLife, hsScalar partLifeMin, hsScalar partLifeMax, hsScalar particlesPerSecond,
UInt32 numSources, hsPoint3 *pos, hsScalar *initPitch, hsScalar *initYaw, hsScalar angleRange,
hsScalar initVelMin, hsScalar initVelMax, hsScalar xSize, hsScalar ySize,
hsScalar scaleMin, hsScalar scaleMax,
hsScalar massRange, hsScalar radsPerSecRange);
CLASSNAME_REGISTER( plSimpleParticleGenerator );
GETINTERFACE_ANY( plSimpleParticleGenerator, plParticleGenerator);
virtual hsBool AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced);
virtual void UpdateParam(UInt32 paramID, hsScalar paramValue);
virtual void Read(hsStream* s, hsResMgr *mgr);
virtual void Write(hsStream* s, hsResMgr *mgr);
protected:
hsScalar fParticlesPerSecond;
UInt32 fNumSources;
hsPoint3 *fInitPos;
hsScalar *fInitPitch, *fInitYaw;
hsScalar fAngleRange;
hsScalar fVelMin, fVelMax;
hsScalar fXSize, fYSize, fScaleMin, fScaleMax;
hsScalar fGenLife; // How long shall we spit out particles from this location? When this time runs out, we stop
// spitting particles, but we don't actually die until all of our particles die naturally.
// (Even the ones that we feel are suffering needlessly.)
hsScalar fPartLifeMin; // lifespan for the particles we generate
hsScalar fPartLifeMax;
hsScalar fPartInvMassMin; // Doing a uniform variant over the inverse mass range (instead of over the mass range
hsScalar fPartInvMassRange; // and then inverting) will favor the low end of the mass range, but then again,
// it's just a freaking game. Note though that fPartInvMassMin == 1.f / massMAX.
hsScalar fPartRadsPerSecRange; // Zero means no rot, otherwise uniform random between [-range..range]
hsScalar fParticleSum;
enum
{
kImmortal = 0x1,
kDisabled = 0x2,
};
UInt32 fMiscFlags;
};
class plOneTimeParticleGenerator : public plParticleGenerator
{
public:
plOneTimeParticleGenerator();
~plOneTimeParticleGenerator();
void Init(hsScalar count, hsPoint3 *pointArray, hsVector3 *dirArray,
hsScalar xSize, hsScalar ySize, hsScalar scaleMin, hsScalar scaleMax, hsScalar radsPerSec);
CLASSNAME_REGISTER( plOneTimeParticleGenerator );
GETINTERFACE_ANY( plOneTimeParticleGenerator, plParticleGenerator);
virtual hsBool AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced = 0);
virtual void UpdateParam(UInt32 paramID, hsScalar paramValue) {}
virtual void Read(hsStream* s, hsResMgr *mgr);
virtual void Write(hsStream* s, hsResMgr *mgr);
protected:
hsScalar fCount;
hsPoint3 *fPosition;
hsVector3 *fDirection;
hsScalar fXSize, fYSize, fScaleMin, fScaleMax;
hsScalar fPartRadsPerSecRange; // Zero means no rot, otherwise uniform random between [-range..range]
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleGenerator_inc
#define plParticleGenerator_inc
#include "hsGeometry3.h"
#include "pnNetCommon/plSynchedValue.h"
class plParticleEmitter;
class plScalarController;
// This class is responsible for all the details of automatically generating particles for a plParticleEmitter.
// It gets a change in time, and must do whatever necessary to generate the appropriate number of particles
// for that timespan
class plParticleGenerator : public plCreatable
{
public:
// returns false if it's done generating particles and is safe to delete.
virtual hsBool AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced = 0) = 0;
virtual void UpdateParam(UInt32 paramID, hsScalar paramValue) = 0;
CLASSNAME_REGISTER( plParticleGenerator );
GETINTERFACE_ANY( plParticleGenerator, plCreatable );
static const void ComputeDirection(float pitch, float yaw, hsVector3 &direction);
static const void ComputePitchYaw(float &pitch, float &yaw, const hsVector3 &dir);
static inline float GetRandomVar() { return 2.0f * (float)hsRand() / RAND_MAX - 1; } // returns a num between +/- 1.0
};
class plSimpleParticleGenerator : public plParticleGenerator
{
public:
plSimpleParticleGenerator();
~plSimpleParticleGenerator();
void Init(hsScalar genLife, hsScalar partLifeMin, hsScalar partLifeMax, hsScalar particlesPerSecond,
UInt32 numSources, hsPoint3 *pos, hsScalar *initPitch, hsScalar *initYaw, hsScalar angleRange,
hsScalar initVelMin, hsScalar initVelMax, hsScalar xSize, hsScalar ySize,
hsScalar scaleMin, hsScalar scaleMax,
hsScalar massRange, hsScalar radsPerSecRange);
CLASSNAME_REGISTER( plSimpleParticleGenerator );
GETINTERFACE_ANY( plSimpleParticleGenerator, plParticleGenerator);
virtual hsBool AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced);
virtual void UpdateParam(UInt32 paramID, hsScalar paramValue);
virtual void Read(hsStream* s, hsResMgr *mgr);
virtual void Write(hsStream* s, hsResMgr *mgr);
protected:
hsScalar fParticlesPerSecond;
UInt32 fNumSources;
hsPoint3 *fInitPos;
hsScalar *fInitPitch, *fInitYaw;
hsScalar fAngleRange;
hsScalar fVelMin, fVelMax;
hsScalar fXSize, fYSize, fScaleMin, fScaleMax;
hsScalar fGenLife; // How long shall we spit out particles from this location? When this time runs out, we stop
// spitting particles, but we don't actually die until all of our particles die naturally.
// (Even the ones that we feel are suffering needlessly.)
hsScalar fPartLifeMin; // lifespan for the particles we generate
hsScalar fPartLifeMax;
hsScalar fPartInvMassMin; // Doing a uniform variant over the inverse mass range (instead of over the mass range
hsScalar fPartInvMassRange; // and then inverting) will favor the low end of the mass range, but then again,
// it's just a freaking game. Note though that fPartInvMassMin == 1.f / massMAX.
hsScalar fPartRadsPerSecRange; // Zero means no rot, otherwise uniform random between [-range..range]
hsScalar fParticleSum;
enum
{
kImmortal = 0x1,
kDisabled = 0x2,
};
UInt32 fMiscFlags;
};
class plOneTimeParticleGenerator : public plParticleGenerator
{
public:
plOneTimeParticleGenerator();
~plOneTimeParticleGenerator();
void Init(hsScalar count, hsPoint3 *pointArray, hsVector3 *dirArray,
hsScalar xSize, hsScalar ySize, hsScalar scaleMin, hsScalar scaleMax, hsScalar radsPerSec);
CLASSNAME_REGISTER( plOneTimeParticleGenerator );
GETINTERFACE_ANY( plOneTimeParticleGenerator, plParticleGenerator);
virtual hsBool AddAutoParticles(plParticleEmitter *emitter, float dt, UInt32 numForced = 0);
virtual void UpdateParam(UInt32 paramID, hsScalar paramValue) {}
virtual void Read(hsStream* s, hsResMgr *mgr);
virtual void Write(hsStream* s, hsResMgr *mgr);
protected:
hsScalar fCount;
hsPoint3 *fPosition;
hsVector3 *fDirection;
hsScalar fXSize, fYSize, fScaleMin, fScaleMax;
hsScalar fPartRadsPerSecRange; // Zero means no rot, otherwise uniform random between [-range..range]
};
#endif

View File

@ -1,76 +1,76 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plParticleSDLMod.h"
#include "plParticleSystem.h"
#include "pnSceneObject/plSceneObject.h"
#include "plSDL/plSDL.h"
#include "pnKeyedObject/plKey.h"
// static vars
char plParticleSDLMod::kStrNumParticles[]="numParticles";
void plParticleSDLMod::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plSceneObject* sobj=GetTarget();
if (!sobj)
return;
UInt32 flags = sobj->GetKey()->GetUoid().GetLocation().GetFlags();
const plParticleSystem *sys = plParticleSystem::ConvertNoRef(sobj->GetModifierByType(plParticleSystem::Index()));
if (!sys)
return;
int num = sys->GetNumValidParticles(true);
dstState->FindVar(kStrNumParticles)->Set(num);
}
void plParticleSDLMod::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSceneObject* sobj=GetTarget();
if (!sobj)
return;
plParticleSystem *sys = const_cast<plParticleSystem*>(plParticleSystem::ConvertNoRef(sobj->GetModifierByType(plParticleSystem::Index())));
if (!sys)
return;
int num;
srcState->FindVar(kStrNumParticles)->Get(&num);
if (num > sys->GetMaxTotalParticles())
num = sys->GetMaxTotalParticles();
sys->WipeExistingParticles();
sys->GenerateParticles(num);
}
UInt32 plParticleSDLMod::IApplyModFlags(UInt32 sendFlags)
{
if (fAttachedToAvatar)
return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState);
return sendFlags;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plParticleSDLMod.h"
#include "plParticleSystem.h"
#include "pnSceneObject/plSceneObject.h"
#include "plSDL/plSDL.h"
#include "pnKeyedObject/plKey.h"
// static vars
char plParticleSDLMod::kStrNumParticles[]="numParticles";
void plParticleSDLMod::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plSceneObject* sobj=GetTarget();
if (!sobj)
return;
UInt32 flags = sobj->GetKey()->GetUoid().GetLocation().GetFlags();
const plParticleSystem *sys = plParticleSystem::ConvertNoRef(sobj->GetModifierByType(plParticleSystem::Index()));
if (!sys)
return;
int num = sys->GetNumValidParticles(true);
dstState->FindVar(kStrNumParticles)->Set(num);
}
void plParticleSDLMod::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSceneObject* sobj=GetTarget();
if (!sobj)
return;
plParticleSystem *sys = const_cast<plParticleSystem*>(plParticleSystem::ConvertNoRef(sobj->GetModifierByType(plParticleSystem::Index())));
if (!sys)
return;
int num;
srcState->FindVar(kStrNumParticles)->Get(&num);
if (num > sys->GetMaxTotalParticles())
num = sys->GetMaxTotalParticles();
sys->WipeExistingParticles();
sys->GenerateParticles(num);
}
UInt32 plParticleSDLMod::IApplyModFlags(UInt32 sendFlags)
{
if (fAttachedToAvatar)
return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState);
return sendFlags;
}

View File

@ -1,60 +1,60 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleSDLMod_inc
#define plParticleSDLMod_inc
#include "plModifier/plSDLModifier.h"
//
// This modifier is responsible for sending and recving
// particle system state. Few need it. Little state is needed.
//
class plParticleSDLMod : public plSDLModifier
{
private:
bool fAttachedToAvatar;
protected:
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
UInt32 IApplyModFlags(UInt32 sendFlags);
public:
// var labels
static char kStrNumParticles[];
CLASSNAME_REGISTER( plParticleSDLMod );
GETINTERFACE_ANY( plParticleSDLMod, plSDLModifier);
plParticleSDLMod(bool attachedToAvatar = false): fAttachedToAvatar(attachedToAvatar) {}
void PutCurrentStateIn(plStateDataRecord* dstState);
const char* GetSDLName() const { return kSDLParticleSystem; }
void SetAttachedToAvatar(bool attached) {fAttachedToAvatar = attached;}
};
#endif // plParticleSDLMod_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleSDLMod_inc
#define plParticleSDLMod_inc
#include "plModifier/plSDLModifier.h"
//
// This modifier is responsible for sending and recving
// particle system state. Few need it. Little state is needed.
//
class plParticleSDLMod : public plSDLModifier
{
private:
bool fAttachedToAvatar;
protected:
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
UInt32 IApplyModFlags(UInt32 sendFlags);
public:
// var labels
static char kStrNumParticles[];
CLASSNAME_REGISTER( plParticleSDLMod );
GETINTERFACE_ANY( plParticleSDLMod, plSDLModifier);
plParticleSDLMod(bool attachedToAvatar = false): fAttachedToAvatar(attachedToAvatar) {}
void PutCurrentStateIn(plStateDataRecord* dstState);
const char* GetSDLName() const { return kSDLParticleSystem; }
void SetAttachedToAvatar(bool attached) {fAttachedToAvatar = attached;}
};
#endif // plParticleSDLMod_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,185 +1,185 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleSystem_inc
#define plParticleSystem_inc
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "pnModifier/plModifier.h"
#include "pnNetCommon/plSynchedValue.h"
#include "hsColorRGBA.h"
#include "hsMatrix44.h"
#include "plEffectTargetInfo.h"
class plPipeline;
class plParticle;
class plParticleGenerator;
class plSimpleParticleGenerator;
class plParticleEmitter;
class plParticleEffect;
class plParticleSDLMod;
class plController;
class hsGMaterial;
class plDrawableSpans;
class plDrawInterface;
class Mtl;
// This is responsible for creating and maintaining (allocation and update cycle) a related set of particles.
// Automatic particle generation is handled by the plParticleEmitters (one for each spawning location).
class plParticleSystem : public plModifier
{
friend plParticleEmitter;
friend plSimpleParticleGenerator;
protected:
static const hsScalar GRAVITY_ACCEL_FEET_PER_SEC2;
plSceneObject *fTarget;
hsGMaterial *fTexture; // One texture per system (Tiling is your friend!)
UInt32 fXTiles, fYTiles; // Width/height of the texture (in tiles) for determining a particle's UVs
double fCurrTime;
double fLastTime;
hsVector3 fAccel;
hsScalar fPreSim;
hsScalar fDrag;
hsScalar fWindMult;
bool fAttachedToAvatar;
UInt32 fMaxTotalParticles;
UInt32 fMaxTotalParticlesLeft;
UInt32 fNumValidEmitters;
UInt32 fMaxEmitters;
UInt32 fNextEmitterToGo;
plParticleEmitter **fEmitters; // Various locations we're emitting particles from (the first one is
// reserved for particles added explicitly (to keep all the bookkeeping
// in the hands of plParticleEmitter).
hsTArray<plParticleEffect *> fForces; // Global forces (wind/gravity/etc) that affect accelleration.
hsTArray<plParticleEffect *> fEffects; // Any other non-constraint effects.
hsTArray<plParticleEffect *> fConstraints; // Rigid body, collision, connectivity, etc.
plParticleContext fContext; // Rendering context passed to forces/effects/constraints.
hsTArray<plKey> fPermaLights; // Runtime lights assigned to this system. Currently don't support projected lights on particles.
// Material related animations, mapped over the course of a particle's life
plController *fAmbientCtl;
plController *fDiffuseCtl;
plController *fOpacityCtl;
plController *fWidthCtl;
plController *fHeightCtl;
plParticleSDLMod *fParticleSDLMod;
hsBool IShouldUpdate(plPipeline* pipe) const;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty); // required by plModifier
void IHandleRenderMsg(plPipeline* pipe);
plDrawInterface* ICheckDrawInterface();
void IAddEffect(plParticleEffect *effect, UInt32 type);
void IReadEffectsArray(hsTArray<plParticleEffect *> &effects, UInt32 type, hsStream *s, hsResMgr *mgr);
void IPreSim();
public:
plParticleSystem();
virtual ~plParticleSystem();
void Init(UInt32 xTiles, UInt32 yTiles, UInt32 maxTotalParticles, UInt32 numEmitters,
plController *ambientCtl, plController *diffuseCtl, plController *opacityCtl,
plController *widthCtl, plController *heightCtl);
enum effectType
{
kEffectForce = 0x1,
kEffectMisc = 0x2,
kEffectConstraint = 0x4,
};
enum miscFlags
{
kParticleSystemAlwaysUpdate = 0x1
};
UInt8 fMiscFlags; // Not read/written (could be, but it's not needed yet.)
// There might not be enough particles available. this function returns the number of maxParticles that
// the emitter actually received.
UInt32 AddEmitter(UInt32 maxParticles, plParticleGenerator *gen, UInt32 emitterFlags);
plParticleEmitter* GetAvailEmitter();
CLASSNAME_REGISTER( plParticleSystem );
GETINTERFACE_ANY( plParticleSystem, plModifier);
// These are just public wrappers to the equivalent plParticleEmitter functions, provided for the purpose
// of adding particles to a system explicitly.
void AddParticle(hsPoint3 &pos, hsVector3 &velocity, UInt32 tileIndex,
hsScalar hSize, hsScalar vSize, hsScalar scale, hsScalar invMass, hsScalar life,
hsPoint3 &orientation, UInt32 miscFlags, hsScalar radsPerSec=0.f);
void GenerateParticles(UInt32 num, hsScalar dt = 0.f);
void WipeExistingParticles(); // Instant nuke
void KillParticles(hsScalar num, hsScalar timeToDie, UInt8 flags); // Sets a death timer. They'll get removed on the next update (if time has run out)
UInt16 StealParticlesFrom(plParticleSystem *victim, UInt16 num); // Returns the number of particles actually stolen
void TranslateAllParticles(hsPoint3 &amount); // Used to recenter the system when linking between ages.
void DisableGenerators();
UInt32 GetNumTiles() const { return fXTiles * fYTiles; }
void SetTileIndex(plParticle &particle, UInt32 index); // Sets the UV coordinates appropriate for the current texture
UInt32 GetNumValidParticles(hsBool immortalOnly = false) const; // Takes a bit longer if we want a count of immortal particles...
UInt32 GetMaxTotalParticles() const { return fMaxTotalParticles; }
const hsMatrix44 &GetLocalToWorld() const;
void SetAccel(const hsVector3& a) { fAccel = GRAVITY_ACCEL_FEET_PER_SEC2 * a; }
void SetGravity(hsScalar pct) { fAccel.Set(0, 0, -GRAVITY_ACCEL_FEET_PER_SEC2 * pct); }
void SetDrag(hsScalar d) { fDrag = -d; }
void SetWindMult(hsScalar m) { fWindMult = m; }
void SetPreSim(hsScalar time) { fPreSim = time; }
void UpdateGenerator(UInt32 paramID, hsScalar value);
plParticleGenerator *GetExportedGenerator() const;
const hsVector3& GetAccel() const { return fAccel; }
hsScalar GetDrag() const { return fDrag; }
hsScalar GetWindMult() const { return fWindMult; }
plParticleEffect *GetEffect(UInt16 type) const;
plParticleSDLMod* GetSDLMod() {return fParticleSDLMod;}
// Functions related to/required by plModifier
virtual int GetNumTargets() const { return fTarget ? 1 : 0; }
virtual plSceneObject* GetTarget(int w) const { hsAssert(w < 1, "Bad target"); return fTarget; }
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
void SetAttachedToAvatar(bool attached);
// Export only functions for building the system. Not supported at runtime.
// AddLight allows the particle system to remain in ignorant bliss about runtime lights
void AddLight(plKey liKey);
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plParticleSystem_inc
#define plParticleSystem_inc
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "pnModifier/plModifier.h"
#include "pnNetCommon/plSynchedValue.h"
#include "hsColorRGBA.h"
#include "hsMatrix44.h"
#include "plEffectTargetInfo.h"
class plPipeline;
class plParticle;
class plParticleGenerator;
class plSimpleParticleGenerator;
class plParticleEmitter;
class plParticleEffect;
class plParticleSDLMod;
class plController;
class hsGMaterial;
class plDrawableSpans;
class plDrawInterface;
class Mtl;
// This is responsible for creating and maintaining (allocation and update cycle) a related set of particles.
// Automatic particle generation is handled by the plParticleEmitters (one for each spawning location).
class plParticleSystem : public plModifier
{
friend plParticleEmitter;
friend plSimpleParticleGenerator;
protected:
static const hsScalar GRAVITY_ACCEL_FEET_PER_SEC2;
plSceneObject *fTarget;
hsGMaterial *fTexture; // One texture per system (Tiling is your friend!)
UInt32 fXTiles, fYTiles; // Width/height of the texture (in tiles) for determining a particle's UVs
double fCurrTime;
double fLastTime;
hsVector3 fAccel;
hsScalar fPreSim;
hsScalar fDrag;
hsScalar fWindMult;
bool fAttachedToAvatar;
UInt32 fMaxTotalParticles;
UInt32 fMaxTotalParticlesLeft;
UInt32 fNumValidEmitters;
UInt32 fMaxEmitters;
UInt32 fNextEmitterToGo;
plParticleEmitter **fEmitters; // Various locations we're emitting particles from (the first one is
// reserved for particles added explicitly (to keep all the bookkeeping
// in the hands of plParticleEmitter).
hsTArray<plParticleEffect *> fForces; // Global forces (wind/gravity/etc) that affect accelleration.
hsTArray<plParticleEffect *> fEffects; // Any other non-constraint effects.
hsTArray<plParticleEffect *> fConstraints; // Rigid body, collision, connectivity, etc.
plParticleContext fContext; // Rendering context passed to forces/effects/constraints.
hsTArray<plKey> fPermaLights; // Runtime lights assigned to this system. Currently don't support projected lights on particles.
// Material related animations, mapped over the course of a particle's life
plController *fAmbientCtl;
plController *fDiffuseCtl;
plController *fOpacityCtl;
plController *fWidthCtl;
plController *fHeightCtl;
plParticleSDLMod *fParticleSDLMod;
hsBool IShouldUpdate(plPipeline* pipe) const;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty); // required by plModifier
void IHandleRenderMsg(plPipeline* pipe);
plDrawInterface* ICheckDrawInterface();
void IAddEffect(plParticleEffect *effect, UInt32 type);
void IReadEffectsArray(hsTArray<plParticleEffect *> &effects, UInt32 type, hsStream *s, hsResMgr *mgr);
void IPreSim();
public:
plParticleSystem();
virtual ~plParticleSystem();
void Init(UInt32 xTiles, UInt32 yTiles, UInt32 maxTotalParticles, UInt32 numEmitters,
plController *ambientCtl, plController *diffuseCtl, plController *opacityCtl,
plController *widthCtl, plController *heightCtl);
enum effectType
{
kEffectForce = 0x1,
kEffectMisc = 0x2,
kEffectConstraint = 0x4,
};
enum miscFlags
{
kParticleSystemAlwaysUpdate = 0x1
};
UInt8 fMiscFlags; // Not read/written (could be, but it's not needed yet.)
// There might not be enough particles available. this function returns the number of maxParticles that
// the emitter actually received.
UInt32 AddEmitter(UInt32 maxParticles, plParticleGenerator *gen, UInt32 emitterFlags);
plParticleEmitter* GetAvailEmitter();
CLASSNAME_REGISTER( plParticleSystem );
GETINTERFACE_ANY( plParticleSystem, plModifier);
// These are just public wrappers to the equivalent plParticleEmitter functions, provided for the purpose
// of adding particles to a system explicitly.
void AddParticle(hsPoint3 &pos, hsVector3 &velocity, UInt32 tileIndex,
hsScalar hSize, hsScalar vSize, hsScalar scale, hsScalar invMass, hsScalar life,
hsPoint3 &orientation, UInt32 miscFlags, hsScalar radsPerSec=0.f);
void GenerateParticles(UInt32 num, hsScalar dt = 0.f);
void WipeExistingParticles(); // Instant nuke
void KillParticles(hsScalar num, hsScalar timeToDie, UInt8 flags); // Sets a death timer. They'll get removed on the next update (if time has run out)
UInt16 StealParticlesFrom(plParticleSystem *victim, UInt16 num); // Returns the number of particles actually stolen
void TranslateAllParticles(hsPoint3 &amount); // Used to recenter the system when linking between ages.
void DisableGenerators();
UInt32 GetNumTiles() const { return fXTiles * fYTiles; }
void SetTileIndex(plParticle &particle, UInt32 index); // Sets the UV coordinates appropriate for the current texture
UInt32 GetNumValidParticles(hsBool immortalOnly = false) const; // Takes a bit longer if we want a count of immortal particles...
UInt32 GetMaxTotalParticles() const { return fMaxTotalParticles; }
const hsMatrix44 &GetLocalToWorld() const;
void SetAccel(const hsVector3& a) { fAccel = GRAVITY_ACCEL_FEET_PER_SEC2 * a; }
void SetGravity(hsScalar pct) { fAccel.Set(0, 0, -GRAVITY_ACCEL_FEET_PER_SEC2 * pct); }
void SetDrag(hsScalar d) { fDrag = -d; }
void SetWindMult(hsScalar m) { fWindMult = m; }
void SetPreSim(hsScalar time) { fPreSim = time; }
void UpdateGenerator(UInt32 paramID, hsScalar value);
plParticleGenerator *GetExportedGenerator() const;
const hsVector3& GetAccel() const { return fAccel; }
hsScalar GetDrag() const { return fDrag; }
hsScalar GetWindMult() const { return fWindMult; }
plParticleEffect *GetEffect(UInt16 type) const;
plParticleSDLMod* GetSDLMod() {return fParticleSDLMod;}
// Functions related to/required by plModifier
virtual int GetNumTargets() const { return fTarget ? 1 : 0; }
virtual plSceneObject* GetTarget(int w) const { hsAssert(w < 1, "Bad target"); return fTarget; }
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
void SetAttachedToAvatar(bool attached);
// Export only functions for building the system. Not supported at runtime.
// AddLight allows the particle system to remain in ignorant bliss about runtime lights
void AddLight(plKey liKey);
};
#endif