2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

CWE Directory Reorganization

Rearrange directory structure of CWE to be loosely equivalent to
the H'uru Plasma repository.

Part 1: Movement of directories and files.
This commit is contained in:
rarified
2021-05-15 12:49:46 -06:00
parent c3f4a640a3
commit 96903e8dca
4002 changed files with 159 additions and 644 deletions

View File

@ -0,0 +1,88 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 pfAnimationCreatable_inc
#define pfAnimationCreatable_inc
#include "../pnFactory/plCreator.h"
#include "plViewFaceModifier.h"
REGISTER_CREATABLE( plViewFaceModifier );
#include "plLineFollowMod.h"
REGISTER_CREATABLE( plLineFollowMod );
REGISTER_CREATABLE( plRailCameraMod );
#include "plLightModifier.h"
REGISTER_CREATABLE( plLightModifier );
REGISTER_CREATABLE( plOmniModifier );
REGISTER_CREATABLE( plSpotModifier );
REGISTER_CREATABLE( plLtdDirModifier );
#include "plRandomCommandMod.h"
REGISTER_NONCREATABLE( plRandomCommandMod );
#include "plFollowMod.h"
REGISTER_CREATABLE( plFollowMod );
#include "plBlower.h"
REGISTER_CREATABLE( plBlower );
#include "plFilterCoordInterface.h"
REGISTER_CREATABLE( plFilterCoordInterface );
#include "plStereizer.h"
REGISTER_CREATABLE( plStereizer );
#include "pfObjectFlocker.h"
REGISTER_CREATABLE( pfObjectFlocker );
#endif // pfAnimationCreatable_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,454 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 OBJECT_FLOCKER_H
#define OBJECT_FLOCKER_H
#include "../pnModifier/plSingleModifier.h"
class hsStream;
class hsResMgr;
class plRandom;
class pfObjectFlocker;
// Database tokens for our prox database
template <class T>
class pfTokenForProximityDatabase
{
public:
virtual ~pfTokenForProximityDatabase() {}
// call this when your position changes
virtual void UpdateWithNewPosition(const hsPoint3 &newPos) = 0;
// find all close-by objects (determined by center and radius)
virtual void FindNeighbors(const hsPoint3 &center, const float radius, std::vector<T> &results) = 0;
};
// A basic prox database (might need to be optimized in the future)
template <class T>
class pfBasicProximityDatabase
{
public:
class tokenType;
typedef std::vector<tokenType*> tokenVector;
typedef typename tokenVector::const_iterator tokenIterator;
// "token" to represent objects stored in the database
class tokenType: public pfTokenForProximityDatabase<T>
{
private:
tokenVector& fTokens;
T fParent;
hsPoint3 fPosition;
public:
// constructor
tokenType(T parentObject, tokenVector& tokens) : fParent(parentObject), fTokens(tokens)
{
fTokens.push_back(this);
}
// destructor
virtual ~tokenType()
{
// remove this token from the database's vector
fTokens.erase(std::find(fTokens.begin(), fTokens.end(), this));
}
// call this when your position changes
void UpdateWithNewPosition(const hsPoint3 &newPosition) {fPosition = newPosition;}
// find all close-by objects (determined by center and radius)
void FindNeighbors(const hsPoint3 &center, const float radius, std::vector<T> & results)
{
// take the slow way, loop and check every one
const float radiusSquared = radius * radius;
for (tokenIterator i = fTokens.begin(); i != fTokens.end(); i++)
{
const hsVector3 offset(&center, &((**i).fPosition));
const float distanceSquared = offset.MagnitudeSquared();
// push onto result vector when within given radius
if (distanceSquared < radiusSquared)
results.push_back((**i).fParent);
}
}
};
private:
// STL vector containing all tokens in database
tokenVector fGroup;
public:
// constructor
pfBasicProximityDatabase(void) {}
// destructor
virtual ~pfBasicProximityDatabase() {}
// allocate a token to represent a given client object in this database
tokenType *MakeToken(T parentObject) {return TRACKED_NEW tokenType(parentObject, fGroup);}
// return the number of tokens currently in the database
int Size(void) {return group.size();}
};
// A basic vehicle class that handles accelleration, braking, and turning
class pfVehicle
{
private:
hsPoint3 fPos; // position in meters
hsPoint3 fLastPos; // the last position we had
hsPoint3 fSmoothedPosition;
hsVector3 fVel; // velocity in meters/second
hsVector3 fSmoothedAcceleration;
hsVector3 fForward; // forward vector (unit length)
hsVector3 fLastForward; // the last forward vector we had
hsVector3 fSide; // side vector (unit length)
hsVector3 fUp; // up vector (unit length)
float fSpeed; // speed (length of velocity vector)
float fMass; // mass of the object (defaults to 1)
float fMaxForce; // the maximum steering force that can be applied
float fMaxSpeed; // the maximum speed of this vehicle
float fCurvature;
float fSmoothedCurvature;
float fRadius;
// measure the path curvature (1/turning radius), maintain smoothed version
void IMeasurePathCurvature(const float elapsedTime);
public:
pfVehicle() {Reset();}
virtual ~pfVehicle() {}
void Reset();
// get/set attributes
float Mass() const {return fMass;}
float SetMass(float m) {return fMass = m;}
hsVector3 Forward() const {return fForward;}
hsVector3 SetForward(hsVector3 forward) {return fForward = forward;}
hsVector3 Side() const {return fSide;}
hsVector3 SetSide(hsVector3 side) {return fSide = side;}
hsVector3 Up() const {return fUp;}
hsVector3 SetUp(hsVector3 up) {return fUp = up;}
hsPoint3 Position() const {return fPos;}
hsPoint3 SetPosition(hsPoint3 pos) {return fPos = pos;}
hsVector3 Velocity() const {return Forward() * fSpeed;}
float Speed() const {return fSpeed;}
float SetSpeed(float speed) {return fSpeed = speed;}
float MaxForce() const {return fMaxForce;}
float SetMaxForce(float maxForce) {return fMaxForce = maxForce;}
float MaxSpeed() const {return fMaxSpeed;}
float SetMaxSpeed(float maxSpeed) {return fMaxSpeed = maxSpeed;}
float Curvature() const {return fCurvature;}
float SmoothedCurvature() {return fSmoothedCurvature;}
float ResetSmoothedCurvature(float value = 0);
hsVector3 SmoothedAcceleration() {return fSmoothedAcceleration;}
hsVector3 ResetSmoothedAcceleration(const hsVector3 &value = hsVector3(0,0,0));
hsPoint3 SmoothedPosition() {return fSmoothedPosition;}
hsPoint3 ResetSmoothedPosition(const hsPoint3 &value = hsPoint3(0,0,0));
float Radius() const {return fRadius;}
float SetRadius(float radius) {return fRadius = radius;}
// Basic geometry functions
// Reset local space to identity
void ResetLocalSpace();
// Set the side vector to a normalized cross product of forward and up
void SetUnitSideFromForwardAndUp();
// Regenerate orthonormal basis vectors given a new forward vector (unit length)
void RegenerateOrthonormalBasisUF(const hsVector3 &newUnitForward);
// If the new forward is NOT known to have unit length
void RegenerateOrthonormalBasis(const hsVector3 &newForward)
{hsVector3 temp = newForward; temp.Normalize(); RegenerateOrthonormalBasisUF(temp);}
// For supplying both a new forward, and a new up
void RegenerateOrthonormalBasis(const hsVector3 &newForward, const hsVector3 &newUp)
{fUp = newUp; RegenerateOrthonormalBasis(newForward);}
// Keep forward parallel to velocity, change up as little as possible
virtual void RegenerateLocalSpace(const hsVector3 &newVelocity, const float elapsedTime);
// Keep forward parallel to velocity, but "bank" the up vector
void RegenerateLocalSpaceForBanking(const hsVector3 &newVelocity, const float elapsedTime);
// Vehicle physics functions
// apply a steering force to our momentum and adjust our
// orientation to match our velocity vector
void ApplySteeringForce(const hsVector3 &force, const float deltaTime);
// adjust the steering force passed to ApplySteeringForce (so sub-classes can refine)
// by default, we won't allow backward-facing steering at a low speed
virtual hsVector3 AdjustRawSteeringForce(const hsVector3 &force, const float deltaTime);
// apply a braking force
void ApplyBrakingForce(const float rate, const float deltaTime);
// predict the position of the vehicle (assumes constant velocity)
hsPoint3 PredictFuturePosition(const float predictionTime);
};
// A goal object, basically keeps track of a scene object so we can get velocity from it
class pfBoidGoal
{
private:
hsPoint3 fLastPos;
hsPoint3 fCurPos;
hsVector3 fForward;
float fSpeed; // in meters/sec
hsBool fHasLastPos; // does the last position make sense?
public:
pfBoidGoal();
~pfBoidGoal() {}
void Update(plSceneObject *goal, float deltaTime);
hsPoint3 Position() const {return fCurPos;}
float Speed() const {return fSpeed;}
hsVector3 Forward() const {return fForward;}
hsPoint3 PredictFuturePosition(const float predictionTime);
};
typedef pfTokenForProximityDatabase<pfVehicle*> pfProximityToken;
typedef pfBasicProximityDatabase<pfVehicle*> pfProximityDatabase;
// The actual "flocking following" (not really a boid, but whatever)
class pfBoid: public pfVehicle
{
private:
plKey fObjKey;
float fWanderSide;
float fWanderUp;
float fGoalWeight;
float fRandomWeight;
float fSeparationRadius;
float fSeparationAngle;
float fSeparationWeight;
float fCohesionRadius;
float fCohesionAngle;
float fCohesionWeight;
pfProximityToken* fProximityToken;
std::vector<pfVehicle*> fNeighbors;
// Set our flocking settings to default
void IFlockDefaults();
// Setup our prox database token
void ISetupToken(pfProximityDatabase &pd);
// Are we in the neighborhood of another boid?
hsBool IInBoidNeighborhood(const pfVehicle &other, const float minDistance, const float maxDistance, const float cosMaxAngle);
// Wander steering
hsVector3 ISteerForWander(float timeDelta);
// Seek the target point
hsVector3 ISteerForSeek(const hsPoint3 &target);
// Steer the boid toward our goal
hsVector3 ISteerToGoal(pfBoidGoal &goal, float maxPredictionTime);
// Steer to keep separation
hsVector3 ISteerForSeparation(const float maxDistance, const float cosMaxAngle, const std::vector<pfVehicle*> &flock);
// Steer to keep the flock together
hsVector3 ISteerForCohesion(const float maxDistance, const float cosMaxAngle, const std::vector<pfVehicle*> &flock);
public:
pfObjectFlocker *fFlockerPtr;
pfBoid(pfProximityDatabase &pd, pfObjectFlocker *flocker, plKey &key);
pfBoid(pfProximityDatabase &pd, pfObjectFlocker *flocker, plKey &key, hsPoint3 &pos);
pfBoid(pfProximityDatabase &pd, pfObjectFlocker *flocker, plKey &key, hsPoint3 &pos, float speed, hsVector3 &forward, hsVector3 &side, hsVector3 &up);
virtual ~pfBoid();
// Get/set functions
float GoalWeight() const {return fGoalWeight;}
float SetGoalWeight(float goalWeight) {return fGoalWeight = goalWeight;}
float WanderWeight() const {return fRandomWeight;}
float SetWanderWeight(float wanderWeight) {return fRandomWeight = wanderWeight;}
float SeparationWeight() const {return fSeparationWeight;}
float SetSeparationWeight(float weight) {return fSeparationWeight = weight;}
float SeparationRadius() const {return fSeparationRadius;}
float SetSeparationRadius(float radius) {return fSeparationRadius = radius;}
float CohesionWeight() const {return fCohesionWeight;}
float SetCohesionWeight(float weight) {return fCohesionWeight = weight;}
float CohesionRadius() const {return fCohesionRadius;}
float SetCohesionRadius(float radius) {return fCohesionRadius = radius;}
// Update the boid's data based on the goal and time delta
void Update(pfBoidGoal &goal, float deltaTime);
plKey &GetKey() {return fObjKey;}
// We're redirecting this to the "banking" function
virtual void RegenerateLocalSpace(const hsVector3 &newVelocity, const float elapsedTime);
};
class pfFlock
{
private:
std::vector<pfBoid*> fBoids;
pfBoidGoal fBoidGoal;
pfProximityDatabase *fDatabase;
// global values so when we add a boid we can set it's parameters
float fGoalWeight, fRandomWeight;
float fSeparationWeight, fSeparationRadius;
float fCohesionWeight, fCohesionRadius;
float fMaxForce; // max steering force
float fMaxSpeed, fMinSpeed;
public:
pfFlock();
~pfFlock();
// Get/set functions (affect the whole flock, and any new boids added)
float GoalWeight() const {return fGoalWeight;}
void SetGoalWeight(float goalWeight);
float WanderWeight() const {return fRandomWeight;}
void SetWanderWeight(float wanderWeight);
float SeparationWeight() const {return fSeparationWeight;}
void SetSeparationWeight(float weight);
float SeparationRadius() const {return fSeparationRadius;}
void SetSeparationRadius(float radius);
float CohesionWeight() const {return fCohesionWeight;}
void SetCohesionWeight(float weight);
float CohesionRadius() const {return fCohesionRadius;}
void SetCohesionRadius(float radius);
float MaxForce() const {return fMaxForce;}
void SetMaxForce(float force);
float MaxSpeed() const {return fMaxSpeed;}
void SetMaxSpeed(float speed);
float MinSpeed() const {return fMinSpeed;}
void SetMinSpeed(float minSpeed);
// setup/run functions
void AddBoid(pfObjectFlocker *flocker, plKey &key, hsPoint3 &pos);
void Update(plSceneObject *goal, float deltaTime);
pfBoid *GetBoid(int i);
friend class pfObjectFlocker;
};
class pfObjectFlocker : public plSingleModifier
{
public:
pfObjectFlocker();
~pfObjectFlocker();
CLASSNAME_REGISTER( pfObjectFlocker );
GETINTERFACE_ANY( pfObjectFlocker, plSingleModifier );
virtual void SetTarget(plSceneObject* so);
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetNumBoids(UInt8 val);
void SetBoidKey(plKey key) { fBoidKey = key; }
float GoalWeight() const {return fFlock.GoalWeight();}
void SetGoalWeight(float goalWeight) {fFlock.SetGoalWeight(goalWeight);}
float WanderWeight() const {return fFlock.WanderWeight();}
void SetWanderWeight(float wanderWeight) {fFlock.SetWanderWeight(wanderWeight);}
float SeparationWeight() const {return fFlock.SeparationWeight();}
void SetSeparationWeight(float weight) {fFlock.SetSeparationWeight(weight);}
float SeparationRadius() const {return fFlock.SeparationRadius();}
void SetSeparationRadius(float radius) {fFlock.SetSeparationRadius(radius);}
float CohesionWeight() const {return fFlock.CohesionWeight();}
void SetCohesionWeight(float weight) {fFlock.SetCohesionWeight(weight);}
float CohesionRadius() const {return fFlock.CohesionRadius();}
void SetCohesionRadius(float radius) {fFlock.SetCohesionRadius(radius);}
float MaxForce() const {return fFlock.MaxForce();}
void SetMaxForce(float force) {fFlock.SetMaxForce(force);}
float MaxSpeed() const {return fFlock.MaxSpeed();}
void SetMaxSpeed(float speed) {fFlock.SetMaxSpeed(speed);}
float MinSpeed() const {return fFlock.MinSpeed();}
void SetMinSpeed(float minSpeed) {fFlock.SetMinSpeed(minSpeed);}
hsBool RandomizeAnimStart() const {return fRandomizeAnimationStart;}
void SetRandomizeAnimStart(hsBool val) {fRandomizeAnimationStart = val;}
hsBool UseTargetRotation() const {return fUseTargetRotation;}
void SetUseTargetRotation(hsBool val) {fUseTargetRotation = val;}
protected:
const static int fFileVersion; // so we don't have to update the global version number when we change
pfFlock fFlock;
int fNumBoids;
plKey fBoidKey;
hsBool fUseTargetRotation;
hsBool fRandomizeAnimationStart;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
};
#endif

