You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
485 lines
12 KiB
485 lines
12 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
#include "plPointChannel.h" |
|
#include "plScalarChannel.h" |
|
#include "hsResMgr.h" |
|
|
|
#include "../pnSceneObject/plDrawInterface.h" |
|
#include "../pnSceneObject/plSimulationInterface.h" |
|
#include "../pnSceneObject/plCoordinateInterface.h" |
|
#include "../pnSceneObject/plAudioInterface.h" |
|
#include "../plInterp/plController.h" |
|
#include "../plInterp/plAnimTimeConvert.h" |
|
#include "../plGLight/plLightInfo.h" |
|
|
|
////////////// |
|
// PLPOINTSRCE |
|
////////////// |
|
|
|
// CTOR |
|
plPointChannel::plPointChannel() |
|
: plAGChannel(), fResult(0, 0, 0) |
|
{ |
|
} |
|
|
|
// DTOR |
|
plPointChannel::~plPointChannel() |
|
{ |
|
} |
|
|
|
// VALUE |
|
// default behaviour is just to return our result (constant value) |
|
const hsPoint3 & plPointChannel::Value(double time) |
|
{ |
|
return fResult; |
|
} |
|
|
|
// VALUE(point, time) |
|
void plPointChannel::Value(hsPoint3 &point, double time) |
|
{ |
|
point = Value(time); |
|
} |
|
|
|
// MAKECOMBINE |
|
plAGChannel * plPointChannel::MakeCombine(plAGChannel *channelA) |
|
{ |
|
return nil; |
|
} |
|
|
|
// MAKEBLEND |
|
plAGChannel * plPointChannel::MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority) |
|
{ |
|
return TRACKED_NEW plPointBlend(this, (plPointChannel *)channelB, channelBias); |
|
} |
|
|
|
// MAKEZEROSTATE |
|
plAGChannel * plPointChannel::MakeZeroState() |
|
{ |
|
return TRACKED_NEW plPointConstant(Value(0)); |
|
} |
|
|
|
// MAKETIMESCALE |
|
plAGChannel * plPointChannel::MakeTimeScale(plScalarChannel *timeSource) |
|
{ |
|
return TRACKED_NEW plPointTimeScale(this, timeSource); |
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// plPointConstant |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
// ctor -------------------------- |
|
// ----- |
|
plPointConstant::plPointConstant() |
|
: plPointChannel() |
|
{ |
|
} |
|
|
|
// ctor ----------------------------------------------- |
|
// ----- |
|
plPointConstant::plPointConstant(const hsPoint3 &point) |
|
{ |
|
fResult = point; |
|
} |
|
|
|
// dtor --------------------------- |
|
// ----- |
|
plPointConstant::~plPointConstant() |
|
{ |
|
} |
|
|
|
void plPointConstant::Read(hsStream *stream, hsResMgr *mgr) |
|
{ |
|
plPointChannel::Read(stream, mgr); |
|
fResult.Read(stream); |
|
} |
|
|
|
void plPointConstant::Write(hsStream *stream, hsResMgr *mgr) |
|
{ |
|
plPointChannel::Write(stream, mgr); |
|
fResult.Write(stream); |
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// PLPOINTTIMESCALE |
|
// |
|
// Insert into the graph when you need to change the speed or direction of time |
|
// Also serves as a handy instancing node, since it just passes its data through. |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
// ctor ---------------------------- |
|
// ----- |
|
plPointTimeScale::plPointTimeScale() |
|
: fTimeSource(nil), fChannelIn(nil) |
|
{ |
|
} |
|
|
|
// ctor -------------------------------------------------------------------------------- |
|
// ----- |
|
plPointTimeScale::plPointTimeScale(plPointChannel *channel, plScalarChannel *timeSource) |
|
: fChannelIn(channel), |
|
fTimeSource(timeSource) |
|
{ |
|
} |
|
|
|
// dtor ----------------------------- |
|
// ----- |
|
plPointTimeScale::~plPointTimeScale() |
|
{ |
|
} |
|
|
|
// IsStoppedAt --------------------------- |
|
// ------------ |
|
hsBool plPointTimeScale::IsStoppedAt(double time) |
|
{ |
|
return fTimeSource->IsStoppedAt(time); |
|
} |
|
|
|
// Value -------------------------------------------- |
|
// ------ |
|
const hsPoint3 & plPointTimeScale::Value(double time) |
|
{ |
|
fResult = fChannelIn->Value(fTimeSource->Value(time)); |
|
|
|
return fResult; |
|
} |
|
|
|
// Detach --------------------------------------------------- |
|
// ------- |
|
plAGChannel * plPointTimeScale::Detach(plAGChannel * channel) |
|
{ |
|
plAGChannel *result = this; |
|
|
|
fChannelIn = plPointChannel::ConvertNoRef(fChannelIn->Detach(channel)); |
|
|
|
if(!fChannelIn || channel == this) |
|
result = nil; |
|
|
|
if(result != this) |
|
delete this; |
|
|
|
return result; |
|
|
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// plPointBlend |
|
// |
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
// ctor -------------------- |
|
// ----- |
|
plPointBlend::plPointBlend() |
|
: fPointA(nil), |
|
fPointB(nil) |
|
{ |
|
} |
|
|
|
// ctor --------------------------------------------------------------------------------- |
|
// ----- |
|
plPointBlend::plPointBlend(plPointChannel *channelA, plPointChannel *channelB, |
|
plScalarChannel *channelBias) |
|
: fPointA(channelA), |
|
fPointB(channelB), |
|
fChannelBias(channelBias) |
|
{ |
|
} |
|
|
|
// dtor --------------------- |
|
// ----- |
|
plPointBlend::~plPointBlend() |
|
{ |
|
fPointA = nil; |
|
fPointB = nil; |
|
fChannelBias = nil; |
|
} |
|
|
|
// IsStoppedAt ------------------------------ |
|
// ------------ |
|
hsBool plPointBlend::IsStoppedAt(double time) |
|
{ |
|
hsScalar blend = fChannelBias->Value(time); |
|
if (blend == 0) |
|
return fPointA->IsStoppedAt(time); |
|
if (blend == 1) |
|
return fPointB->IsStoppedAt(time); |
|
|
|
return (fPointA->IsStoppedAt(time) && fPointB->IsStoppedAt(time)); |
|
} |
|
|
|
// Value --------------------------------------- |
|
// ------ |
|
const hsPoint3 &plPointBlend::Value(double time) |
|
{ |
|
if (fPointA && fPointB) |
|
{ |
|
hsScalar curBlend = fChannelBias->Value(time); |
|
if(curBlend == 0) { |
|
fPointA->Value(fResult, time); |
|
} else { |
|
if(curBlend == 1) { |
|
fPointB->Value(fResult, time); |
|
} else { |
|
const hsPoint3 &pointA = fPointA->Value(time); |
|
const hsPoint3 &pointB = fPointB->Value(time); |
|
hsPoint3 difference = pointB - pointA; |
|
|
|
difference *= curBlend; |
|
|
|
fResult = pointA + difference; |
|
} |
|
} |
|
} else { |
|
if (fPointA) |
|
{ |
|
fResult = fPointA->Value(time); |
|
} else { |
|
if (fPointB) |
|
{ |
|
fResult = fPointA->Value(time); |
|
} |
|
} |
|
} |
|
return fResult; |
|
} |
|
|
|
// Detach ------------------------------------------------------ |
|
// ------- |
|
plAGChannel * plPointBlend::Detach(plAGChannel *remove) |
|
{ |
|
plAGChannel *result = this; |
|
|
|
if (remove == this) |
|
{ |
|
result = nil; |
|
} else { |
|
// it's possible that the incoming channel could reside down *all* of our |
|
// branches (it's a graph, not a tree,) so we always pass down all limbs |
|
fChannelBias = plScalarChannel::ConvertNoRef(fChannelBias->Detach(remove)); |
|
fPointA = plPointChannel::ConvertNoRef(fPointA->Detach(remove)); |
|
fPointB = plPointChannel::ConvertNoRef(fPointB->Detach(remove)); |
|
if (!fChannelBias) |
|
{ |
|
// No more bias channel, assume it's zero from now on, (a.k.a. We just want channelA) |
|
result = fPointA; |
|
} |
|
else |
|
{ |
|
if(!fChannelBias) |
|
result = fPointA; |
|
else if(fPointA && !fPointB) |
|
result = fPointA; |
|
else if(fPointB && !fPointA) |
|
result = fPointB; |
|
else if(!fPointA && !fPointB) |
|
result = nil; |
|
if(result != this) |
|
{ |
|
delete this; |
|
} |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/////////////////////////// |
|
// PLPOINTCONTROLLERCHANNEL |
|
/////////////////////////// |
|
|
|
// CTOR |
|
plPointControllerChannel::plPointControllerChannel() |
|
: fController(nil) |
|
{ |
|
} |
|
|
|
// CTOR(name, controller) |
|
plPointControllerChannel::plPointControllerChannel(plController *controller) |
|
: fController(controller) |
|
{ |
|
} |
|
|
|
// ~DTOR() |
|
plPointControllerChannel::~plPointControllerChannel() |
|
{ |
|
if(fController) { |
|
delete fController; |
|
fController = nil; |
|
} |
|
} |
|
|
|
// VALUE(time) |
|
const hsPoint3 & plPointControllerChannel::Value(double time) |
|
{ |
|
return Value(time, nil); |
|
} |
|
|
|
// VALUE(time) |
|
const hsPoint3 & plPointControllerChannel::Value(double time, plControllerCacheInfo *cache) |
|
{ |
|
fController->Interp((hsScalar)time, &fResult, cache); |
|
return fResult; |
|
} |
|
|
|
plAGChannel *plPointControllerChannel::MakeCacheChannel(plAnimTimeConvert *atc) |
|
{ |
|
plControllerCacheInfo *cache = fController->CreateCache(); |
|
cache->SetATC(atc); |
|
return TRACKED_NEW plPointControllerCacheChannel(this, cache); |
|
} |
|
|
|
// WRITE(stream, mgr) |
|
void plPointControllerChannel::Write(hsStream *stream, hsResMgr *mgr) |
|
{ |
|
plPointChannel::Write(stream, mgr); |
|
|
|
hsAssert(fController, "Trying to write plPointControllerChannel with nil controller. File will not be importable."); |
|
mgr->WriteCreatable(stream, fController); |
|
} |
|
|
|
// READ(stream, mgr) |
|
void plPointControllerChannel::Read(hsStream *stream, hsResMgr *mgr) |
|
{ |
|
plPointChannel::Read(stream, mgr); |
|
|
|
fController = plController::ConvertNoRef(mgr->ReadCreatable(stream)); |
|
} |
|
|
|
///////////////////////////////// |
|
// PLPOINTCONTROLLERCACHECHANNEL |
|
///////////////////////////////// |
|
|
|
// CTOR |
|
plPointControllerCacheChannel::plPointControllerCacheChannel() |
|
: fControllerChannel(nil), |
|
fCache(nil) |
|
{ |
|
} |
|
|
|
// CTOR(name, controller) |
|
plPointControllerCacheChannel::plPointControllerCacheChannel(plPointControllerChannel *controller, plControllerCacheInfo *cache) |
|
: fControllerChannel(controller), |
|
fCache(cache) |
|
{ |
|
} |
|
|
|
// ~DTOR() |
|
plPointControllerCacheChannel::~plPointControllerCacheChannel() |
|
{ |
|
delete fCache; |
|
fControllerChannel = nil; |
|
} |
|
|
|
// VALUE(time) |
|
const hsPoint3 & plPointControllerCacheChannel::Value(double time, bool peek) |
|
{ |
|
return fControllerChannel->Value(time, fCache); |
|
} |
|
|
|
// DETACH |
|
plAGChannel * plPointControllerCacheChannel::Detach(plAGChannel * channel) |
|
{ |
|
if(channel == this) |
|
{ |
|
return nil; |
|
} else { |
|
plAGChannel *result = fControllerChannel->Detach(channel); |
|
|
|
if(result == fControllerChannel) |
|
{ |
|
return this; |
|
} else { |
|
// if our controller channel has been detached, then detach ourselves as well. |
|
return result; |
|
} |
|
} |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// Channel applicators |
|
|
|
void plPointChannelApplicator::IApply(const plAGModifier *modifier, double time) |
|
{ |
|
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel); |
|
hsAssert(pointChan, "Invalid channel given to plPointChannelApplicator"); |
|
|
|
plCoordinateInterface *CI = IGetCI(modifier); |
|
|
|
hsMatrix44 l2p = CI->GetLocalToParent(); |
|
const hsPoint3 &point = pointChan->Value(time); |
|
|
|
l2p.SetTranslate(&point); |
|
|
|
hsMatrix44 p2l; |
|
l2p.GetInverse(&p2l); |
|
CI->SetLocalToParent(l2p, p2l); |
|
} |
|
|
|
void plLightDiffuseApplicator::IApply(const plAGModifier *modifier, double time) |
|
{ |
|
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel); |
|
hsAssert(pointChan, "Invalid channel given to plLightDiffuseApplicator"); |
|
|
|
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index())); |
|
|
|
const hsPoint3 &point = pointChan->Value(time); |
|
hsColorRGBA color; |
|
color.Set(point.fX, point.fY, point.fZ, 1.0f); |
|
li->SetDiffuse(color); |
|
} |
|
|
|
void plLightAmbientApplicator::IApply(const plAGModifier *modifier, double time) |
|
{ |
|
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel); |
|
hsAssert(pointChan, "Invalid channel given to plLightAmbientApplicator"); |
|
|
|
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index())); |
|
|
|
const hsPoint3 &point = pointChan->Value(time); |
|
hsColorRGBA color; |
|
color.Set(point.fX, point.fY, point.fZ, 1.0f); |
|
li->SetAmbient(color); |
|
} |
|
|
|
void plLightSpecularApplicator::IApply(const plAGModifier *modifier, double time) |
|
{ |
|
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel); |
|
hsAssert(pointChan, "Invalid channel given to plLightSpecularApplicator"); |
|
|
|
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index())); |
|
|
|
const hsPoint3 &point = pointChan->Value(time); |
|
hsColorRGBA color; |
|
color.Set(point.fX, point.fY, point.fZ, 1.0f); |
|
li->SetSpecular(color); |
|
} |
|
|
|
|
|
|