View File

@ -0,0 +1,165 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "hsStlUtils.h"
#include "hsResMgr.h"
#include "hsTemplates.h"
#include "hsTimer.h"
#include "plAnimDebugList.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerAnimation.h"
#include "../plAvatar/plAGMasterMod.h"
#include "../plAvatar/plAGAnimInstance.h"
#include "../plAvatar/plAGAnim.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plPipeline/plDebugText.h"
void plAnimDebugList::AddObjects(char *subString)
{
std::vector<plKey> keys;
std::vector<plKey>::iterator i;
plKeyFinder::Instance().ReallyStupidSubstringSearch(subString, hsGMaterial::Index(), keys);
for (i = keys.begin(); i != keys.end(); i++)
{
if (fMaterialKeys.Find((*i)) == fMaterialKeys.kMissingIndex)
fMaterialKeys.Append((*i));
}
keys.clear();
plKeyFinder::Instance().ReallyStupidSubstringSearch(subString, plSceneObject::Index(), keys);
for (i = keys.begin(); i != keys.end(); i++)
{
plSceneObject *so = plSceneObject::ConvertNoRef((*i)->ObjectIsLoaded());
if (so)
{
const plAGMasterMod *agMod = plAGMasterMod::ConvertNoRef(so->GetModifierByType(plAGMasterMod::Index()));
if (agMod && fSOKeys.Find(so->GetKey()) == fSOKeys.kMissingIndex)
fSOKeys.Append(so->GetKey());
}
}
}
void plAnimDebugList::RemoveObjects(char *subString)
{
int i;
for (i = fMaterialKeys.GetCount() - 1; i >= 0; i--)
{
if (strstr(fMaterialKeys[i]->GetName(), subString))
fMaterialKeys.Remove(i);
}
for (i = fSOKeys.GetCount() - 1; i >= 0; i--)
{
if (strstr(fSOKeys[i]->GetName(), subString))
fSOKeys.Remove(i);
}
}
void plAnimDebugList::ShowReport()
{
if (!fEnabled)
return;
plDebugText &txt = plDebugText::Instance();
int y,x,i,j;
const int yOff=10, startY=40, startX=10;
char str[256];
x = startX;
y = startY;
txt.DrawString(x, y, "Material Animations:", 255, 255, 255, 255, plDebugText::kStyleBold);
y += yOff;
for (i = 0; i < fMaterialKeys.GetCount(); i++)
{
hsGMaterial *mat = hsGMaterial::ConvertNoRef(fMaterialKeys[i]->ObjectIsLoaded());
if (!mat)
continue;
for (j = 0; j < mat->GetNumLayers(); j++)
{
plLayerInterface *layer = mat->GetLayer(j)->BottomOfStack();
while (layer != nil)
{
plLayerAnimation *layerAnim = plLayerAnimation::ConvertNoRef(layer);
if (layerAnim)
{
sprintf(str, "%s: %s %.3f (%.3f)", mat->GetKeyName(), layerAnim->GetKeyName(),
layerAnim->GetTimeConvert().CurrentAnimTime(),
layerAnim->GetTimeConvert().WorldToAnimTimeNoUpdate(hsTimer::GetSysSeconds()));
txt.DrawString(x, y, str);
y += yOff;
}
layer = layer->GetOverLay();
}
}
}
y += yOff;
txt.DrawString(x, y, "AGMaster Anims", 255, 255, 255, 255, plDebugText::kStyleBold);
y += yOff;
for (i = 0; i < fSOKeys.GetCount(); i++)
{
plSceneObject *so = plSceneObject::ConvertNoRef(fSOKeys[i]->ObjectIsLoaded());
if (!so)
continue;
plAGMasterMod *mod = const_cast<plAGMasterMod*>(plAGMasterMod::ConvertNoRef(so->GetModifierByType(plAGMasterMod::Index())));
if (!mod)
continue;
sprintf(str, " %s", so->GetKeyName());
txt.DrawString(x, y, str);
y += yOff;
for (j = 0; j < mod->GetNumATCAnimations(); j++)
{
plAGAnimInstance *anim = mod->GetATCAnimInstance(j);
sprintf(str, " %s: %.3f (%.3f)", anim->GetAnimation()->GetName(),
anim->GetTimeConvert()->CurrentAnimTime(),
anim->GetTimeConvert()->WorldToAnimTimeNoUpdate(hsTimer::GetSysSeconds()));
txt.DrawString(x, y, str);
y += yOff;
}
}
}

View File

@ -0,0 +1,63 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plAnimDebugList_inc
#define plAnimDebugList_inc
// Simple debugging tool, everything is public
// This class collects a list of keyed objects that deal with
// animation, to report info on them when requested.
class plAnimDebugList
{
public:
hsBool fEnabled;
hsTArray<plKey> fSOKeys;
hsTArray<plKey> fMaterialKeys;
plAnimDebugList() : fEnabled(false) {}
~plAnimDebugList() {}
void AddObjects(char *subString);
void RemoveObjects(char *subString);
void ShowReport();
};
#endif

View File

@ -0,0 +1,240 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "plBlower.h"
#include "plgDispatch.h"
#include "hsFastMath.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnMessage/plTimeMsg.h"
#include "hsTimer.h"
plRandom plBlower::fRandom;
static const hsScalar kDefaultMasterPower = 20.f;
static const hsScalar kDefaultMasterFrequency = 2.f;
static const hsScalar kDefaultDirectRate = 1.f;
static const hsScalar kDefaultImpulseRate = 1.e2f;
static const hsScalar kDefaultSpringKonst = 20.f;
static const hsScalar kDefaultBias = 0.25f;
static const hsScalar kInitialMaxOffDist = 1.f;
plBlower::plBlower()
:
fMasterPower(kDefaultMasterPower),
fMasterFrequency(kDefaultMasterFrequency),
fDirectRate(kDefaultDirectRate),
fImpulseRate(kDefaultImpulseRate),
fSpringKonst(kDefaultSpringKonst),
fBias(kDefaultBias),
fMaxOffsetDist(kInitialMaxOffDist),
fAccumTime(0)
{
fRestPos.Set(0,0,0);
fLocalRestPos.Set(0,0,0);
fCurrDel.Set(0,0,0);
fDirection.Set(fRandom.RandMinusOneToOne(), fRandom.RandMinusOneToOne(), 0);
hsFastMath::NormalizeAppr(fDirection);
}
plBlower::~plBlower()
{
}
void plBlower::IBlow(double secs, hsScalar delSecs)
{
hsPoint3 worldPos = fTarget->GetLocalToWorld().GetTranslate();
hsPoint3 localPos = fTarget->GetLocalToParent().GetTranslate();
// fast oscillation vs slow
// Completely random walk in the rotation
// Strength = Strength + rnd01 * (MaxStrength - Strength)
hsScalar t = (fAccumTime += delSecs);
hsScalar strength = 0;
int i;
for( i = 0; i < fOscillators.GetCount(); i++ )
{
hsScalar c, s;
t *= fOscillators[i].fFrequency * fMasterFrequency;
t += fOscillators[i].fPhase;
hsFastMath::SinCosAppr(t, s, c);
c += fBias;
strength += c * fOscillators[i].fPower;
}
strength *= fMasterPower;
if( strength < 0 )
strength = 0;
fDirection.fX += fRandom.RandMinusOneToOne() * delSecs * fDirectRate;
fDirection.fY += fRandom.RandMinusOneToOne() * delSecs * fDirectRate;
hsFastMath::NormalizeAppr(fDirection);
hsScalar offDist = hsVector3(&fRestPos, &worldPos).Magnitude();
if( offDist > fMaxOffsetDist )
fMaxOffsetDist = offDist;
hsVector3 force = fDirection * strength;
static hsScalar kOffsetDistFrac = 0.5f; // make me const
if( offDist > fMaxOffsetDist * kOffsetDistFrac )
{
offDist /= fMaxOffsetDist;
offDist *= fMasterPower;
hsScalar impulse = offDist * delSecs * fImpulseRate;
force.fX += impulse * fRandom.RandMinusOneToOne();
force.fY += impulse * fRandom.RandMinusOneToOne();
force.fZ += impulse * fRandom.RandMinusOneToOne();
}
const hsScalar kOffsetDistDecay = 0.999f;
fMaxOffsetDist *= kOffsetDistDecay;
hsVector3 accel = force;
accel += fSpringKonst * hsVector3(&fLocalRestPos, &localPos);
hsVector3 del = accel * (delSecs * delSecs);
fCurrDel = del;
}
hsBool plBlower::IEval(double secs, hsScalar delSecs, UInt32 dirty)
{
const hsScalar kMaxDelSecs = 0.1f;
if( delSecs > kMaxDelSecs )
delSecs = kMaxDelSecs;
IBlow(secs, delSecs);
ISetTargetTransform();
return true;
}
void plBlower::ISetTargetTransform()
{
plCoordinateInterface* ci = IGetTargetCoordinateInterface(0);
if( ci )
{
hsMatrix44 l2p = ci->GetLocalToParent();
hsMatrix44 p2l = ci->GetParentToLocal();
hsPoint3 pos = l2p.GetTranslate();
pos += fCurrDel;
l2p.SetTranslate(&pos);
p2l.SetTranslate(&-pos);
ci->SetLocalToParent(l2p, p2l);
}
}
void plBlower::SetTarget(plSceneObject* so)
{
plSingleModifier::SetTarget(so);
if( fTarget )
{
fRestPos = fTarget->GetLocalToWorld().GetTranslate();
fLocalRestPos = fTarget->GetLocalToParent().GetTranslate();
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
IInitOscillators();
}
void plBlower::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
fMasterPower = s->ReadSwapScalar();
fDirectRate = s->ReadSwapScalar();
fImpulseRate = s->ReadSwapScalar();
fSpringKonst = s->ReadSwapScalar();
}
void plBlower::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
s->WriteSwapScalar(fMasterPower);
s->WriteSwapScalar(fDirectRate);
s->WriteSwapScalar(fImpulseRate);
s->WriteSwapScalar(fSpringKonst);
}
void plBlower::IInitOscillators()
{
const hsScalar kBasePower = 5.f;
fOscillators.SetCount(5);
int i;
for( i = 0; i < fOscillators.GetCount(); i++ )
{
hsScalar fi = hsScalar(i+1);
fOscillators[i].fFrequency = fi / hsScalarPI * fRandom.RandRangeF(0.75f, 1.25f);
// fOscillators[i].fFrequency = 1.f / hsScalarPI * fRandom.RandRangeF(0.5f, 1.5f);
fOscillators[i].fPhase = fRandom.RandZeroToOne();
fOscillators[i].fPower = kBasePower * fRandom.RandRangeF(0.75f, 1.25f);
}
}
void plBlower::SetConstancy(hsScalar f)
{
if( f < 0 )
f = 0;
else if( f > 1.f )
f = 1.f;
fBias = f;
}
hsScalar plBlower::GetConstancy() const
{
return fBias;
}

View File

@ -0,0 +1,117 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plBlower_inc
#define plBlower_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsGeometry3.h"
#include "../plMath/plRandom.h"
#include "hsTemplates.h"
class plSceneObject;
class hsStream;
class hsResMgr;
class plBlower : public plSingleModifier
{
protected:
class Oscillator
{
public:
hsScalar fFrequency;
hsScalar fPhase;
hsScalar fPower;
};
static plRandom fRandom;
// Parameters
hsScalar fMasterPower;
hsScalar fMasterFrequency;
hsScalar fDirectRate;
hsScalar fImpulseRate;
hsScalar fSpringKonst;
hsScalar fBias;
hsScalar fAccumTime;
hsTArray<Oscillator> fOscillators;
// CurrentState
hsVector3 fDirection;
hsPoint3 fRestPos;
hsPoint3 fLocalRestPos;
hsVector3 fCurrDel;
hsScalar fMaxOffsetDist;
void IInitOscillators();
void ISetTargetTransform();
void IBlow(double secs, hsScalar delSecs);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
public:
~plBlower();
plBlower();
CLASSNAME_REGISTER( plBlower );
GETINTERFACE_ANY( plBlower, plSingleModifier );
virtual void SetTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetMasterPower(hsScalar f) { fMasterPower = f; }
void SetMasterFrequency(hsScalar f) { fMasterFrequency = f; }
void SetDirectRate(hsScalar f) { fDirectRate = f; }
void SetImpulseRate(hsScalar f) { fImpulseRate = f; }
void SetSpringKonst(hsScalar f) { fSpringKonst = f; }
void SetConstancy(hsScalar f);
hsScalar GetMasterPower() const { return fMasterPower; }
hsScalar GetMasterFrequency() const { return fMasterFrequency; }
hsScalar GetDirectRate() const { return fDirectRate; }
hsScalar GetImpulseRate() const { return fImpulseRate; }
hsScalar GetSpringKonst() const { return fSpringKonst; }
hsScalar GetConstancy() const;
};
#endif // plBlower_inc

View File

@ -0,0 +1,149 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "plFilterCoordInterface.h"
#include "hsMatrix44.h"
#include "hsStream.h"
static hsMatrix44* InvTRS(const hsMatrix44& trs, hsMatrix44& inv)
{
inv.NotIdentity();
hsScalar invSSq[3];
invSSq[0] = 1.f / (trs.fMap[0][0] * trs.fMap[0][0] + trs.fMap[1][0] * trs.fMap[1][0] + trs.fMap[2][0] * trs.fMap[2][0]);
invSSq[1] = 1.f / (trs.fMap[0][1] * trs.fMap[0][1] + trs.fMap[1][1] * trs.fMap[1][1] + trs.fMap[2][1] * trs.fMap[2][1]);
invSSq[2] = 1.f / (trs.fMap[0][2] * trs.fMap[0][2] + trs.fMap[1][2] * trs.fMap[1][2] + trs.fMap[2][2] * trs.fMap[2][2]);
inv.fMap[0][0] = invSSq[0] * trs.fMap[0][0];
inv.fMap[0][1] = invSSq[0] * trs.fMap[1][0];
inv.fMap[0][2] = invSSq[0] * trs.fMap[2][0];
inv.fMap[0][3] = -(inv.fMap[0][0] * trs.fMap[0][3] + inv.fMap[0][1] * trs.fMap[1][3] + inv.fMap[0][2] * trs.fMap[2][3]);
inv.fMap[1][0] = invSSq[1] * trs.fMap[0][1];
inv.fMap[1][1] = invSSq[1] * trs.fMap[1][1];
inv.fMap[1][2] = invSSq[1] * trs.fMap[2][1];
inv.fMap[1][3] = -(inv.fMap[1][0] * trs.fMap[0][3] + inv.fMap[1][1] * trs.fMap[1][3] + inv.fMap[1][2] * trs.fMap[2][3]);
inv.fMap[2][0] = invSSq[2] * trs.fMap[0][2];
inv.fMap[2][1] = invSSq[2] * trs.fMap[1][2];
inv.fMap[2][2] = invSSq[2] * trs.fMap[2][2];
inv.fMap[2][3] = -(inv.fMap[2][0] * trs.fMap[0][3] + inv.fMap[2][1] * trs.fMap[1][3] + inv.fMap[2][2] * trs.fMap[2][3]);
inv.fMap[3][0] = inv.fMap[3][1] = inv.fMap[3][2] = 0;
inv.fMap[3][3] = 1.f;
return &inv;
}
plFilterCoordInterface::plFilterCoordInterface()
: fFilterMask(kNoRotation)
{
fRefParentLocalToWorld.Reset();
}
plFilterCoordInterface::~plFilterCoordInterface()
{
}
void plFilterCoordInterface::Read(hsStream* stream, hsResMgr* mgr)
{
plCoordinateInterface::Read(stream, mgr);
fFilterMask = stream->ReadSwap32();
fRefParentLocalToWorld.Read(stream);
}
void plFilterCoordInterface::Write(hsStream* stream, hsResMgr* mgr)
{
plCoordinateInterface::Write(stream, mgr);
stream->WriteSwap32(fFilterMask);
fRefParentLocalToWorld.Write(stream);
}
void plFilterCoordInterface::IRecalcTransforms()
{
if( !(fFilterMask && fParent) )
{
plCoordinateInterface::IRecalcTransforms();
return;
}
hsMatrix44 origL2W = fRefParentLocalToWorld * fLocalToParent;
fLocalToWorld = fParent->GetLocalToWorld() * fLocalToParent;
// Filter out the stuff we're discarding. Nothing fancy here,
// we're taking the simple (and fast) form and just stuffing in
// what we want to preserve based on our reference matrix.
if( fFilterMask & kNoTransX )
{
fLocalToWorld.fMap[0][3] = origL2W.fMap[0][3];
}
if( fFilterMask & kNoTransY )
{
fLocalToWorld.fMap[1][3] = origL2W.fMap[1][3];
}
if( fFilterMask & kNoTransZ )
{
fLocalToWorld.fMap[2][3] = origL2W.fMap[2][3];
}
if( fFilterMask & kNoRotation )
{
int i;
for( i = 0; i < 3; i++ )
{
int j;
for( j = 0; j < 3; j++ )
{
fLocalToWorld.fMap[i][j] = origL2W.fMap[i][j];
}
}
}
// Construct the inverse of local to world for world to local.
InvTRS(fLocalToWorld, fWorldToLocal);
}

View File

@ -0,0 +1,84 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plFilterCoordInterface_inc
#define plFilterCoordInterface_inc
#include "../pnSceneObject/plCoordinateInterface.h"
class plFilterCoordInterface : public plCoordinateInterface
{
public:
enum
{
kNoRotation = 0x1,
kNoTransX = 0x2,
kNoTransY = 0x4,
kNoTransZ = 0x8,
kNoMove = kNoTransX | kNoTransY | kNoTransZ,
kNoNothing = kNoRotation | kNoMove
};
protected:
UInt32 fFilterMask;
hsMatrix44 fRefParentLocalToWorld;
virtual void IRecalcTransforms();
public:
plFilterCoordInterface();
~plFilterCoordInterface();
CLASSNAME_REGISTER( plFilterCoordInterface );
GETINTERFACE_ANY( plFilterCoordInterface, plCoordinateInterface );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetFilterMask(UInt32 f) { fFilterMask = f; }
UInt32 GetFilterMask() const { return fFilterMask; }
void SetRefLocalToWorld(const hsMatrix44& m) { fRefParentLocalToWorld = m; }
const hsMatrix44& GetRefLocalToWorld() const { return fRefParentLocalToWorld; }
};
#endif // plFilterCoordInterface_inc

View File

@ -0,0 +1,298 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "plFollowMod.h"
#include "plgDispatch.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plMessage/plListenerMsg.h"
#include "../plMessage/plRenderMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plRefMsg.h"
#include "hsResMgr.h"
#include "plPipeline.h"
plFollowMod::plFollowMod()
: fLeader(nil), fMode(kPosition), fLeaderType(kLocalPlayer), fLeaderSet(false)
{
}
plFollowMod::~plFollowMod()
{
}
#include "plProfile.h"
plProfile_CreateTimer("FollowMod", "RenderSetup", FollowMod);
hsBool plFollowMod::MsgReceive(plMessage* msg)
{
plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
if( rend )
{
plProfile_BeginLap(FollowMod, this->GetKey()->GetUoid().GetObjectName());
fLeaderL2W = rend->Pipeline()->GetCameraToWorld();
fLeaderW2L = rend->Pipeline()->GetWorldToCamera();
fLeaderSet = true;
plProfile_EndLap(FollowMod, this->GetKey()->GetUoid().GetObjectName());
return true;
}
plListenerMsg* list = plListenerMsg::ConvertNoRef(msg);
if( list )
{
hsVector3 pos;
pos.Set(list->GetPosition().fX, list->GetPosition().fY, list->GetPosition().fZ);
fLeaderL2W.MakeTranslateMat(&pos);
fLeaderW2L.MakeTranslateMat(&-pos);
fLeaderSet = true;
return true;
}
plGenRefMsg* ref = plGenRefMsg::ConvertNoRef(msg);
if( ref )
{
switch( ref->fType )
{
case kRefLeader:
if( ref->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fLeader = plSceneObject::ConvertNoRef(ref->GetRef());
else if( ref->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fLeader = nil;
return true;
default:
hsAssert(false, "Unknown ref type to FollowMod");
break;
}
}
return plSingleModifier::MsgReceive(msg);
}
hsBool plFollowMod::ICheckLeader()
{
switch( fLeaderType )
{
case kLocalPlayer:
{
plSceneObject* player = plSceneObject::ConvertNoRef(plNetClientApp::GetInstance()->GetLocalPlayer());
if( player )
{
fLeaderL2W = player->GetLocalToWorld();
fLeaderW2L = player->GetWorldToLocal();
fLeaderSet = true;
}
else
fLeaderSet = false;
}
break;
case kObject:
if( fLeader )
{
fLeaderL2W = fLeader->GetLocalToWorld();
fLeaderW2L = fLeader->GetWorldToLocal();
fLeaderSet = true;
}
else
fLeaderSet = false;
break;
case kCamera:
break;
case kListener:
break;
}
return fLeaderSet;
}
void plFollowMod::IMoveTarget()
{
if( fMode == kFullTransform )
{
GetTarget()->SetTransform(fLeaderL2W, fLeaderW2L);
return;
}
hsMatrix44 l2w = GetTarget()->GetLocalToWorld();
hsMatrix44 w2l = GetTarget()->GetWorldToLocal();
if( fMode & kRotate )
{
int i, j;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
l2w.fMap[i][j] = fLeaderL2W.fMap[i][j];
w2l.fMap[i][j] = fLeaderW2L.fMap[i][j];
}
}
}
if( fMode & kPosition )
{
hsMatrix44 invMove;
invMove.Reset();
hsPoint3 newPos = fLeaderL2W.GetTranslate();
hsPoint3 newInvPos = fLeaderW2L.GetTranslate();
hsPoint3 oldPos = l2w.GetTranslate();
// l2w = newPosMat * -oldPosMat * l2w
// so w2l = w2l * inv-oldPosMat * invNewPosMat
if( fMode & kPositionX )
{
l2w.fMap[0][3] = newPos.fX;
invMove.fMap[0][3] = oldPos.fX - newPos.fX;
}
if( fMode & kPositionY )
{
l2w.fMap[1][3] = newPos.fY;
invMove.fMap[1][3] = oldPos.fY - newPos.fY;
}
if( fMode & kPositionZ )
{
l2w.fMap[2][3] = newPos.fZ;
invMove.fMap[2][3] = oldPos.fZ - newPos.fZ;
}
invMove.NotIdentity();
// InvMove must happen after rotation.
w2l = w2l * invMove;
}
l2w.NotIdentity();
w2l.NotIdentity();
#ifdef HS_DEBUGGING
//MFHORSE hackola
hsMatrix44 inv;
l2w.GetInverse(&inv);
#endif // HS_DEBUGGING
GetTarget()->SetTransform(l2w, w2l);
}
hsBool plFollowMod::IEval(double secs, hsScalar del, UInt32 dirty)
{
if( ICheckLeader() )
IMoveTarget();
return true;
}
void plFollowMod::SetTarget(plSceneObject* so)
{
plSingleModifier::SetTarget(so);
if( fTarget )
Activate();
else
Deactivate();
}
void plFollowMod::Activate()
{
switch( fLeaderType )
{
case kLocalPlayer:
break;
case kObject:
break;
case kCamera:
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
break;
case kListener:
plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey());
break;
}
if( fTarget )
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plFollowMod::Deactivate()
{
switch( fLeaderType )
{
case kLocalPlayer:
if( fTarget )
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
break;
case kObject:
if( fTarget )
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
break;
case kCamera:
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
break;
case kListener:
plgDispatch::Dispatch()->UnRegisterForExactType(plListenerMsg::Index(), GetKey());
break;
}
}
void plFollowMod::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
fLeaderType = FollowLeaderType(stream->ReadByte());
fMode = stream->ReadByte();
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefLeader), plRefFlags::kActiveRef);
// If active?
Activate();
}
void plFollowMod::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteByte(fLeaderType);
stream->WriteByte(fMode);
mgr->WriteKey(stream, fLeader);
}

View File

@ -0,0 +1,117 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plFollowMod_inc
#define plFollowMod_inc
#include "hsMatrix44.h"
#include "../pnModifier/plSingleModifier.h"
class plSceneObject;
class plMessage;
class hsStream;
class hsResMgr;
class plFollowMod : public plSingleModifier
{
public:
enum FollowRefs
{
kRefLeader
};
enum FollowLeaderType
{
kLocalPlayer,
kObject,
kCamera,
kListener
};
enum FollowModMode
{
kPositionX = 0x1,
kPositionY = 0x2,
kPositionZ = 0x4,
kPosition = (kPositionX | kPositionY | kPositionZ),
kRotate = 0x8,
kFullTransform = kPosition | kRotate
};
protected:
FollowLeaderType fLeaderType;
UInt8 fMode;
UInt8 fLeaderSet;
plSceneObject* fLeader; // may be nil if Leader isn't a sceneobject
hsMatrix44 fLeaderL2W;
hsMatrix44 fLeaderW2L;
hsBool ICheckLeader();
void IMoveTarget();
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
public:
plFollowMod();
~plFollowMod();
CLASSNAME_REGISTER( plFollowMod );
GETINTERFACE_ANY( plFollowMod, plSingleModifier );
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual void SetTarget(plSceneObject* so);
void SetType(FollowLeaderType t) { fLeaderType = t; }
FollowLeaderType GetType() const { return fLeaderType; }
void SetMode(UInt8 m) { fMode = m; }
UInt8 GetMode() const { return fMode; }
void Activate();
void Deactivate();
};
#endif // plFollowMod_inc

View File

@ -0,0 +1,429 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "plLightModifier.h"
#include "../plGLight/plLightInfo.h"
#include "../plInterp/plController.h"
#include "hsStream.h"
#include "hsResMgr.h"
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// Basic light
plLightModifier::plLightModifier()
: fLight(nil),
fColorCtl(nil),
fAmbientCtl(nil),
fSpecularCtl(nil)
{
}
plLightModifier::~plLightModifier()
{
delete fColorCtl;
fColorCtl = nil;
delete fAmbientCtl;
fAmbientCtl = nil;
delete fSpecularCtl;
fSpecularCtl = nil;
}
void plLightModifier::IClearCtls()
{
delete fColorCtl;
fColorCtl = nil;
delete fAmbientCtl;
fAmbientCtl = nil;
delete fSpecularCtl;
fSpecularCtl = nil;
}
void plLightModifier::AddTarget(plSceneObject* so)
{
plSimpleModifier::AddTarget(so);
if( so )
fLight = plLightInfo::ConvertNoRef(so->GetGenericInterface(plLightInfo::Index()));
else
fLight = nil;
}
void plLightModifier::RemoveTarget(plSceneObject* so)
{
if( so = fTarget )
fLight = nil;
plSimpleModifier::RemoveTarget(so);
}
void plLightModifier::Read(hsStream* s, hsResMgr* mgr)
{
plSimpleModifier::Read(s, mgr);
fColorCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fAmbientCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fSpecularCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
}
void plLightModifier::Write(hsStream* s, hsResMgr* mgr)
{
plSimpleModifier::Write(s, mgr);
mgr->WriteCreatable(s, fColorCtl);
mgr->WriteCreatable(s, fAmbientCtl);
mgr->WriteCreatable(s, fSpecularCtl);
}
void plLightModifier::IApplyDynamic()
{
hsColorRGBA col;
if( fLight != nil )
{
if( fColorCtl )
{
col.Set(0,0,0,1.f);
fColorCtl->Interp(fCurrentTime, &col);
fLight->SetDiffuse(col);
}
if( fAmbientCtl )
{
col.Set(0,0,0,1.f);
fAmbientCtl->Interp(fCurrentTime, &col);
fLight->SetAmbient(col);
}
if( fSpecularCtl )
{
col.Set(0,0,0,1.f);
fSpecularCtl->Interp(fCurrentTime, &col);
fLight->SetSpecular(col);
}
}
}
void plLightModifier::DefaultAnimation()
{
hsScalar len = MaxAnimLength(0);
fTimeConvert.SetBegin(0);
fTimeConvert.SetEnd(len);
fTimeConvert.SetLoopPoints(0, len);
fTimeConvert.Loop();
fTimeConvert.Start();
}
hsScalar plLightModifier::MaxAnimLength(hsScalar len) const
{
if( fColorCtl && (fColorCtl->GetLength() > len) )
len = fColorCtl->GetLength();
if( fAmbientCtl && (fAmbientCtl->GetLength() > len) )
len = fAmbientCtl->GetLength();
if( fSpecularCtl && (fSpecularCtl->GetLength() > len) )
len = fSpecularCtl->GetLength();
return len;
}
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// Omni Lights
plOmniModifier::plOmniModifier()
: fOmni(nil),
fAttenCtl(nil)
{
}
plOmniModifier::~plOmniModifier()
{
delete fAttenCtl;
fAttenCtl = nil;
}
void plOmniModifier::AddTarget(plSceneObject* so)
{
plLightModifier::AddTarget(so);
if( fLight )
fOmni = plOmniLightInfo::ConvertNoRef(fLight);
else
fOmni = nil;
}
void plOmniModifier::RemoveTarget(plSceneObject* so)
{
plLightModifier::RemoveTarget(so);
if( !fLight )
fOmni = nil;
}
void plOmniModifier::IClearCtls()
{
plLightModifier::IClearCtls();
delete fAttenCtl;
fAttenCtl = nil;
}
void plOmniModifier::Read(hsStream* s, hsResMgr* mgr)
{
plLightModifier::Read(s, mgr);
fAttenCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fInitAtten.Read(s);
}
void plOmniModifier::Write(hsStream* s, hsResMgr* mgr)
{
plLightModifier::Write(s, mgr);
mgr->WriteCreatable(s, fAttenCtl);
fInitAtten.Write(s);
}
void plOmniModifier::IApplyDynamic()
{
plLightModifier::IApplyDynamic();
if( fAttenCtl )
{
hsPoint3 p = fInitAtten;
fAttenCtl->Interp(fCurrentTime, &p);
fOmni->SetConstantAttenuation(p.fX);
fOmni->SetLinearAttenuation(p.fY);
fOmni->SetQuadraticAttenuation(p.fZ);
}
}
hsScalar plOmniModifier::MaxAnimLength(hsScalar len) const
{
len = plLightModifier::MaxAnimLength(len);
if( fAttenCtl && (fAttenCtl->GetLength() > len) )
len = fAttenCtl->GetLength();
return len;
}
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// Spot Lights
plSpotModifier::plSpotModifier()
: fSpot(nil),
fInnerCtl(nil),
fOuterCtl(nil)
{
}
plSpotModifier::~plSpotModifier()
{
delete fInnerCtl;
fInnerCtl = nil;
delete fOuterCtl;
fOuterCtl = nil;
}
void plSpotModifier::AddTarget(plSceneObject* so)
{
plOmniModifier::AddTarget(so);
if( fLight )
fSpot = plSpotLightInfo::ConvertNoRef(fLight);
else
fSpot = nil;
}
void plSpotModifier::RemoveTarget(plSceneObject* so)
{
plOmniModifier::RemoveTarget(so);
if( !fLight )
fSpot = nil;
}
void plSpotModifier::IClearCtls()
{
plOmniModifier::IClearCtls();
delete fInnerCtl;
fInnerCtl = nil;
delete fOuterCtl;
fOuterCtl = nil;
}
void plSpotModifier::Read(hsStream* s, hsResMgr* mgr)
{
plOmniModifier::Read(s, mgr);
fInnerCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fOuterCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
}
void plSpotModifier::Write(hsStream* s, hsResMgr* mgr)
{
plOmniModifier::Write(s, mgr);
mgr->WriteCreatable(s, fInnerCtl);
mgr->WriteCreatable(s, fOuterCtl);
}
void plSpotModifier::IApplyDynamic()
{
plOmniModifier::IApplyDynamic();
hsScalar f;
if( fInnerCtl )
{
fInnerCtl->Interp(fCurrentTime, &f);
fSpot->SetSpotInner(hsScalarDegToRad(f)*0.5f);
}
if( fOuterCtl )
{
fOuterCtl->Interp(fCurrentTime, &f);
fSpot->SetSpotOuter(hsScalarDegToRad(f)*0.5f);
}
}
hsScalar plSpotModifier::MaxAnimLength(hsScalar len) const
{
len = plOmniModifier::MaxAnimLength(len);
if( fInnerCtl && (fInnerCtl->GetLength() > len) )
len = fInnerCtl->GetLength();
if( fOuterCtl && (fOuterCtl->GetLength() > len) )
len = fOuterCtl->GetLength();
return len;
}
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// LtdDir Lights
plLtdDirModifier::plLtdDirModifier()
: fLtdDir(nil),
fWidthCtl(nil),
fHeightCtl(nil),
fDepthCtl(nil)
{
}
plLtdDirModifier::~plLtdDirModifier()
{
delete fWidthCtl;
fWidthCtl = nil;
delete fHeightCtl;
fHeightCtl = nil;
delete fDepthCtl;
fDepthCtl = nil;
}
void plLtdDirModifier::AddTarget(plSceneObject* so)
{
plLightModifier::AddTarget(so);
if( fLight )
fLtdDir = plLimitedDirLightInfo::ConvertNoRef(fLight);
else
fLtdDir = nil;
}
void plLtdDirModifier::RemoveTarget(plSceneObject* so)
{
plLightModifier::RemoveTarget(so);
if( !fLight )
fLtdDir = nil;
}
void plLtdDirModifier::IClearCtls()
{
plLightModifier::IClearCtls();
delete fWidthCtl;
fWidthCtl = nil;
delete fHeightCtl;
fHeightCtl = nil;
delete fDepthCtl;
fDepthCtl = nil;
}
void plLtdDirModifier::Read(hsStream* s, hsResMgr* mgr)
{
plLightModifier::Read(s, mgr);
fWidthCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fHeightCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fDepthCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
}
void plLtdDirModifier::Write(hsStream* s, hsResMgr* mgr)
{
plLightModifier::Write(s, mgr);
mgr->WriteCreatable(s, fWidthCtl);
mgr->WriteCreatable(s, fHeightCtl);
mgr->WriteCreatable(s, fDepthCtl);
}
void plLtdDirModifier::IApplyDynamic()
{
plLightModifier::IApplyDynamic();
hsScalar f;
if( fWidthCtl )
{
fWidthCtl->Interp(fCurrentTime, &f);
fLtdDir->SetWidth(f);
}
if( fHeightCtl )
{
fHeightCtl->Interp(fCurrentTime, &f);
fLtdDir->SetHeight(f);
}
if( fDepthCtl )
{
fDepthCtl->Interp(fCurrentTime, &f);
fLtdDir->SetDepth(f);
}
}
hsScalar plLtdDirModifier::MaxAnimLength(hsScalar len) const
{
len = plLightModifier::MaxAnimLength(len);
if( fWidthCtl && (fWidthCtl->GetLength() > len) )
len = fWidthCtl->GetLength();
if( fHeightCtl && (fHeightCtl->GetLength() > len) )
len = fHeightCtl->GetLength();
if( fDepthCtl && (fDepthCtl->GetLength() > len) )
len = fDepthCtl->GetLength();
return len;
}

View File

@ -0,0 +1,197 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plLightModifier_inc
#define plLightModifier_inc
#include "../../PubUtilLib/plModifier/plSimpleModifier.h"
#include "hsGeometry3.h"
class plController;
class plController;
class plLightInfo;
class plOmniLightInfo;
class plSpotLightInfo;
class plLimitedDirLightInfo;
class plLightModifier : public plSimpleModifier
{
protected:
plController* fColorCtl;
plController* fAmbientCtl;
plController* fSpecularCtl;
plLightInfo* fLight;
virtual void IApplyDynamic();
virtual void IClearCtls();
public:
plLightModifier();
virtual ~plLightModifier();
CLASSNAME_REGISTER( plLightModifier );
GETINTERFACE_ANY( plLightModifier, plSimpleModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool HasAnima() const { return fColorCtl || fAmbientCtl || fSpecularCtl; }
// Export only
void SetColorCtl(plController* ctl) { fColorCtl = ctl; }
void SetAmbientCtl(plController* ctl) { fAmbientCtl = ctl; }
void SetSpecularCtl(plController* ctl) { fSpecularCtl = ctl; }
virtual void DefaultAnimation();
virtual hsScalar MaxAnimLength(hsScalar len) const;
};
class plOmniModifier : public plLightModifier
{
protected:
plOmniLightInfo* fOmni;
plController* fAttenCtl;
hsPoint3 fInitAtten;
virtual void IApplyDynamic();
virtual void IClearCtls();
public:
plOmniModifier();
virtual ~plOmniModifier();
CLASSNAME_REGISTER( plOmniModifier );
GETINTERFACE_ANY( plOmniModifier, plLightModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool HasAnima() const { return plLightModifier::HasAnima() || fAttenCtl; }
// Export Only
void SetAttenCtl(plController* ctl) { fAttenCtl = ctl; }
void SetInitAtten(const hsPoint3& p) { fInitAtten = p; }
virtual hsScalar MaxAnimLength(hsScalar len) const;
};
class plSpotModifier : public plOmniModifier
{
protected:
plSpotLightInfo* fSpot;
plController* fInnerCtl;
plController* fOuterCtl;
virtual void IApplyDynamic();
virtual void IClearCtls();
public:
plSpotModifier();
virtual ~plSpotModifier();
CLASSNAME_REGISTER( plSpotModifier );
GETINTERFACE_ANY( plSpotModifier, plLightModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool HasAnima() const { return plOmniModifier::HasAnima() || fInnerCtl || fOuterCtl; }
// Export Only
void SetInnerCtl(plController* ctl) { fInnerCtl = ctl; }
void SetOuterCtl(plController* ctl) { fOuterCtl = ctl; }
virtual hsScalar MaxAnimLength(hsScalar len) const;
};
class plLtdDirModifier : public plLightModifier
{
protected:
plLimitedDirLightInfo* fLtdDir;
plController* fWidthCtl;
plController* fHeightCtl;
plController* fDepthCtl;
virtual void IApplyDynamic();
virtual void IClearCtls();
public:
plLtdDirModifier();
virtual ~plLtdDirModifier();
CLASSNAME_REGISTER( plLtdDirModifier );
GETINTERFACE_ANY( plLtdDirModifier, plLightModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool HasAnima() const { return plLightModifier::HasAnima() || fWidthCtl || fHeightCtl || fDepthCtl; }
// Export Only
void SetWidthCtl(plController* ctl) { fWidthCtl = ctl; }
void SetHeightCtl(plController* ctl) { fHeightCtl = ctl; }
void SetDepthCtl(plController* ctl) { fDepthCtl = ctl; }
virtual hsScalar MaxAnimLength(hsScalar len) const;
};
#endif // plLightModifier_inc

View File

@ -0,0 +1,703 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "plLineFollowMod.h"
#include "plStereizer.h"
#include "../plInterp/plAnimPath.h"
#include "hsResMgr.h"
#include "../pnMessage/plRefMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnSceneObject/plDrawInterface.h"
#include "plgDispatch.h"
#include "../plMessage/plListenerMsg.h"
#include "../plMessage/plRenderMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "hsBounds.h"
#include "plPipeline.h"
#include "hsFastMath.h"
#include "../pnMessage/plPlayerPageMsg.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plNetClient/plNetClientMgr.h"
#include "hsTimer.h"
plLineFollowMod::plLineFollowMod()
: fPath(nil),
fPathParent(nil),
fRefObj(nil),
fFollowMode(kFollowListener),
fFollowFlags(kNone),
fOffset(0),
fOffsetClamp(0),
fSpeedClamp(0)
{
fSearchPos.Set(0,0,0);
}
plLineFollowMod::~plLineFollowMod()
{
delete fPath;
}
void plLineFollowMod::SetSpeedClamp(hsScalar fps)
{
fSpeedClamp = fps;
if( fSpeedClamp > 0 )
{
fFollowFlags |= kSpeedClamp;
}
else
{
fFollowFlags &= ~kSpeedClamp;
}
}
void plLineFollowMod::SetOffsetFeet(hsScalar f)
{
fOffset = f;
if( fOffset != 0 )
{
fFollowFlags &= ~kOffsetAng;
fFollowFlags |= kOffsetFeet;
}
else
{
fFollowFlags &= ~kOffset;
}
}
void plLineFollowMod::SetForceToLine(hsBool on)
{
if( on )
fFollowFlags |= kForceToLine;
else
fFollowFlags &= ~kForceToLine;
}
void plLineFollowMod::SetOffsetDegrees(hsScalar f)
{
fOffset = hsScalarDegToRad(f);
if( fOffset != 0 )
{
fFollowFlags &= ~kOffsetFeet;
fFollowFlags |= kOffsetAng;
fTanOffset = tanf(f);
}
else
{
fFollowFlags &= ~kOffset;
}
}
void plLineFollowMod::SetOffsetClamp(hsScalar f)
{
fOffsetClamp = f;
if( fOffsetClamp > 0 )
{
fFollowFlags |= kOffsetClamp;
}
else
{
fFollowFlags &= ~kOffsetClamp;
}
}
void plLineFollowMod::SetPath(plAnimPath* path)
{
delete fPath;
fPath = path;
}
void plLineFollowMod::Read(hsStream* stream, hsResMgr* mgr)
{
plMultiModifier::Read(stream, mgr);
fPath = plAnimPath::ConvertNoRef(mgr->ReadCreatable(stream));
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefParent), plRefFlags::kPassiveRef);
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefObject), plRefFlags::kPassiveRef);
int n = stream->ReadSwap32();
while(n--)
{
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefStereizer), plRefFlags::kPassiveRef);
}
UInt32 f = stream->ReadSwap32();
SetFollowMode(FollowMode(f & 0xffff));
fFollowFlags = (UInt16)((f >> 16) & 0xffff);
if( fFollowFlags & kOffset )
{
fOffset = stream->ReadSwapScalar();
}
if( fFollowFlags & kOffsetAng )
{
fTanOffset = tanf(fOffset);
}
if( fFollowFlags & kOffsetClamp )
{
fOffsetClamp = stream->ReadSwapScalar();
}
if( fFollowFlags & kSpeedClamp )
{
fSpeedClamp = stream->ReadSwapScalar();
}
}
void plLineFollowMod::Write(hsStream* stream, hsResMgr* mgr)
{
plMultiModifier::Write(stream, mgr);
mgr->WriteCreatable(stream, fPath);
mgr->WriteKey(stream, fPathParent);
mgr->WriteKey(stream, fRefObj);
stream->WriteSwap32(fStereizers.GetCount());
int i;
for( i = 0; i < fStereizers.GetCount(); i++ )
mgr->WriteKey(stream, fStereizers[i]->GetKey());
UInt32 f = UInt32(fFollowMode) | (UInt32(fFollowFlags) << 16);
stream->WriteSwap32(f);
if( fFollowFlags & kOffset )
stream->WriteSwapScalar(fOffset);
if( fFollowFlags & kOffsetClamp )
stream->WriteSwapScalar(fOffsetClamp);
if( fFollowFlags & kSpeedClamp )
stream->WriteSwapScalar(fSpeedClamp);
}
#include "plProfile.h"
plProfile_CreateTimer("LineFollow", "RenderSetup", LineFollow);
hsBool plLineFollowMod::MsgReceive(plMessage* msg)
{
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
plSceneObject* obj = plSceneObject::ConvertNoRef(refMsg->GetRef());
if( kRefParent == refMsg->fType )
fPathParent = obj;
else if( kRefObject == refMsg->fType )
fRefObj = obj;
else if( kRefStereizer == refMsg->fType )
{
plStereizer* ster = plStereizer::ConvertNoRef(refMsg->GetRef());
int idx = fStereizers.Find(ster);
if( idx == fStereizers.kMissingIndex )
fStereizers.Append(ster);
}
}
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
{
if( kRefParent == refMsg->fType )
fPathParent = nil;
else if( kRefObject == refMsg->fType )
fRefObj = nil;
else if( kRefStereizer == refMsg->fType )
{
plStereizer* ster = (plStereizer*)(refMsg->GetRef());
int idx = fStereizers.Find(ster);
if( idx != fStereizers.kMissingIndex )
fStereizers.Remove(idx);
}
}
return true;
}
plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
if( rend )
{
plProfile_BeginLap(LineFollow, this->GetKey()->GetUoid().GetObjectName());
hsPoint3 oldPos = fSearchPos;
fSearchPos = rend->Pipeline()->GetViewPositionWorld();
ICheckForPop(oldPos, fSearchPos);
plProfile_EndLap(LineFollow, this->GetKey()->GetUoid().GetObjectName());
return true;
}
plListenerMsg* list = plListenerMsg::ConvertNoRef(msg);
if( list )
{
hsPoint3 oldPos = fSearchPos;
fSearchPos = list->GetPosition();
ICheckForPop(oldPos, fSearchPos);
ISetupStereizers(list);
return true;
}
plPlayerPageMsg* pPMsg = plPlayerPageMsg::ConvertNoRef(msg);
if (pPMsg)
{
if (pPMsg->fPlayer == plNetClientMgr::GetInstance()->GetLocalPlayerKey() && !pPMsg->fUnload)
{
fRefObj = (plSceneObject*)pPMsg->fPlayer->GetObjectPtr();
}
return true;
}
return plMultiModifier::MsgReceive(msg);
}
void plLineFollowMod::SetFollowMode(FollowMode f)
{
IUnRegister();
fFollowMode = f;
IRegister();
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plLineFollowMod::IUnRegister()
{
switch( fFollowMode )
{
case kFollowObject:
break;
case kFollowListener:
plgDispatch::Dispatch()->UnRegisterForExactType(plListenerMsg::Index(), GetKey());
break;
case kFollowCamera:
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
break;
case kFollowLocalAvatar:
plgDispatch::Dispatch()->UnRegisterForExactType(plPlayerPageMsg::Index(), GetKey());
break;
}
}
void plLineFollowMod::IRegister()
{
switch( fFollowMode )
{
case kFollowObject:
break;
case kFollowListener:
plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey());
break;
case kFollowCamera:
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
break;
case kFollowLocalAvatar:
{
if (plNetClientApp::GetInstance() && plNetClientApp::GetInstance()->GetLocalPlayer())
fRefObj = ((plSceneObject*)plNetClientApp::GetInstance()->GetLocalPlayer());
plgDispatch::Dispatch()->RegisterForExactType(plPlayerPageMsg::Index(), GetKey());
break;
}
}
}
hsBool plLineFollowMod::IEval(double secs, hsScalar del, UInt32 dirty)
{
if( !fPath )
return false;
ISetPathTransform();
if( !IGetSearchPos() )
return false;
hsMatrix44 tgtXfm;
IGetTargetTransform(fSearchPos, tgtXfm);
if( fFollowFlags & kOffset )
IOffsetTargetTransform(tgtXfm);
int i;
for( i = 0; i < GetNumTargets(); i++ )
{
ISetTargetTransform(i, tgtXfm);
}
return true;
}
hsBool plLineFollowMod::IOffsetTargetTransform(hsMatrix44& tgtXfm)
{
hsPoint3 tgtPos = tgtXfm.GetTranslate();
hsVector3 tgt2src(&fSearchPos, &tgtPos);
hsScalar t2sLen = tgt2src.Magnitude();
hsFastMath::NormalizeAppr(tgt2src);
hsVector3 out;
out.Set(-tgt2src.fY, tgt2src.fX, 0); // (0,0,1) X (tgt2src)
if( fFollowFlags & kOffsetAng )
{
hsScalar del = t2sLen * fTanOffset;
if( fFollowFlags & kOffsetClamp )
{
if( del > fOffsetClamp )
del = fOffsetClamp;
else if( del < -fOffsetClamp )
del = -fOffsetClamp;
}
out *= del;
}
else if( fFollowFlags & kOffsetFeet )
{
out *= fOffset;
}
else
out.Set(0,0,0);
if( fFollowFlags & kForceToLine )
{
hsPoint3 newSearch = tgtPos;
newSearch += out;
IGetTargetTransform(newSearch, tgtXfm);
}
else
{
tgtXfm.fMap[0][3] += out[0];
tgtXfm.fMap[1][3] += out[1];
tgtXfm.fMap[2][3] += out[2];
}
return true;
}
hsBool plLineFollowMod::IGetTargetTransform(hsPoint3& searchPos, hsMatrix44& tgtXfm)
{
hsScalar t = fPath->GetExtremePoint(searchPos);
if( fFollowFlags & kFullMatrix )
{
fPath->SetCurTime(t, plAnimPath::kNone);
fPath->GetMatrix44(&tgtXfm);
}
else
{
fPath->SetCurTime(t, plAnimPath::kCalcPosOnly);
hsPoint3 pos;
fPath->GetPosition(&pos);
tgtXfm.MakeTranslateMat((hsVector3*)&pos);
}
return true;
}
void plLineFollowMod::ISetPathTransform()
{
if( fPathParent && fPathParent->GetCoordinateInterface() )
{
hsMatrix44 l2w = fPathParent->GetCoordinateInterface()->GetLocalToWorld();
hsMatrix44 w2l = fPathParent->GetCoordinateInterface()->GetWorldToLocal();
fPath->SetTransform(l2w, w2l);
}
}
void plLineFollowMod::ICheckForPop(const hsPoint3& oldPos, const hsPoint3& newPos)
{
hsVector3 del(&oldPos, &newPos);
hsScalar elapsed = hsTimer::GetDelSysSeconds();
hsScalar speedSq = 0.f;
if (elapsed > 0.f)
speedSq = del.MagnitudeSquared() / elapsed;
const hsScalar kMaxSpeedSq = 30.f * 30.f; // (feet per sec)^2
if( speedSq > kMaxSpeedSq )
fFollowFlags |= kSearchPosPop;
else
fFollowFlags &= ~kSearchPosPop;
}
hsBool plLineFollowMod::IGetSearchPos()
{
hsPoint3 oldPos = fSearchPos;
if( kFollowObject == fFollowMode )
{
if( !fRefObj )
return false;
if( fRefObj->GetCoordinateInterface() )
{
fSearchPos = fRefObj->GetCoordinateInterface()->GetWorldPos();
ICheckForPop(oldPos, fSearchPos);
return true;
}
else if( fRefObj->GetDrawInterface() )
{
fSearchPos = fRefObj->GetDrawInterface()->GetWorldBounds().GetCenter();
ICheckForPop(oldPos, fSearchPos);
return true;
}
return false;
}
else
if (fFollowMode == kFollowLocalAvatar)
{
if (!fRefObj)
return false;
if( fRefObj->GetCoordinateInterface() )
{
fSearchPos = fRefObj->GetCoordinateInterface()->GetWorldPos();
ICheckForPop(oldPos, fSearchPos);
return true;
}
else if( fRefObj->GetDrawInterface() )
{
fSearchPos = fRefObj->GetDrawInterface()->GetWorldBounds().GetCenter();
ICheckForPop(oldPos, fSearchPos);
return true;
}
return false;
}
return true;
}
hsMatrix44 plLineFollowMod::IInterpMatrices(const hsMatrix44& m0, const hsMatrix44& m1, hsScalar parm)
{
hsMatrix44 retVal;
int i, j;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 4; j++ )
{
retVal.fMap[i][j] = m0.fMap[i][j] * (1.f - parm) + m1.fMap[i][j] * parm;
}
}
retVal.fMap[3][0] = retVal.fMap[3][1] = retVal.fMap[3][2] = 0;
retVal.fMap[3][3] = 1.f;
retVal.NotIdentity();
return retVal;
}
hsMatrix44 plLineFollowMod::ISpeedClamp(plCoordinateInterface* ci, const hsMatrix44& unclTgtXfm)
{
// If our search position has popped, or delsysseconds is zero, just return as is.
if( (fFollowFlags & kSearchPosPop) || !(hsTimer::GetDelSysSeconds() > 0) )
return unclTgtXfm;
const hsMatrix44 currL2W = ci->GetLocalToWorld();
const hsPoint3 oldPos = currL2W.GetTranslate();
const hsPoint3 newPos = unclTgtXfm.GetTranslate();
const hsVector3 del(&newPos, &oldPos);
hsScalar elapsed = hsTimer::GetDelSysSeconds();
hsScalar speed = 0.f;
if (elapsed > 0.f)
speed = del.Magnitude() / elapsed;
if( speed > fSpeedClamp )
{
hsScalar parm = fSpeedClamp / speed;
hsMatrix44 clTgtXfm = IInterpMatrices(currL2W, unclTgtXfm, parm);
return clTgtXfm;
}
return unclTgtXfm;
}
void plLineFollowMod::ISetTargetTransform(int iTarg, const hsMatrix44& unclTgtXfm)
{
plCoordinateInterface* ci = IGetTargetCoordinateInterface(iTarg);
if( ci )
{
hsMatrix44 tgtXfm = fFollowFlags & kSpeedClamp ? ISpeedClamp(ci, unclTgtXfm) : unclTgtXfm;
if( fFollowFlags & kFullMatrix )
{
// This branch currently never gets taken. If it ever does,
// we should probably optimize out this GetInverse() (depending
// on how often it gets taken).
const hsMatrix44& l2w = tgtXfm;
hsMatrix44 w2l;
l2w.GetInverse(&w2l);
ci->SetTransform(l2w, w2l);
}
else
{
hsMatrix44 l2w = ci->GetLocalToWorld();
hsMatrix44 w2l = ci->GetWorldToLocal();
hsPoint3 pos = tgtXfm.GetTranslate();
hsPoint3 oldPos = l2w.GetTranslate();
l2w.SetTranslate(&pos);
hsMatrix44 xlate;
xlate.Reset();
xlate.SetTranslate(&oldPos);
w2l = w2l * xlate;
xlate.SetTranslate(&-pos);
w2l = w2l * xlate;
ci->SetTransform(l2w, w2l);
}
hsPoint3 newPos = tgtXfm.GetTranslate();
int i;
for( i = 0; i < fStereizers.GetCount(); i++ )
{
if( fStereizers[i] )
{
fStereizers[i]->SetWorldInitPos(newPos);
fStereizers[i]->Stereize();
}
}
}
}
void plLineFollowMod::ISetupStereizers(const plListenerMsg* listMsg)
{
int i;
for( i = 0; i < fStereizers.GetCount(); i++ )
{
if( fStereizers[i] )
fStereizers[i]->SetFromListenerMsg(listMsg);
}
}
void plLineFollowMod::AddTarget(plSceneObject* so)
{
plMultiModifier::AddTarget(so);
if( so )
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plLineFollowMod::RemoveTarget(plSceneObject* so)
{
plMultiModifier::RemoveTarget(so);
}
void plLineFollowMod::AddStereizer(const plKey& key)
{
hsgResMgr::ResMgr()->SendRef(plKey(key), TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefStereizer), plRefFlags::kPassiveRef);
}
void plLineFollowMod::RemoveStereizer(const plKey& key)
{
hsgResMgr::ResMgr()->SendRef(plKey(key), TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnRemove, 0, kRefStereizer), plRefFlags::kPassiveRef);
}
// derived version of this class for rail cameras
// the difference is the rail camera just calculates
// the desired position but does not move the target to
// it.
plRailCameraMod::plRailCameraMod() :
fCurrentTime(0.0f),
fTargetTime(0.0f),
fFarthest(false)
{
plLineFollowMod::plLineFollowMod();
fGoal.Set(0,0,0);
}
plRailCameraMod::~plRailCameraMod()
{
}
hsBool plRailCameraMod::IGetTargetTransform(hsPoint3& searchPos, hsMatrix44& tgtXfm)
{
if (fPath->GetFarthest())
{
fFarthest = true;
fPath->SetFarthest(false);
}
fTargetTime = fPath->GetExtremePoint(searchPos);
fPath->SetCurTime(fTargetTime, plAnimPath::kCalcPosOnly);
hsPoint3 pos;
fPath->GetPosition(&pos);
tgtXfm.MakeTranslateMat((hsVector3*)&pos);
return true;
}
hsPoint3 plRailCameraMod::GetGoal(double secs, hsScalar speed)
{
hsScalar delTime;
int dir;
if (fTargetTime == fCurrentTime)
return fGoal;
if (fTargetTime > fCurrentTime)
{
dir = 1;
delTime = fTargetTime - fCurrentTime;
}
else
{
dir = -1;
delTime = fCurrentTime - fTargetTime;
}
if (fPath->GetWrap() && delTime > fPath->GetLength() * 0.5f)
dir *= -1;
if (delTime <= (secs * speed))
fCurrentTime = fTargetTime;
else
fCurrentTime += (hsScalar)((secs * speed) * dir);
if (fPath->GetWrap())
{
if (fCurrentTime > fPath->GetLength())
fCurrentTime = (fCurrentTime - fPath->GetLength());
else
if (fCurrentTime < 0.0f)
fCurrentTime = fPath->GetLength() - fCurrentTime;
}
if (fFarthest)
fPath->SetCurTime((fPath->GetLength() - fCurrentTime), plAnimPath::kCalcPosOnly);
else
fPath->SetCurTime(fCurrentTime, plAnimPath::kCalcPosOnly);
fPath->GetPosition(&fGoal);
fPath->SetCurTime(fTargetTime, plAnimPath::kCalcPosOnly);
return fGoal;
}

View File

@ -0,0 +1,191 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plLineFollowMod_inc
#define plLineFollowMod_inc
#include "../pnModifier/plMultiModifier.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
class plAnimPath;
class plSceneObject;
class plStereizer;
class plListenerMsg;
class plLineFollowMod : public plMultiModifier
{
public:
enum FollowMode {
kFollowObject,
kFollowListener,
kFollowCamera,
kFollowLocalAvatar,
};
enum RefType {
kRefParent,
kRefObject,
kRefStereizer
};
enum {
kNone = 0x0,
kFullMatrix = 0x1,
kOffsetFeet = 0x2,
kOffsetAng = 0x4,
kOffset = kOffsetFeet | kOffsetAng,
kOffsetClamp = 0x8,
kForceToLine = 0x10,
kSpeedClamp = 0x20,
kSearchPosPop = 0x40 // Temp flag, gets set every time the target pops in position
};
protected:
FollowMode fFollowMode;
UInt16 fFollowFlags;
plAnimPath* fPath;
plSceneObject* fPathParent;
plSceneObject* fRefObj;
mutable hsPoint3 fSearchPos;
hsTArray<plStereizer*> fStereizers;
hsScalar fTanOffset;
hsScalar fOffset;
hsScalar fOffsetClamp;
hsScalar fSpeedClamp;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual hsBool IGetSearchPos();
virtual void ISetTargetTransform(int iTarg, const hsMatrix44& tgtXfm);
virtual void ISetPathTransform();
virtual hsBool IGetTargetTransform(hsPoint3& searchPos, hsMatrix44& tgtXfm);
virtual hsBool IOffsetTargetTransform(hsMatrix44& tgtXfm);
virtual hsMatrix44 ISpeedClamp(plCoordinateInterface* ci, const hsMatrix44& unclTgtXfm);
hsMatrix44 IInterpMatrices(const hsMatrix44& m0, const hsMatrix44& m1, hsScalar parm);
void ICheckForPop(const hsPoint3& oldPos, const hsPoint3& newPos);
void ISetupStereizers(const plListenerMsg* listMsg);
void IUnRegister();
void IRegister();
public:
plLineFollowMod();
~plLineFollowMod();
CLASSNAME_REGISTER( plLineFollowMod );
GETINTERFACE_ANY( plLineFollowMod, plMultiModifier );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// Export time stuff
void SetPath(plAnimPath* path);
const plAnimPath* GetPath() const { return fPath; }
void SetFollowMode(FollowMode f);
FollowMode GetFollowMode() const { return fFollowMode; }
hsBool HasOffsetFeet() const { return 0 != (fFollowFlags & kOffsetFeet); }
hsBool HasOffsetDegrees() const { return 0 != (fFollowFlags & kOffsetAng); }
hsBool HasOffset() const { return 0 != (fFollowFlags & kOffset); }
hsBool HasOffsetClamp() const { return 0 != (fFollowFlags & kOffsetClamp); }
hsBool HasSpeedClamp() const { return 0 != (fFollowFlags & kSpeedClamp); }
void SetOffsetFeet(hsScalar f);
hsScalar GetOffsetFeet() const { return fOffset; }
void SetOffsetDegrees(hsScalar f);
hsScalar GetOffsetDegrees() const { return hsScalarRadToDeg(fOffset); }
void SetOffsetClamp(hsScalar f);
hsScalar GetOffsetClamp() const { return fOffsetClamp; }
void SetForceToLine(hsBool on);
hsBool GetForceToLine() const { return 0 != (fFollowFlags & kForceToLine); }
void SetSpeedClamp(hsScalar feetPerSec);
hsScalar GetSpeedClamp() const { return fSpeedClamp; }
hsBool MsgReceive(plMessage* msg);
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
void AddStereizer(const plKey& sterKey);
void RemoveStereizer(const plKey& sterKey);
};
class plRailCameraMod : public plLineFollowMod
{
public:
plRailCameraMod();
~plRailCameraMod();
CLASSNAME_REGISTER( plRailCameraMod );
GETINTERFACE_ANY( plRailCameraMod, plLineFollowMod );
void Init() { fCurrentTime = -1; } // twiddle ourselves so we get ready to go...
hsPoint3 GetGoal(double secs, hsScalar speed);
protected:
virtual void ISetTargetTransform(int iTarg, const hsMatrix44& tgtXfm) {fDesiredMatrix = tgtXfm;}
virtual hsBool IGetTargetTransform(hsPoint3& searchPos, hsMatrix44& tgtXfm);
hsMatrix44 fDesiredMatrix;
hsScalar fCurrentTime;
hsScalar fTargetTime;
hsPoint3 fGoal;
hsBool fFarthest;
};
#endif // plLineFollowMod_inc

View File

@ -0,0 +1,306 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 <stdlib.h>
#include "hsTypes.h"
#include "plRandomCommandMod.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../pnMessage/plEventCallbackMsg.h"
#include "plgDispatch.h"
#include "hsTimer.h"
#include "hsUtils.h"
static const hsScalar kRandNormalize = 1.f / 32767.f;
plRandomCommandMod::plRandomCommandMod()
{
fState = 0;
fMode = kNormal;
fCurrent = -1;
fMinDelay = 0;
fMaxDelay = 0;
}
plRandomCommandMod::~plRandomCommandMod()
{
}
// return how many are left to choose from
int plRandomCommandMod::IExcludeSelections(int ncmds)
{
if( fMode & kCoverall )
{
int nLeft = ncmds;
fExcluded.SetBit(fCurrent);
// Count how many haven't been played.
int i;
for( i = ncmds-1; i >= 0; --i )
{
if( fExcluded.IsBitSet(i) )
nLeft--;
}
// If we're out of cmds, and OneCycle is set,
// we're out of cmds until the next play.
// Go ahead and reset for that.
// If we're out and OneCycle isn't set, then go ahead
// and set up for a new cycle.
if( !nLeft )
{
fExcluded.Clear();
if( fMode & kNoRepeats )
fExcluded.SetBit(fCurrent);
if( fMode & kOneCycle )
return 0;
nLeft = ncmds;
if( ( fMode & kNoRepeats ) && ncmds > 1 )
nLeft--;
}
return nLeft;
}
double currTime = hsTimer::GetSysSeconds();
fExcluded.Clear();
int i;
for( i = 0; i < fEndTimes.GetCount(); i++ )
{
if( fEndTimes[i] > currTime )
{
ncmds--;
fExcluded.SetBit(i);
}
}
if( fMode & kNoRepeats )
{
ncmds--;
fExcluded.SetBit(fCurrent);
return ncmds;
}
return ncmds;
}
hsScalar plRandomCommandMod::IGetDelay(hsScalar len) const
{
hsScalar r = float(hsRand() * kRandNormalize);
hsScalar delay = fMinDelay + (fMaxDelay - fMinDelay) * r;
if( fMode & kDelayFromEnd )
delay += len;
if( delay < 0 )
delay = fmodf(len, -delay);
return delay;
}
hsBool plRandomCommandMod::ISelectNext(int ncmds)
{
if( fMode & kSequential )
{
if( ++fCurrent >= ncmds )
{
if( fMode & kOneCycle )
{
fCurrent = -1;
return false;
}
fCurrent = 0;
}
return true;
}
hsScalar r = float(hsRand() * kRandNormalize);
int nSelect = ncmds;
if( fCurrent >= 0 )
nSelect = IExcludeSelections(ncmds);
if( !nSelect )
return false;
int nth = int(r * (float(nSelect)-1.e-3f));
int iNext = 0;
int i;
for( i = 0; i < ncmds; i++ )
{
if( !fExcluded.IsBitSet(i) )
{
if( !nth-- )
{
iNext = i;
break;
}
}
}
fCurrent = iNext;
return true;
}
void plRandomCommandMod::IStart()
{
if( !IStopped() )
return;
fState &= ~kStopped;
IPlayNextIfMaster();
}
void plRandomCommandMod::IStop()
{
fState |= kStopped;
}
hsBool plRandomCommandMod::IStopped() const
{
return 0 != (fState & kStopped);
}
void plRandomCommandMod::IPlayNextIfMaster()
{
if( !fTarget )
IRetry(2.f);
if( fTarget->IsLocallyOwned() == plSynchedObject::kNo ) // if this object is a proxy, it should just wait for network cmds
return;
if( IStopped() )
return;
IPlayNext();
}
hsBool plRandomCommandMod::MsgReceive(plMessage* msg)
{
// plAnimCmdMsg - interpret start/stop appropriately.
// could overinterpret set loop points to limit range of
// cmds we use to a window of the total set.
plAnimCmdMsg* anim = plAnimCmdMsg::ConvertNoRef(msg);
if( anim )
{
if( anim->GetSender() != GetKey() )
{
#if 0
hsStatusMessageF("someone triggered me, remote=%d\n",
msg->HasBCastFlag(plMessage::kNetNonLocal));
#endif
if( anim->Cmd(plAnimCmdMsg::kContinue) )
IStart();
if( anim->Cmd(plAnimCmdMsg::kStop) )
IStop();
if( anim->Cmd(plAnimCmdMsg::kToggleState) )
{
if( IStopped() )
IStart();
else
IStop();
}
}
else
{
#if 0
hsStatusMessageF("play next if master, remote=%d\n",
msg->HasBCastFlag(plMessage::kNetNonLocal));
#endif
IPlayNextIfMaster();
}
return true;
}
// Don't understand, pass on to base class.
return plSingleModifier::MsgReceive(msg);
}
void plRandomCommandMod::IReset()
{
fCurrent = -1;
fExcluded.Clear();
if( !IStopped() )
IRetry(0);
}
void plRandomCommandMod::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
fMode = s->ReadByte();
fState = s->ReadByte();
fMinDelay = s->ReadSwapScalar();
fMaxDelay = s->ReadSwapScalar();
IReset();
}
void plRandomCommandMod::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
s->WriteByte(fMode);
s->WriteByte(fState);
s->WriteSwapScalar(fMinDelay);
s->WriteSwapScalar(fMaxDelay);
}
void plRandomCommandMod::IRetry(hsScalar secs)
{
IStop();
double t = hsTimer::GetSysSeconds() + secs;
plAnimCmdMsg* msg = TRACKED_NEW plAnimCmdMsg(nil, GetKey(), &t);
msg->SetCmd(plAnimCmdMsg::kContinue);
plgDispatch::MsgSend(msg);
}

View File

@ -0,0 +1,127 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plRandomCommandMod_inc
#define plRandomCommandMod_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsTemplates.h"
class plRandomCommandMod : public plSingleModifier
{
public:
enum {
kNormal = 0x0, // randomly select the next
kNoRepeats = 0x1, // random, but no cmd twice in a row
kCoverall = 0x2, // random, but no cmd played twice till all cmds played
kOneCycle = 0x4, // after playing through all cmds, stop
kOneCmd = 0x8, // after playing a random cmd, stop until started again.
kDelayFromEnd = 0x10,
kSequential = 0x20
};
enum {
kStopped = 0x1
};
protected:
// These are only lightly synched, the only synched state is whether
// they are currently active.
UInt8 fState;
hsBitVector fExcluded;
Int8 fCurrent;
UInt8 fMode; // static, if it becomes dynamic, move to SynchedValue
hsTArray<double> fEndTimes;
hsScalar fMinDelay;
hsScalar fMaxDelay;
void IStart();
virtual void IStop();
hsBool IStopped() const;
void IRetry(hsScalar secs);
virtual void IPlayNextIfMaster();
void IReset();
hsScalar IGetDelay(hsScalar len) const;
int IExcludeSelections(int ncmds);
hsBool ISelectNext(int nAnim); // return false if we should stop, else set fCurrent to next index
// Once fCurrent is set to the next animation index to play,
// IPlayNext() does whatever it takes to actually play it.
virtual void IPlayNext() = 0;
// We only act in response to messages.
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
public:
plRandomCommandMod();
~plRandomCommandMod();
CLASSNAME_REGISTER( plRandomCommandMod );
GETINTERFACE_ANY( plRandomCommandMod, plSingleModifier );
virtual hsBool MsgReceive(plMessage* pMsg);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
// Export only
void SetMode(UInt8 m) { fMode = m; }
UInt8 GetMode() const { return fMode; }
void SetState(UInt8 s) { fState = s; }
UInt8 GetState() const { return fState; }
void SetMinDelay(hsScalar f) { fMinDelay = f; }
hsScalar GetMinDelay() const { return fMinDelay; }
void SetMaxDelay(hsScalar f) { fMaxDelay = f; }
hsScalar GetMaxDelay() const { return fMaxDelay; }
};
#endif // plRandomCommandMod_inc

View File

@ -0,0 +1,310 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 <math.h>
#include "hsTypes.h"
#include "plStereizer.h"
#include "plLineFollowMod.h"
#include "../plMessage/plListenerMsg.h"
#include "plgDispatch.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "hsFastMath.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "hsStream.h"
plStereizer::plStereizer()
: fInitPos(0,0,0),
fListPos(0,0,0),
fListDirection(0,1.f,0),
fListUp(0,0,1.f)
{
}
plStereizer::~plStereizer()
{
if( !HasMaster() )
plgDispatch::Dispatch()->UnRegisterForExactType(plListenerMsg::Index(), GetKey());
}
void plStereizer::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
fAmbientDist = stream->ReadSwapScalar();
fTransition = stream->ReadSwapScalar();
fMaxSepDist = stream->ReadSwapScalar();
fMinSepDist = stream->ReadSwapScalar();
fTanAng = stream->ReadSwapScalar();
fInitPos.Read(stream);
if( !HasMaster() )
plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey());
}
void plStereizer::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteSwapScalar(fAmbientDist);
stream->WriteSwapScalar(fTransition);
stream->WriteSwapScalar(fMaxSepDist);
stream->WriteSwapScalar(fMinSepDist);
stream->WriteSwapScalar(fTanAng);
fInitPos.Write(stream);
}
hsBool plStereizer::MsgReceive(plMessage* msg)
{
plListenerMsg* listenMsg = plListenerMsg::ConvertNoRef(msg);
if( listenMsg )
{
SetFromListenerMsg(listenMsg);
return Stereize();
}
return plSingleModifier::MsgReceive(msg);
}
hsBool plStereizer::IEval(double secs, hsScalar del, UInt32 dirty)
{
return false;
}
hsBool plStereizer::Stereize()
{
plSceneObject* targ = GetTarget();
if( !targ )
return true;
targ->FlushTransform();
// Find distance to listener
hsPoint3 pos = IGetUnStereoPos();
hsVector3 posToList(&fListPos, &pos);
hsScalar dist = posToList.Magnitude();
// If distance less than ambient distance
// setup as pure ambient
// Else if distance greater than ambient distance + transition
// setup as pure localized
// Else
// Calc pure ambient position
// Calc pure localized position
// Interpolate between the two.
if( dist <= fAmbientDist )
{
ISetNewPos(IGetAmbientPos());
}
else if( dist >= fAmbientDist + fTransition )
{
ISetNewPos(IGetLocalizedPos(posToList, dist));
}
else
{
hsPoint3 ambPos = IGetAmbientPos();
hsPoint3 localizePos = IGetLocalizedPos(posToList, dist);
hsPoint3 newPos(ambPos);
newPos += (localizePos - ambPos) * ((dist - fAmbientDist) / fTransition);
ISetNewPos(newPos);
}
return true;
}
void plStereizer::ISetNewPos(const hsPoint3& newPos)
{
hsMatrix44 l2w = GetTarget()->GetLocalToWorld();
hsMatrix44 w2l = GetTarget()->GetWorldToLocal();
l2w.NotIdentity();
l2w.fMap[0][3] = newPos[0];
l2w.fMap[1][3] = newPos[1];
l2w.fMap[2][3] = newPos[2];
hsPoint3 invPos = -newPos;
w2l.fMap[0][3] = ((hsVector3*)&w2l.fMap[0][0])->InnerProduct(invPos);
w2l.fMap[1][3] = ((hsVector3*)&w2l.fMap[1][0])->InnerProduct(invPos);
w2l.fMap[2][3] = ((hsVector3*)&w2l.fMap[2][0])->InnerProduct(invPos);
IGetTargetCoordinateInterface(0)->SetTransform(l2w, w2l);
}
void plStereizer::SetFromListenerMsg(const plListenerMsg* listMsg)
{
fListPos = listMsg->GetPosition();
fListDirection = listMsg->GetDirection();
fListUp = listMsg->GetUp();
}
hsPoint3 plStereizer::IGetAmbientPos() const
{
hsPoint3 pos = fListPos;
hsVector3 axOut = fListDirection % fListUp;
hsFastMath::NormalizeAppr(axOut);
if( IsLeftChannel() )
axOut *= -fMinSepDist;
else
axOut *= fMinSepDist;
pos += axOut;
return pos;
}
hsPoint3 plStereizer::IGetLocalizedPos(const hsVector3& posToList, hsScalar distToList) const
{
hsPoint3 pos = IGetUnStereoPos();
hsVector3 axOut(-posToList.fY, posToList.fX, 0);
hsFastMath::NormalizeAppr(axOut);
hsScalar distOut = distToList * fTanAng;
if( distOut > fMaxSepDist )
distOut = fMaxSepDist;
else if( distOut < fMinSepDist )
distOut = fMinSepDist;
if( IsLeftChannel() )
distOut = -distOut;
axOut *= distOut;
pos += axOut;
return pos;
}
void plStereizer::SetSepAngle(hsScalar rads)
{
fTanAng = hsScalar(tan(rads));
}
hsScalar plStereizer::GetSepAngle() const
{
return atan(fTanAng);
}
hsPoint3 plStereizer::IGetUnStereoPos() const
{
return GetWorldInitPos();
}
void plStereizer::SetWorldInitPos(const hsPoint3& pos)
{
plCoordinateInterface* parent = IGetParent();
if( parent )
fInitPos = parent->GetWorldToLocal() * pos;
else
fInitPos = pos;
}
hsPoint3 plStereizer::GetWorldInitPos() const
{
plCoordinateInterface* parent = IGetParent();
if( parent )
return parent->GetLocalToWorld() * fInitPos;
return fInitPos;
}
plCoordinateInterface* plStereizer::IGetParent() const
{
plCoordinateInterface* coord = IGetTargetCoordinateInterface(0);
if( coord )
{
return coord->GetParent();
}
return nil;
}
// Note that (along with it's many other hacky defects), this
// will go down in flames if there are two potential masters.
// Of course, two line follow mods doesn't really make sense
// now anyway, but the point is that this is a simplified placeholder
// to get the job done. If and when a need is shown for sequencing of
// modifiers, this should be updated to follow that protocol. But
// the rationale is that one simple example of a need for sequencing
// doesn't give enough basis to decide what that protocol should be.
// Or in simpler terms, I want to do it one way, Brice wants to do
// it another, and since either would work for this, we're waiting
// for a tie breaker case that gives one way or the other an advantage.
hsBool plStereizer::CheckForMaster()
{
ISetHasMaster(false);
plSceneObject* targ = GetTarget();
if( !targ )
return false;
int n = targ->GetNumModifiers();
int i;
for( i = 0; i < n; i++ )
{
plLineFollowMod* line = plLineFollowMod::ConvertNoRef(IGetTargetModifier(0, i));
if( line )
{
ISetHasMaster(true);
line->AddStereizer(GetKey());
return true;
}
}
return false;
}

View File

@ -0,0 +1,140 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plStereizer_inc
#define plStereizer_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
class plListenerMsg;
class plMessage;
class plCoordinateInterface;
class hsStream;
class hsResMgr;
class plStereizer : public plSingleModifier
{
protected:
// Flags - in a plSingleModifier::hsBitVector.
enum
{
kLeftChannel,
kHasMaster
};
// Static properties
hsScalar fAmbientDist;
hsScalar fTransition;
hsScalar fMaxSepDist;
hsScalar fMinSepDist;
hsScalar fTanAng;
hsPoint3 fInitPos;
// Environmental properties, namely of the current listener
hsPoint3 fListPos;
hsVector3 fListDirection;
hsVector3 fListUp;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
hsPoint3 IGetLocalizedPos(const hsVector3& posToList, hsScalar distToList) const;
hsPoint3 IGetAmbientPos() const;
void ISetNewPos(const hsPoint3& newPos);
hsPoint3 IGetUnStereoPos() const;
plCoordinateInterface* IGetParent() const;
void ISetHasMaster(hsBool on) { if(on)SetFlag(kHasMaster); else ClearFlag(kHasMaster); }
public:
plStereizer();
virtual ~plStereizer();
CLASSNAME_REGISTER( plStereizer );
GETINTERFACE_ANY( plStereizer, plSingleModifier );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
hsBool Stereize();
void SetFromListenerMsg(const plListenerMsg* listMsg);
void SetAmbientDist(hsScalar d) { fAmbientDist = d; }
hsScalar GetAmbientDist() const { return fAmbientDist; }
void SetTransition(hsScalar d) { fTransition = d; }
hsScalar GetTransition() const { return fTransition; }
void SetMaxSepDist(hsScalar d) { fMaxSepDist = d; }
hsScalar GetMaxSepDist() const { return fMaxSepDist; }
void SetMinSepDist(hsScalar d) { fMinSepDist = d; }
hsScalar GetMinSepDist() const { return fMinSepDist; }
void SetSepAngle(hsScalar rads);
hsScalar GetSepAngle() const;
void SetAsLeftChannel(hsBool on) { if(on)SetFlag(kLeftChannel); else ClearFlag(kLeftChannel); }
hsBool IsLeftChannel() const { return HasFlag(kLeftChannel); }
void SetParentInitPos(const hsPoint3& pos) { fInitPos = pos; }
const hsPoint3& GetParentInitPos() const { return fInitPos; }
void SetWorldInitPos(const hsPoint3& pos);
hsPoint3 GetWorldInitPos() const;
hsBool CheckForMaster();
hsBool HasMaster() const { return HasFlag(kHasMaster); }
};
#endif // plStereizer_inc

View File

@ -0,0 +1,448 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "plViewFaceModifier.h"
#include "plgDispatch.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "hsFastMath.h"
#include "plPipeline.h"
#include "../plMessage/plRenderMsg.h"
#include "../plMessage/plListenerMsg.h"
#include "../plMessage/plAvatarMsg.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plArmatureMod.h"
plViewFaceModifier::plViewFaceModifier()
: fFacePoint(0,0,0),
fLastDirY(0,1.f,0),
fScale(1.f,1.f,1.f),
fOffset(0,0,0)
{
fOrigLocalToParent.Reset();
fOrigParentToLocal.Reset();
SetFlag(kFaceCam); // default
}
plViewFaceModifier::~plViewFaceModifier()
{
}
void plViewFaceModifier::SetOrigTransform(const hsMatrix44& l2p, const hsMatrix44& p2l)
{
fOrigLocalToParent = l2p;
fOrigParentToLocal = p2l;
}
void plViewFaceModifier::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
fScale.Read(s);
fOrigLocalToParent.Read(s);
fOrigParentToLocal.Read(s);
if( HasFlag(kFaceObj) )
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefFaceObj), plRefFlags::kPassiveRef);
fOffset.Read(s);
if( HasFlag(kMaxBounds) )
fMaxBounds.Read(s);
}
void plViewFaceModifier::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
fScale.Write(s);
fOrigLocalToParent.Write(s);
fOrigParentToLocal.Write(s);
if( HasFlag(kFaceObj) )
mgr->WriteKey(s, fFaceObj);
fOffset.Write(s);
if( HasFlag(kMaxBounds) )
fMaxBounds.Write(s);
}
void plViewFaceModifier::SetMaxBounds(const hsBounds3Ext& bnd)
{
SetFlag(kMaxBounds);
fMaxBounds = bnd;
}
void plViewFaceModifier::SetTarget(plSceneObject* so)
{
plSingleModifier::SetTarget(so);
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
if( HasFlag(kFaceList) )
plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey());
if( HasFlag(kFacePlay) )
plgDispatch::Dispatch()->RegisterForExactType(plArmatureUpdateMsg::Index(), GetKey());
}
hsBool plViewFaceModifier::IEval(double secs, hsScalar del, UInt32 dirty)
{
return false;
}
hsBool plViewFaceModifier::IFacePoint(plPipeline* pipe, const hsPoint3& at)
{
#if 1 // BOUNDSTEST
extern int mfCurrentTest;
if( mfCurrentTest != 101 )
if( HasFlag(kMaxBounds) )
{
if( !pipe->TestVisibleWorld(fMaxBounds) )
return false;
}
#endif // BOUNDSTEST
if( !(GetTarget() && GetTarget()->GetCoordinateInterface()) )
return false;
hsMatrix44 worldToLocal = fOrigParentToLocal; // parentToLocal
if( GetTarget()->GetCoordinateInterface()->GetParent() && GetTarget()->GetCoordinateInterface()->GetParent() )
{
hsMatrix44 m;
worldToLocal = worldToLocal * GetTarget()->GetCoordinateInterface()->GetParent()->GetWorldToLocal();
}
hsPoint3 localAt = worldToLocal * at;
hsScalar len = localAt.MagnitudeSquared();
if( len <= 0 )
return false;
len = -hsFastMath::InvSqrtAppr(len);
hsVector3 dirX, dirY, dirZ;
dirZ.Set(localAt.fX * len, localAt.fY * len, localAt.fZ * len);
if( HasFlag(kPivotFace) )
{
dirY.Set(0.f, 0.f, 1.f);
dirX = dirY % dirZ;
dirX = hsFastMath::NormalizeAppr(dirX);
dirY = dirZ % dirX;
}
else if( HasFlag(kPivotFavorY) )
{
dirY.Set(0.f, 1.f, 0.f);
dirX = dirY % dirZ;
dirX = hsFastMath::NormalizeAppr(dirX);
dirY = dirZ % dirX;
}
else if( HasFlag(kPivotY) )
{
dirY.Set(0.f, 1.f, 0.f);
dirX = dirY % dirZ;
dirX = hsFastMath::NormalizeAppr(dirX);
dirZ = dirX % dirY;
}
else if( HasFlag(kPivotTumble) )
{
dirY = fLastDirY;
dirX = dirY % dirZ;
dirX = hsFastMath::NormalizeAppr(dirX);
dirY = dirZ % dirX;
fLastDirY = dirY;
}
else
{
hsAssert(false, "I've no idea what you're getting at here in ViewFace land");
}
hsMatrix44 x;
hsMatrix44 xInv;
xInv.fMap[0][0] = x.fMap[0][0] = dirX[0];
xInv.fMap[1][0] = x.fMap[0][1] = dirY[0];
xInv.fMap[2][0] = x.fMap[0][2] = dirZ[0];
xInv.fMap[3][0] = x.fMap[0][3] = 0;
xInv.fMap[0][1] = x.fMap[1][0] = dirX[1];
xInv.fMap[1][1] = x.fMap[1][1] = dirY[1];
xInv.fMap[2][1] = x.fMap[1][2] = dirZ[1];
xInv.fMap[3][1] = x.fMap[1][3] = 0;
xInv.fMap[0][2] = x.fMap[2][0] = dirX[2];
xInv.fMap[1][2] = x.fMap[2][1] = dirY[2];
xInv.fMap[2][2] = x.fMap[2][2] = dirZ[2];
xInv.fMap[3][2] = x.fMap[2][3] = 0;
x.fMap[3][0] = x.fMap[3][1] = x.fMap[3][2] = 0;
xInv.fMap[0][3] = xInv.fMap[1][3] = xInv.fMap[2][3] = 0;
xInv.fMap[3][3] = x.fMap[3][3] = hsScalar1;
x.NotIdentity();
xInv.NotIdentity();
if( HasFlag(kScale) )
{
x.fMap[0][0] *= fScale.fX;
x.fMap[0][1] *= fScale.fX;
x.fMap[0][2] *= fScale.fX;
x.fMap[1][0] *= fScale.fY;
x.fMap[1][1] *= fScale.fY;
x.fMap[1][2] *= fScale.fY;
x.fMap[2][0] *= fScale.fZ;
x.fMap[2][1] *= fScale.fZ;
x.fMap[2][2] *= fScale.fZ;
hsScalar inv = 1.f / fScale.fX;
xInv.fMap[0][0] *= inv;
xInv.fMap[1][0] *= inv;
xInv.fMap[2][0] *= inv;
inv = 1.f / fScale.fY;
xInv.fMap[0][1] *= inv;
xInv.fMap[1][1] *= inv;
xInv.fMap[2][1] *= inv;
inv = 1.f / fScale.fZ;
xInv.fMap[0][2] *= inv;
xInv.fMap[1][2] *= inv;
xInv.fMap[2][2] *= inv;
}
hsMatrix44 l2p = fOrigLocalToParent * x;
hsMatrix44 p2l = xInv * fOrigParentToLocal;
if( l2p != IGetTargetCoordinateInterface(0)->GetLocalToParent() ) // TERRORDAN
{
IGetTargetCoordinateInterface(0)->SetLocalToParent(l2p, p2l);
IGetTargetCoordinateInterface(0)->FlushTransform(false);
}
return true;
}
#include "plProfile.h"
plProfile_CreateTimer("ViewFacing", "RenderSetup", ViewFace);
hsBool plViewFaceModifier::MsgReceive(plMessage* msg)
{
plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
if( rend )
{
plProfile_BeginLap(ViewFace, this->GetKey()->GetUoid().GetObjectName());
if( HasFlag(kFaceCam) )
{
fFacePoint = rend->Pipeline()->GetViewPositionWorld();
if( HasFlag(kOffset) )
{
if( HasFlag(kOffsetLocal) )
{
fFacePoint += rend->Pipeline()->GetViewAcrossWorld() * fOffset.fX;
fFacePoint += rend->Pipeline()->GetViewUpWorld() * fOffset.fY;
fFacePoint += rend->Pipeline()->GetViewDirWorld() * fOffset.fZ;
}
else
{
fFacePoint += fOffset;
}
}
}
else
if( HasFlag(kFaceObj) )
{
if( !fFaceObj )
return true;
fFacePoint = fFaceObj->GetLocalToWorld().GetTranslate();
if( HasFlag(kOffset) )
{
if( HasFlag(kOffsetLocal) )
fFacePoint += fFaceObj->GetLocalToWorld() * fOffset;
else
fFacePoint += fOffset;
}
}
IFacePoint(rend->Pipeline(), fFacePoint);
plProfile_EndLap(ViewFace, this->GetKey()->GetUoid().GetObjectName());
return true;
}
plArmatureUpdateMsg* armMsg = plArmatureUpdateMsg::ConvertNoRef(msg);
if( armMsg && armMsg->IsLocal() )
{
const plSceneObject* head = armMsg->fArmature->FindBone(plAvBrainHuman::Head);
if( head )
{
fFacePoint = head->GetLocalToWorld().GetTranslate();
if( HasFlag(kOffset) )
{
if( HasFlag(kOffsetLocal) )
fFacePoint += head->GetLocalToWorld() * fOffset;
else
fFacePoint += fOffset;
}
}
return true;
}
plListenerMsg* list = plListenerMsg::ConvertNoRef(msg);
if( list )
{
fFacePoint = list->GetPosition();
if( HasFlag(kOffset) )
{
if( HasFlag(kOffsetLocal) )
{
fFacePoint += (list->GetDirection() % list->GetUp()) * fOffset.fX;
fFacePoint += list->GetDirection() * fOffset.fY;
fFacePoint += list->GetUp() * fOffset.fZ;
}
else
{
fFacePoint += fOffset;
}
}
return true;
}
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
IOnReceive(refMsg);
else
IOnRemove(refMsg);
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plViewFaceModifier::IOnReceive(plGenRefMsg* refMsg)
{
switch(refMsg->fType)
{
case kRefFaceObj:
fFaceObj = plSceneObject::ConvertNoRef(refMsg->GetRef());
break;
}
}
void plViewFaceModifier::IOnRemove(plGenRefMsg* refMsg)
{
switch(refMsg->fType)
{
case kRefFaceObj:
fFaceObj = nil;
break;
}
}
void plViewFaceModifier::ISetObject(plKey soKey)
{
hsgResMgr::ResMgr()->SendRef(soKey, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnRequest, 0, kRefFaceObj), plRefFlags::kPassiveRef);
}
void plViewFaceModifier::SetFollowMode(FollowMode m, plKey soKey)
{
ClearFlag(kFaceCam);
ClearFlag(kFaceList);
ClearFlag(kFacePlay);
ClearFlag(kFaceObj);
switch(m)
{
case kFollowCamera:
SetFlag(kFaceCam);
break;
case kFollowListener:
SetFlag(kFaceList);
break;
case kFollowPlayer:
SetFlag(kFacePlay);
break;
case kFollowObject:
SetFlag(kFaceObj);
ISetObject(soKey);
break;
default:
hsAssert(false, "Unknown follow mode");
SetFlag(kFaceCam);
break;
}
}
plViewFaceModifier::FollowMode plViewFaceModifier::GetFollowMode() const
{
if( HasFlag(kFaceCam) )
return kFollowCamera;
if( HasFlag(kFaceList) )
return kFollowListener;
if( HasFlag(kFacePlay) )
return kFollowPlayer;
if( HasFlag(kFaceObj) )
return kFollowObject;
hsAssert(false, "Have no follow mode");
return kFollowCamera;
}
void plViewFaceModifier::SetOffset(const hsVector3& off, hsBool local)
{
fOffset = off;
if( local )
SetFlag(kOffsetLocal);
else
ClearFlag(kOffsetLocal);
}

View File

@ -0,0 +1,140 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plViewFaceModifier_inc
#define plViewFaceModifier_inc
#include "hsMatrix44.h"
#include "hsBounds.h"
#include "../pnModifier/plSingleModifier.h"
class plGenRefMsg;
class plPipeline;
class plViewFaceModifier : public plSingleModifier
{
public:
enum plVFFlags {
kPivotFace = 0,
kPivotFavorY,
kPivotY,
kPivotTumble,
kScale,
kFaceCam,
kFaceList,
kFacePlay,
kFaceObj,
kOffset,
kOffsetLocal,
kMaxBounds
};
protected:
hsVector3 fLastDirY;
hsVector3 fScale;
hsMatrix44 fOrigLocalToParent;
hsMatrix44 fOrigParentToLocal;
hsPoint3 fFacePoint;
plSceneObject* fFaceObj;
hsVector3 fOffset;
hsBounds3Ext fMaxBounds;
virtual hsBool IFacePoint(plPipeline* pipe, const hsPoint3& at);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
enum RefType
{
kRefFaceObj
};
void IOnReceive(plGenRefMsg* refMsg);
void IOnRemove(plGenRefMsg* refMsg);
void ISetObject(plKey soKey);
public:
plViewFaceModifier();
virtual ~plViewFaceModifier();
CLASSNAME_REGISTER( plViewFaceModifier );
GETINTERFACE_ANY( plViewFaceModifier, plSingleModifier );
virtual void SetTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
// ViewFace specific
void SetScale(const hsVector3& s) { fScale = s; }
const hsVector3& GetScale() const { return fScale; }
void SetOrigTransform(const hsMatrix44& l2p, const hsMatrix44& p2l);
void SetMaxBounds(const hsBounds3Ext& bnd);
const hsBounds3Ext& GetMaxBounds() const { return fMaxBounds; }
hsBool HaveMaxBounds() const { return HasFlag(kMaxBounds); }
enum FollowMode
{
kFollowCamera = 0, // Follow the camera
kFollowListener,
kFollowPlayer,
kFollowObject
};
void SetFollowMode(FollowMode m, plKey soKey=nil); // For follow object, set obj, else it's ignored.
FollowMode GetFollowMode() const;
plSceneObject* GetFollowObject() const { return fFaceObj; }
void SetOffsetActive(hsBool on) { if(on) SetFlag(kOffset); else ClearFlag(kOffset); }
hsBool GetOffsetActive() const { return HasFlag(kOffset); }
void SetOffset(const hsVector3& off, hsBool local=true);
const hsVector3& GetOffset() const { return fOffset; }
hsBool GetOffsetLocal() const { return HasFlag(kOffsetLocal); }
};
#endif // plViewFaceModifier_inc