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

Fix line endings and tabs

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

View File

@ -1,37 +1,37 @@
include_directories("../../CoreLib")
include_directories("../../NucleusLib/inc")
include_directories("../../NucleusLib")
include_directories("../../PubUtilLib")
include_directories(${OPENSSL_INCLUDE_DIR})
set(plGLight_SOURCES
plDirectShadowMaster.cpp
plLightInfo.cpp
plLightProxy.cpp
plLightSpace.cpp
plPerspDirSlave.cpp
plPointShadowMaster.cpp
plShadowCaster.cpp
plShadowMaster.cpp
plShadowSlave.cpp
)
set(plGLight_HEADERS
plDirectShadowMaster.h
plGLightCreatable.h
plLightInfo.h
plLightKonstants.h
plLightProxy.h
plLightSpace.h
plPerspDirSlave.h
plPointShadowMaster.h
plShadowCaster.h
plShadowMaster.h
plShadowSlave.h
)
add_library(plGLight STATIC ${plGLight_SOURCES} ${plGLight_HEADERS})
source_group("Source Files" FILES ${plGLight_SOURCES})
source_group("Header Files" FILES ${plGLight_HEADERS})
include_directories("../../CoreLib")
include_directories("../../NucleusLib/inc")
include_directories("../../NucleusLib")
include_directories("../../PubUtilLib")
include_directories(${OPENSSL_INCLUDE_DIR})
set(plGLight_SOURCES
plDirectShadowMaster.cpp
plLightInfo.cpp
plLightProxy.cpp
plLightSpace.cpp
plPerspDirSlave.cpp
plPointShadowMaster.cpp
plShadowCaster.cpp
plShadowMaster.cpp
plShadowSlave.cpp
)
set(plGLight_HEADERS
plDirectShadowMaster.h
plGLightCreatable.h
plLightInfo.h
plLightKonstants.h
plLightProxy.h
plLightSpace.h
plPerspDirSlave.h
plPointShadowMaster.h
plShadowCaster.h
plShadowMaster.h
plShadowSlave.h
)
add_library(plGLight STATIC ${plGLight_SOURCES} ${plGLight_HEADERS})
source_group("Source Files" FILES ${plGLight_SOURCES})
source_group("Header Files" FILES ${plGLight_HEADERS})

View File

@ -1,189 +1,189 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plDirectShadowMaster.h"
#include "plShadowSlave.h"
#include "plPerspDirSlave.h"
#include "plShadowCaster.h"
#include "plMessage/plShadowCastMsg.h"
#include "plLightInfo.h"
#include "hsMatrix44.h"
#include "hsBounds.h"
#include "hsFastMath.h"
////////////////////////////////////////////////////////////////////////////////////
// Point first, directional lights follow
////////////////////////////////////////////////////////////////////////////////////
plDirectShadowMaster::plDirectShadowMaster()
{
}
plDirectShadowMaster::~plDirectShadowMaster()
{
fIsectPool.SetCount(fIsectPool.GetNumAlloc());
int i;
for( i = 0; i < fIsectPool.GetCount(); i++ )
delete fIsectPool[i];
}
plShadowSlave* plDirectShadowMaster::INewSlave(const plShadowCaster* caster)
{
if( caster->GetPerspective() )
return TRACKED_NEW plPerspDirSlave;
return TRACKED_NEW plDirectShadowSlave;
}
plShadowSlave* plDirectShadowMaster::INextSlave(const plShadowCaster* caster)
{
if( !caster->GetPerspective() )
return plShadowMaster::INextSlave(caster);
int iSlave = fPerspSlavePool.GetCount();
fPerspSlavePool.ExpandAndZero(iSlave+1);
plShadowSlave* slave = fPerspSlavePool[iSlave];
if( !slave )
{
fPerspSlavePool[iSlave] = slave = INewSlave(caster);
}
return slave;
}
plShadowSlave* plDirectShadowMaster::IRecycleSlave(plShadowSlave* slave)
{
if( fSlavePool.GetCount() && (fSlavePool[fSlavePool.GetCount()-1] == slave) )
fSlavePool.SetCount(fSlavePool.GetCount()-1);
else
if( fPerspSlavePool.GetCount() && (fPerspSlavePool[fPerspSlavePool.GetCount()-1] == slave) )
fPerspSlavePool.SetCount(fPerspSlavePool.GetCount()-1);
return nil;
}
void plDirectShadowMaster::IBeginRender()
{
plShadowMaster::IBeginRender();
fPerspSlavePool.SetCount(0);
fIsectPool.SetCount(0);
}
void plDirectShadowMaster::IComputeWorldToLight(const hsBounds3Ext& wBnd, plShadowSlave* slave) const
{
hsMatrix44 kFlipDir;
kFlipDir.Reset();
kFlipDir.NotIdentity();
kFlipDir.fMap[2][2] = -1.f;
hsMatrix44 worldToLight = kFlipDir * fLightInfo->GetWorldToLight();
hsMatrix44 lightToWorld = fLightInfo->GetLightToWorld() * kFlipDir;
hsBounds3Ext bnd = wBnd;
bnd.Transform(&worldToLight);
hsPoint3 pos = bnd.GetCenter();
pos.fZ = bnd.GetMins().fZ;
hsPoint3 wPos = lightToWorld * pos;
lightToWorld.NotIdentity();
lightToWorld.fMap[0][3] = wPos[0];
lightToWorld.fMap[1][3] = wPos[1];
lightToWorld.fMap[2][3] = wPos[2];
// Need worldToLight and hate doing an inverse.
// worldToLight = pureTrans * pureRot;
// lightToWorld = Inv(pureRot) * Inv(pureTran);
// So Inv(pureTran) = pureRot * Inv(pureRot) * Inv(pureTran) = pureRot * lightToWorld
// Make worldToLight pure rotation inverse of lightToWorld
worldToLight.fMap[0][3] = 0;
worldToLight.fMap[1][3] = 0;
worldToLight.fMap[2][3] = 0;
hsMatrix44 trans = worldToLight * lightToWorld;
worldToLight.fMap[0][3] = -trans.fMap[0][3];
worldToLight.fMap[1][3] = -trans.fMap[1][3];
worldToLight.fMap[2][3] = -trans.fMap[2][3];
//#define CHECK_INVERSE
#ifdef CHECK_INVERSE
hsMatrix44 inv;
lightToWorld.GetInverse(&inv);
#endif // CHECK_INVERSE
slave->fWorldToLight = worldToLight;
slave->fLightToWorld = lightToWorld;
}
void plDirectShadowMaster::IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const
{
slave->fView.SetPerspective(false);
}
void plDirectShadowMaster::IComputeISect(const hsBounds3Ext& casterBnd, plShadowSlave* slave) const
{
int iIsect = fIsectPool.GetCount();
fIsectPool.ExpandAndZero(iIsect+1);
if( !fIsectPool[iIsect] )
{
fIsectPool[iIsect] = TRACKED_NEW plBoundsIsect;
}
plBoundsIsect* isect = fIsectPool[iIsect];
const hsBounds3Ext& wBnd = slave->fWorldBounds;
isect->SetBounds(wBnd);
slave->fIsect = isect;
}
void plDirectShadowMaster::IComputeBounds(const hsBounds3Ext& casterBnd, plShadowSlave* slave) const
{
// Plan here is to look at the bounds in the slave's local space.
// Our slave's bounds will clearly contain the shadow caster's bounds. It will also
// contain the bnd's corners extended out in light space Z.
// They will extend fAttenDist farther than the center pointof the bound.
hsBounds3Ext bnd = casterBnd;
bnd.Transform(&slave->fWorldToLight);
hsPoint3 farPt = bnd.GetCenter();
farPt.fZ += slave->fAttenDist;
bnd.Union(&farPt);
bnd.Transform(&slave->fLightToWorld);
slave->fWorldBounds = bnd;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plDirectShadowMaster.h"
#include "plShadowSlave.h"
#include "plPerspDirSlave.h"
#include "plShadowCaster.h"
#include "plMessage/plShadowCastMsg.h"
#include "plLightInfo.h"
#include "hsMatrix44.h"
#include "hsBounds.h"
#include "hsFastMath.h"
////////////////////////////////////////////////////////////////////////////////////
// Point first, directional lights follow
////////////////////////////////////////////////////////////////////////////////////
plDirectShadowMaster::plDirectShadowMaster()
{
}
plDirectShadowMaster::~plDirectShadowMaster()
{
fIsectPool.SetCount(fIsectPool.GetNumAlloc());
int i;
for( i = 0; i < fIsectPool.GetCount(); i++ )
delete fIsectPool[i];
}
plShadowSlave* plDirectShadowMaster::INewSlave(const plShadowCaster* caster)
{
if( caster->GetPerspective() )
return TRACKED_NEW plPerspDirSlave;
return TRACKED_NEW plDirectShadowSlave;
}
plShadowSlave* plDirectShadowMaster::INextSlave(const plShadowCaster* caster)
{
if( !caster->GetPerspective() )
return plShadowMaster::INextSlave(caster);
int iSlave = fPerspSlavePool.GetCount();
fPerspSlavePool.ExpandAndZero(iSlave+1);
plShadowSlave* slave = fPerspSlavePool[iSlave];
if( !slave )
{
fPerspSlavePool[iSlave] = slave = INewSlave(caster);
}
return slave;
}
plShadowSlave* plDirectShadowMaster::IRecycleSlave(plShadowSlave* slave)
{
if( fSlavePool.GetCount() && (fSlavePool[fSlavePool.GetCount()-1] == slave) )
fSlavePool.SetCount(fSlavePool.GetCount()-1);
else
if( fPerspSlavePool.GetCount() && (fPerspSlavePool[fPerspSlavePool.GetCount()-1] == slave) )
fPerspSlavePool.SetCount(fPerspSlavePool.GetCount()-1);
return nil;
}
void plDirectShadowMaster::IBeginRender()
{
plShadowMaster::IBeginRender();
fPerspSlavePool.SetCount(0);
fIsectPool.SetCount(0);
}
void plDirectShadowMaster::IComputeWorldToLight(const hsBounds3Ext& wBnd, plShadowSlave* slave) const
{
hsMatrix44 kFlipDir;
kFlipDir.Reset();
kFlipDir.NotIdentity();
kFlipDir.fMap[2][2] = -1.f;
hsMatrix44 worldToLight = kFlipDir * fLightInfo->GetWorldToLight();
hsMatrix44 lightToWorld = fLightInfo->GetLightToWorld() * kFlipDir;
hsBounds3Ext bnd = wBnd;
bnd.Transform(&worldToLight);
hsPoint3 pos = bnd.GetCenter();
pos.fZ = bnd.GetMins().fZ;
hsPoint3 wPos = lightToWorld * pos;
lightToWorld.NotIdentity();
lightToWorld.fMap[0][3] = wPos[0];
lightToWorld.fMap[1][3] = wPos[1];
lightToWorld.fMap[2][3] = wPos[2];
// Need worldToLight and hate doing an inverse.
// worldToLight = pureTrans * pureRot;
// lightToWorld = Inv(pureRot) * Inv(pureTran);
// So Inv(pureTran) = pureRot * Inv(pureRot) * Inv(pureTran) = pureRot * lightToWorld
// Make worldToLight pure rotation inverse of lightToWorld
worldToLight.fMap[0][3] = 0;
worldToLight.fMap[1][3] = 0;
worldToLight.fMap[2][3] = 0;
hsMatrix44 trans = worldToLight * lightToWorld;
worldToLight.fMap[0][3] = -trans.fMap[0][3];
worldToLight.fMap[1][3] = -trans.fMap[1][3];
worldToLight.fMap[2][3] = -trans.fMap[2][3];
//#define CHECK_INVERSE
#ifdef CHECK_INVERSE
hsMatrix44 inv;
lightToWorld.GetInverse(&inv);
#endif // CHECK_INVERSE
slave->fWorldToLight = worldToLight;
slave->fLightToWorld = lightToWorld;
}
void plDirectShadowMaster::IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const
{
slave->fView.SetPerspective(false);
}
void plDirectShadowMaster::IComputeISect(const hsBounds3Ext& casterBnd, plShadowSlave* slave) const
{
int iIsect = fIsectPool.GetCount();
fIsectPool.ExpandAndZero(iIsect+1);
if( !fIsectPool[iIsect] )
{
fIsectPool[iIsect] = TRACKED_NEW plBoundsIsect;
}
plBoundsIsect* isect = fIsectPool[iIsect];
const hsBounds3Ext& wBnd = slave->fWorldBounds;
isect->SetBounds(wBnd);
slave->fIsect = isect;
}
void plDirectShadowMaster::IComputeBounds(const hsBounds3Ext& casterBnd, plShadowSlave* slave) const
{
// Plan here is to look at the bounds in the slave's local space.
// Our slave's bounds will clearly contain the shadow caster's bounds. It will also
// contain the bnd's corners extended out in light space Z.
// They will extend fAttenDist farther than the center pointof the bound.
hsBounds3Ext bnd = casterBnd;
bnd.Transform(&slave->fWorldToLight);
hsPoint3 farPt = bnd.GetCenter();
farPt.fZ += slave->fAttenDist;
bnd.Union(&farPt);
bnd.Transform(&slave->fLightToWorld);
slave->fWorldBounds = bnd;
}

View File

@ -1,63 +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/>.
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 plDirectShdowMaster_inc
#define plDirectShdowMaster_inc
#include "plShadowMaster.h"
#include "hsGeometry3.h"
class plBoundsIsect;
class plDirectShadowMaster : public plShadowMaster
{
protected:
mutable hsTArray<plBoundsIsect*> fIsectPool;
hsTArray<plShadowSlave*> fPerspSlavePool;
virtual void IComputeWorldToLight(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual void IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const;
virtual void IComputeISect(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual void IComputeBounds(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual plShadowSlave* INewSlave(const plShadowCaster* caster);
virtual plShadowSlave* INextSlave(const plShadowCaster* caster);
virtual plShadowSlave* IRecycleSlave(plShadowSlave* slave);
virtual void IBeginRender();
public:
plDirectShadowMaster();
virtual ~plDirectShadowMaster();
CLASSNAME_REGISTER( plDirectShadowMaster );
GETINTERFACE_ANY( plDirectShadowMaster, plShadowMaster );
};
#endif // plDirectShdowMaster_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plDirectShdowMaster_inc
#define plDirectShdowMaster_inc
#include "plShadowMaster.h"
#include "hsGeometry3.h"
class plBoundsIsect;
class plDirectShadowMaster : public plShadowMaster
{
protected:
mutable hsTArray<plBoundsIsect*> fIsectPool;
hsTArray<plShadowSlave*> fPerspSlavePool;
virtual void IComputeWorldToLight(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual void IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const;
virtual void IComputeISect(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual void IComputeBounds(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual plShadowSlave* INewSlave(const plShadowCaster* caster);
virtual plShadowSlave* INextSlave(const plShadowCaster* caster);
virtual plShadowSlave* IRecycleSlave(plShadowSlave* slave);
virtual void IBeginRender();
public:
plDirectShadowMaster();
virtual ~plDirectShadowMaster();
CLASSNAME_REGISTER( plDirectShadowMaster );
GETINTERFACE_ANY( plDirectShadowMaster, plShadowMaster );
};
#endif // plDirectShdowMaster_inc

View File

@ -1,60 +1,60 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plGLightCreatable_inc
#define plGLightCreatable_inc
#include "pnFactory/plCreator.h"
#include "plLightInfo.h"
REGISTER_NONCREATABLE( plLightInfo );
REGISTER_CREATABLE( plDirectionalLightInfo );
REGISTER_CREATABLE( plLimitedDirLightInfo );
REGISTER_CREATABLE( plOmniLightInfo );
REGISTER_CREATABLE( plSpotLightInfo );
#include "plLightSpace.h"
REGISTER_CREATABLE( plLightSpace );
#include "plShadowMaster.h"
REGISTER_NONCREATABLE( plShadowMaster );
#include "plPointShadowMaster.h"
REGISTER_CREATABLE( plPointShadowMaster );
#include "plDirectShadowMaster.h"
REGISTER_CREATABLE( plDirectShadowMaster );
#include "plShadowCaster.h"
REGISTER_CREATABLE( plShadowCaster );
#endif // plGLightCreatable_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plGLightCreatable_inc
#define plGLightCreatable_inc
#include "pnFactory/plCreator.h"
#include "plLightInfo.h"
REGISTER_NONCREATABLE( plLightInfo );
REGISTER_CREATABLE( plDirectionalLightInfo );
REGISTER_CREATABLE( plLimitedDirLightInfo );
REGISTER_CREATABLE( plOmniLightInfo );
REGISTER_CREATABLE( plSpotLightInfo );
#include "plLightSpace.h"
REGISTER_CREATABLE( plLightSpace );
#include "plShadowMaster.h"
REGISTER_NONCREATABLE( plShadowMaster );
#include "plPointShadowMaster.h"
REGISTER_CREATABLE( plPointShadowMaster );
#include "plDirectShadowMaster.h"
REGISTER_CREATABLE( plDirectShadowMaster );
#include "plShadowCaster.h"
REGISTER_CREATABLE( plShadowCaster );
#endif // plGLightCreatable_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,403 +1,403 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightInfo_inc
#define plLightInfo_inc
#include "pnSceneObject/plObjInterface.h"
#include "hsMatrix44.h"
#include "hsColorRGBA.h"
#include "plIntersect/plVolumeIsect.h"
#include "hsBitVector.h"
class hsStream;
class hsResMgr;
class plSpaceTree;
class hsGDeviceRef;
class hsGMaterial;
class plDrawableSpans;
class plLayerInterface;
class plPipeline;
class plDrawable;
class plSoftVolume;
class hsBounds3Ext;
class plVisRegion;
class plRenderRequest;
class plRenderTarget;
class plLightProxy;
class plLightInfo : public plObjInterface
{
public:
enum {
kDisable = 0x0, // prop 0 is always disable, declared in plObjInterface
kLPObsolete,
kLPCastShadows,
kLPMovable,
kLPHasIncludes,
kLPIncludesChars,
kLP_OBSOLECTE_0, // OLD
kLPOverAll,
kLPHasSpecular, // This is the same as a non-black specular color, but we use it here to make it faster to check
kLPShadowOnly,
kLPShadowLightGroup,
kLPForceProj,
kNumProps
};
enum LIRefType
{
kProjection = 0,
k_OBSOLECTE_REF_0, // OLD
k_OBSOLECTE_REF_1, // OLD
k_OBSOLECTE_REF_2, // OLD
kSoftVolume,
kVisRegion
};
protected:
// Volatile properties that shouldn't be network propagated.
enum VolatileFlags {
kVolNone = 0x0,
kVolDirty = 0x1,
kVolEmpty = 0x2,
kVolZero = 0x4
};
UInt8 fVolFlags;
hsBitVector fVisSet;
hsBitVector fVisNot;
hsTArray<plVisRegion*> fVisRegions;
plLightInfo** fPrevDevPtr;
plLightInfo* fNextDevPtr;
hsGDeviceRef* fDeviceRef;
plLayerInterface* fProjection;
hsMatrix44 fWorldToProj;
hsColorRGBA fAmbient;
hsColorRGBA fDiffuse;
hsColorRGBA fSpecular;
hsMatrix44 fLightToLocal;
hsMatrix44 fLocalToLight;
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
hsMatrix44 fLightToWorld;
hsMatrix44 fWorldToLight;
plKey fSceneNode;
plLightProxy* fProxyGen;
plSoftVolume* fSoftVolume;
hsScalar fMaxStrength;
hsBool fRegisteredForRenderMsg;
// Small shadow section
hsBitVector fSlaveBits;
virtual void IMakeIsect() = 0;
virtual plVolumeIsect* IGetIsect() = 0;
virtual void IRefresh();
virtual const hsMatrix44& IGetWorldToProj() const { return fWorldToProj; }
void IAddVisRegion(plVisRegion* reg);
void IRemoveVisRegion(plVisRegion* reg);
virtual void ISetSceneNode(plKey node);
void ICheckMaxStrength();
public:
plLightInfo();
virtual ~plLightInfo();
CLASSNAME_REGISTER( plLightInfo );
GETINTERFACE_ANY( plLightInfo, plObjInterface );
void SetDeviceRef(hsGDeviceRef* ref);
hsGDeviceRef* GetDeviceRef() const { return fDeviceRef; }
// Dirty state is local to this machine, so shouldn't be in the network synchronized properties.
hsBool IsDirty() const { return 0 != (fVolFlags & kVolDirty); }
void SetDirty(hsBool on=true) { if(on)fVolFlags |= kVolDirty; else fVolFlags &= ~kVolDirty; }
hsBool IsEmpty() const { return 0 != (fVolFlags & kVolEmpty); }
void SetEmpty(hsBool on=true) { if(on)fVolFlags |= kVolEmpty; else fVolFlags &= ~kVolEmpty; }
hsBool IsZero() const { return 0 != (fVolFlags & kVolZero); }
void SetZero(hsBool on) { if(on)fVolFlags |= kVolZero; else fVolFlags &= ~kVolZero; }
inline hsBool IsIdle() const;
hsBool OverAll() const { return GetProperty(kLPOverAll); }
hsBool IsShadowCaster() const { return GetProperty(kLPCastShadows); }
void SetShadowCaster(hsBool on) { SetProperty(kLPCastShadows, on); }
void Refresh() { if( IsDirty() ) { IRefresh(); SetDirty(false); } }
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
hsBool AffectsBound(const hsBounds3Ext& bnd) { return IGetIsect() ? IGetIsect()->Test(bnd) != kVolumeCulled : true; }
void GetAffectedForced(const plSpaceTree* space, hsBitVector& list, hsBool charac);
void GetAffected(const plSpaceTree* space, hsBitVector& list, hsBool charac);
const hsTArray<Int16>& GetAffected(plSpaceTree* space, const hsTArray<Int16>& visList, hsTArray<Int16>& litList, hsBool charac);
hsBool InVisSet(const hsBitVector& visSet) const { return fVisSet.Overlap(visSet); }
hsBool InVisNot(const hsBitVector& visNot) const { return fVisNot.Overlap(visNot); }
void SetAmbient(const hsColorRGBA& c) { fAmbient = c; SetDirty(); }
void SetDiffuse(const hsColorRGBA& c) { fDiffuse = c; SetDirty(); }
void SetSpecular(const hsColorRGBA& c);
const hsColorRGBA& GetAmbient() const { return fAmbient; }
const hsColorRGBA& GetDiffuse() const { return fDiffuse; }
const hsColorRGBA& GetSpecular() const { return fSpecular; }
plLayerInterface* GetProjection() const { return fProjection; }
virtual void SetProperty(int prop, hsBool on);
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual const hsMatrix44& GetLocalToWorld() const;
virtual const hsMatrix44& GetWorldToLocal() const;
virtual const hsMatrix44& GetLightToWorld() const;
virtual const hsMatrix44& GetWorldToLight() const;
virtual Int32 GetNumProperties() const { return kNumProps; }
const plSoftVolume* GetSoftVolume() const { return fSoftVolume; }
virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const = 0;
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
virtual void Unlink( void );
virtual void Link( plLightInfo **back );
virtual plLightInfo *GetNext( void ) { return fNextDevPtr; }
virtual hsBool IsLinked( void ) { return ( fNextDevPtr != nil || fPrevDevPtr != nil ) ? true : false; }
// New shadow
void ClearSlaveBits() { fSlaveBits.Clear(); }
void SetSlaveBit(int which) { fSlaveBits.SetBit(which); }
const hsBitVector& GetSlaveBits() const { return fSlaveBits; }
// These two should only be called internally and on export/convert
virtual plKey GetSceneNode() const;
// Export only. At runtime, the LocalToLight should be considered const.
void SetLocalToLight(const hsMatrix44& l2lt, const hsMatrix44& lt2l);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo) { return addTo; }
};
class plDirectionalLightInfo : public plLightInfo
{
protected:
virtual void IMakeIsect() {}
virtual plVolumeIsect* IGetIsect() { return nil; }
public:
plDirectionalLightInfo();
virtual ~plDirectionalLightInfo();
CLASSNAME_REGISTER( plDirectionalLightInfo );
GETINTERFACE_ANY( plDirectionalLightInfo, plLightInfo );
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
hsVector3 GetWorldDirection() const;
virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const { return -GetWorldDirection(); }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
};
class plLimitedDirLightInfo : public plDirectionalLightInfo
{
protected:
hsScalar fWidth;
hsScalar fHeight;
hsScalar fDepth;
plParallelIsect* fParPlanes;
virtual void IMakeIsect();
virtual plVolumeIsect* IGetIsect() { return fParPlanes; }
virtual void IRefresh();
public:
plLimitedDirLightInfo();
virtual ~plLimitedDirLightInfo();
CLASSNAME_REGISTER( plLimitedDirLightInfo );
GETINTERFACE_ANY( plLimitedDirLightInfo, plDirectionalLightInfo );
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
hsScalar GetWidth() const { return fWidth; }
hsScalar GetHeight() const { return fHeight; }
hsScalar GetDepth() const { return fDepth; }
void SetWidth(hsScalar w) { fWidth = w; }
void SetHeight(hsScalar h) { fHeight = h; }
void SetDepth(hsScalar d) { fDepth = d; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
};
class plOmniLightInfo : public plLightInfo
{
protected:
// Omni and spot
hsScalar fAttenConst;
hsScalar fAttenLinear;
hsScalar fAttenQuadratic;
hsScalar fAttenCutoff; // Only for attenuate-but-not-really mode, 0 otherwise
plSphereIsect* fSphere;
virtual void IMakeIsect();
virtual plVolumeIsect* IGetIsect() { return fSphere; }
virtual void IRefresh();
public:
plOmniLightInfo();
virtual ~plOmniLightInfo();
CLASSNAME_REGISTER( plOmniLightInfo );
GETINTERFACE_ANY( plOmniLightInfo, plLightInfo );
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const;
hsBool IsAttenuated() const { return (fAttenLinear != 0)||(fAttenQuadratic != 0) || ( fAttenCutoff != 0 ); }
hsScalar GetRadius() const;
hsScalar GetConstantAttenuation() const { return fAttenConst; }
hsScalar GetLinearAttenuation() const { return fAttenLinear; }
hsScalar GetQuadraticAttenuation() const { return fAttenQuadratic; }
hsScalar GetCutoffAttenuation() const { return fAttenCutoff; }
hsPoint3 GetWorldPosition() const { return fLightToWorld.GetTranslate(); }
void SetConstantAttenuation(hsScalar a) { fAttenConst = a; SetDirty(true); }
void SetLinearAttenuation(hsScalar a) { fAttenLinear = a; SetDirty(true); }
void SetQuadraticAttenuation(hsScalar a) { fAttenQuadratic = a; SetDirty(true); }
void SetCutoffAttenuation( hsScalar a ) { fAttenCutoff = a; SetDirty( true ); }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
};
class plSpotLightInfo : public plOmniLightInfo
{
protected:
// Valid only for spot
hsScalar fFalloff;
// Note - these are half angles, D3D wants whole angles, so fSpotInner*2 etc.
hsScalar fSpotInner;
hsScalar fSpotOuter;
hsScalar fEffectiveFOV;
plConeIsect* fCone;
virtual void IMakeIsect();
virtual plVolumeIsect* IGetIsect() { return fCone; }
virtual void IRefresh();
public:
plSpotLightInfo();
virtual ~plSpotLightInfo();
CLASSNAME_REGISTER( plSpotLightInfo );
GETINTERFACE_ANY( plSpotLightInfo, plOmniLightInfo );
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
hsVector3 GetWorldDirection() const;
virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const { return -GetWorldDirection(); }
void SetFalloff(hsScalar f) { fFalloff = f; SetDirty(true); }
void SetSpotInner(hsScalar rads) { fSpotInner = rads; SetDirty(true); }
void SetSpotOuter(hsScalar rads) { fSpotOuter = rads; SetDirty(true); }
hsScalar GetFalloff() const { return fFalloff; }
hsScalar GetSpotInner() const { return fSpotInner; }
hsScalar GetSpotOuter() const { return fSpotOuter; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
};
inline hsBool plLightInfo::IsIdle() const
{
if( GetProperty(kDisable) )
return true;
if( IsZero() )
return true;
if( IsEmpty() )
return true;
return false;
}
#endif // plLightInfo_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightInfo_inc
#define plLightInfo_inc
#include "pnSceneObject/plObjInterface.h"
#include "hsMatrix44.h"
#include "hsColorRGBA.h"
#include "plIntersect/plVolumeIsect.h"
#include "hsBitVector.h"
class hsStream;
class hsResMgr;
class plSpaceTree;
class hsGDeviceRef;
class hsGMaterial;
class plDrawableSpans;
class plLayerInterface;
class plPipeline;
class plDrawable;
class plSoftVolume;
class hsBounds3Ext;
class plVisRegion;
class plRenderRequest;
class plRenderTarget;
class plLightProxy;
class plLightInfo : public plObjInterface
{
public:
enum {
kDisable = 0x0, // prop 0 is always disable, declared in plObjInterface
kLPObsolete,
kLPCastShadows,
kLPMovable,
kLPHasIncludes,
kLPIncludesChars,
kLP_OBSOLECTE_0, // OLD
kLPOverAll,
kLPHasSpecular, // This is the same as a non-black specular color, but we use it here to make it faster to check
kLPShadowOnly,
kLPShadowLightGroup,
kLPForceProj,
kNumProps
};
enum LIRefType
{
kProjection = 0,
k_OBSOLECTE_REF_0, // OLD
k_OBSOLECTE_REF_1, // OLD
k_OBSOLECTE_REF_2, // OLD
kSoftVolume,
kVisRegion
};
protected:
// Volatile properties that shouldn't be network propagated.
enum VolatileFlags {
kVolNone = 0x0,
kVolDirty = 0x1,
kVolEmpty = 0x2,
kVolZero = 0x4
};
UInt8 fVolFlags;
hsBitVector fVisSet;
hsBitVector fVisNot;
hsTArray<plVisRegion*> fVisRegions;
plLightInfo** fPrevDevPtr;
plLightInfo* fNextDevPtr;
hsGDeviceRef* fDeviceRef;
plLayerInterface* fProjection;
hsMatrix44 fWorldToProj;
hsColorRGBA fAmbient;
hsColorRGBA fDiffuse;
hsColorRGBA fSpecular;
hsMatrix44 fLightToLocal;
hsMatrix44 fLocalToLight;
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
hsMatrix44 fLightToWorld;
hsMatrix44 fWorldToLight;
plKey fSceneNode;
plLightProxy* fProxyGen;
plSoftVolume* fSoftVolume;
hsScalar fMaxStrength;
hsBool fRegisteredForRenderMsg;
// Small shadow section
hsBitVector fSlaveBits;
virtual void IMakeIsect() = 0;
virtual plVolumeIsect* IGetIsect() = 0;
virtual void IRefresh();
virtual const hsMatrix44& IGetWorldToProj() const { return fWorldToProj; }
void IAddVisRegion(plVisRegion* reg);
void IRemoveVisRegion(plVisRegion* reg);
virtual void ISetSceneNode(plKey node);
void ICheckMaxStrength();
public:
plLightInfo();
virtual ~plLightInfo();
CLASSNAME_REGISTER( plLightInfo );
GETINTERFACE_ANY( plLightInfo, plObjInterface );
void SetDeviceRef(hsGDeviceRef* ref);
hsGDeviceRef* GetDeviceRef() const { return fDeviceRef; }
// Dirty state is local to this machine, so shouldn't be in the network synchronized properties.
hsBool IsDirty() const { return 0 != (fVolFlags & kVolDirty); }
void SetDirty(hsBool on=true) { if(on)fVolFlags |= kVolDirty; else fVolFlags &= ~kVolDirty; }
hsBool IsEmpty() const { return 0 != (fVolFlags & kVolEmpty); }
void SetEmpty(hsBool on=true) { if(on)fVolFlags |= kVolEmpty; else fVolFlags &= ~kVolEmpty; }
hsBool IsZero() const { return 0 != (fVolFlags & kVolZero); }
void SetZero(hsBool on) { if(on)fVolFlags |= kVolZero; else fVolFlags &= ~kVolZero; }
inline hsBool IsIdle() const;
hsBool OverAll() const { return GetProperty(kLPOverAll); }
hsBool IsShadowCaster() const { return GetProperty(kLPCastShadows); }
void SetShadowCaster(hsBool on) { SetProperty(kLPCastShadows, on); }
void Refresh() { if( IsDirty() ) { IRefresh(); SetDirty(false); } }
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
hsBool AffectsBound(const hsBounds3Ext& bnd) { return IGetIsect() ? IGetIsect()->Test(bnd) != kVolumeCulled : true; }
void GetAffectedForced(const plSpaceTree* space, hsBitVector& list, hsBool charac);
void GetAffected(const plSpaceTree* space, hsBitVector& list, hsBool charac);
const hsTArray<Int16>& GetAffected(plSpaceTree* space, const hsTArray<Int16>& visList, hsTArray<Int16>& litList, hsBool charac);
hsBool InVisSet(const hsBitVector& visSet) const { return fVisSet.Overlap(visSet); }
hsBool InVisNot(const hsBitVector& visNot) const { return fVisNot.Overlap(visNot); }
void SetAmbient(const hsColorRGBA& c) { fAmbient = c; SetDirty(); }
void SetDiffuse(const hsColorRGBA& c) { fDiffuse = c; SetDirty(); }
void SetSpecular(const hsColorRGBA& c);
const hsColorRGBA& GetAmbient() const { return fAmbient; }
const hsColorRGBA& GetDiffuse() const { return fDiffuse; }
const hsColorRGBA& GetSpecular() const { return fSpecular; }
plLayerInterface* GetProjection() const { return fProjection; }
virtual void SetProperty(int prop, hsBool on);
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual const hsMatrix44& GetLocalToWorld() const;
virtual const hsMatrix44& GetWorldToLocal() const;
virtual const hsMatrix44& GetLightToWorld() const;
virtual const hsMatrix44& GetWorldToLight() const;
virtual Int32 GetNumProperties() const { return kNumProps; }
const plSoftVolume* GetSoftVolume() const { return fSoftVolume; }
virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const = 0;
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
virtual void Unlink( void );
virtual void Link( plLightInfo **back );
virtual plLightInfo *GetNext( void ) { return fNextDevPtr; }
virtual hsBool IsLinked( void ) { return ( fNextDevPtr != nil || fPrevDevPtr != nil ) ? true : false; }
// New shadow
void ClearSlaveBits() { fSlaveBits.Clear(); }
void SetSlaveBit(int which) { fSlaveBits.SetBit(which); }
const hsBitVector& GetSlaveBits() const { return fSlaveBits; }
// These two should only be called internally and on export/convert
virtual plKey GetSceneNode() const;
// Export only. At runtime, the LocalToLight should be considered const.
void SetLocalToLight(const hsMatrix44& l2lt, const hsMatrix44& lt2l);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo) { return addTo; }
};
class plDirectionalLightInfo : public plLightInfo
{
protected:
virtual void IMakeIsect() {}
virtual plVolumeIsect* IGetIsect() { return nil; }
public:
plDirectionalLightInfo();
virtual ~plDirectionalLightInfo();
CLASSNAME_REGISTER( plDirectionalLightInfo );
GETINTERFACE_ANY( plDirectionalLightInfo, plLightInfo );
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
hsVector3 GetWorldDirection() const;
virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const { return -GetWorldDirection(); }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
};
class plLimitedDirLightInfo : public plDirectionalLightInfo
{
protected:
hsScalar fWidth;
hsScalar fHeight;
hsScalar fDepth;
plParallelIsect* fParPlanes;
virtual void IMakeIsect();
virtual plVolumeIsect* IGetIsect() { return fParPlanes; }
virtual void IRefresh();
public:
plLimitedDirLightInfo();
virtual ~plLimitedDirLightInfo();
CLASSNAME_REGISTER( plLimitedDirLightInfo );
GETINTERFACE_ANY( plLimitedDirLightInfo, plDirectionalLightInfo );
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
hsScalar GetWidth() const { return fWidth; }
hsScalar GetHeight() const { return fHeight; }
hsScalar GetDepth() const { return fDepth; }
void SetWidth(hsScalar w) { fWidth = w; }
void SetHeight(hsScalar h) { fHeight = h; }
void SetDepth(hsScalar d) { fDepth = d; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
};
class plOmniLightInfo : public plLightInfo
{
protected:
// Omni and spot
hsScalar fAttenConst;
hsScalar fAttenLinear;
hsScalar fAttenQuadratic;
hsScalar fAttenCutoff; // Only for attenuate-but-not-really mode, 0 otherwise
plSphereIsect* fSphere;
virtual void IMakeIsect();
virtual plVolumeIsect* IGetIsect() { return fSphere; }
virtual void IRefresh();
public:
plOmniLightInfo();
virtual ~plOmniLightInfo();
CLASSNAME_REGISTER( plOmniLightInfo );
GETINTERFACE_ANY( plOmniLightInfo, plLightInfo );
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const;
hsBool IsAttenuated() const { return (fAttenLinear != 0)||(fAttenQuadratic != 0) || ( fAttenCutoff != 0 ); }
hsScalar GetRadius() const;
hsScalar GetConstantAttenuation() const { return fAttenConst; }
hsScalar GetLinearAttenuation() const { return fAttenLinear; }
hsScalar GetQuadraticAttenuation() const { return fAttenQuadratic; }
hsScalar GetCutoffAttenuation() const { return fAttenCutoff; }
hsPoint3 GetWorldPosition() const { return fLightToWorld.GetTranslate(); }
void SetConstantAttenuation(hsScalar a) { fAttenConst = a; SetDirty(true); }
void SetLinearAttenuation(hsScalar a) { fAttenLinear = a; SetDirty(true); }
void SetQuadraticAttenuation(hsScalar a) { fAttenQuadratic = a; SetDirty(true); }
void SetCutoffAttenuation( hsScalar a ) { fAttenCutoff = a; SetDirty( true ); }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
};
class plSpotLightInfo : public plOmniLightInfo
{
protected:
// Valid only for spot
hsScalar fFalloff;
// Note - these are half angles, D3D wants whole angles, so fSpotInner*2 etc.
hsScalar fSpotInner;
hsScalar fSpotOuter;
hsScalar fEffectiveFOV;
plConeIsect* fCone;
virtual void IMakeIsect();
virtual plVolumeIsect* IGetIsect() { return fCone; }
virtual void IRefresh();
public:
plSpotLightInfo();
virtual ~plSpotLightInfo();
CLASSNAME_REGISTER( plSpotLightInfo );
GETINTERFACE_ANY( plSpotLightInfo, plOmniLightInfo );
virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const;
hsVector3 GetWorldDirection() const;
virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const { return -GetWorldDirection(); }
void SetFalloff(hsScalar f) { fFalloff = f; SetDirty(true); }
void SetSpotInner(hsScalar rads) { fSpotInner = rads; SetDirty(true); }
void SetSpotOuter(hsScalar rads) { fSpotOuter = rads; SetDirty(true); }
hsScalar GetFalloff() const { return fFalloff; }
hsScalar GetSpotInner() const { return fSpotInner; }
hsScalar GetSpotOuter() const { return fSpotOuter; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
};
inline hsBool plLightInfo::IsIdle() const
{
if( GetProperty(kDisable) )
return true;
if( IsZero() )
return true;
if( IsEmpty() )
return true;
return false;
}
#endif // plLightInfo_inc

View File

@ -1,41 +1,41 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightKonstants_inc
#define plLightKonstants_inc
class plSillyLightKonstants
{
public:
static const float GetFarPowerKonst( void )
{
// arbitrary const, make light drop to 1/kFarPower at attenEnd. 15 just looked good to me. mf
// Done as a function so we don't have to worry about a separate .cpp file
return 15.f;
}
};
#endif // plLightKonstants_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightKonstants_inc
#define plLightKonstants_inc
class plSillyLightKonstants
{
public:
static const float GetFarPowerKonst( void )
{
// arbitrary const, make light drop to 1/kFarPower at attenEnd. 15 just looked good to me. mf
// Done as a function so we don't have to worry about a separate .cpp file
return 15.f;
}
};
#endif // plLightKonstants_inc

View File

@ -1,66 +1,66 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plLightProxy.h"
#include "plLightInfo.h"
#include "plDrawable/plDrawableSpans.h"
#include "plDrawable/plDrawableGenerator.h"
#include "pnMessage/plProxyDrawMsg.h"
plLightProxy::plLightProxy()
: plProxyGen(hsColorRGBA().Set(0,0,0,1.f), hsColorRGBA().Set(0.5f,1.0,0.5f,1.f), 0.2f),
fOwner(nil)
{
}
plLightProxy::~plLightProxy()
{
}
hsBool plLightProxy::Init(plLightInfo* liInfo)
{
plProxyGen::Init(liInfo);
fOwner = liInfo;
fProxyMsgType = plProxyDrawMsg::kLight;
return fOwner != nil;
}
plKey plLightProxy::IGetNode() const
{
return fOwner ? fOwner->GetSceneNode() : nil;
}
plDrawableSpans* plLightProxy::ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo)
{
if( fOwner )
{
return fOwner->CreateProxy(mat, idx, addTo);
}
return nil;
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plLightProxy.h"
#include "plLightInfo.h"
#include "plDrawable/plDrawableSpans.h"
#include "plDrawable/plDrawableGenerator.h"
#include "pnMessage/plProxyDrawMsg.h"
plLightProxy::plLightProxy()
: plProxyGen(hsColorRGBA().Set(0,0,0,1.f), hsColorRGBA().Set(0.5f,1.0,0.5f,1.f), 0.2f),
fOwner(nil)
{
}
plLightProxy::~plLightProxy()
{
}
hsBool plLightProxy::Init(plLightInfo* liInfo)
{
plProxyGen::Init(liInfo);
fOwner = liInfo;
fProxyMsgType = plProxyDrawMsg::kLight;
return fOwner != nil;
}
plKey plLightProxy::IGetNode() const
{
return fOwner ? fOwner->GetSceneNode() : nil;
}
plDrawableSpans* plLightProxy::ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo)
{
if( fOwner )
{
return fOwner->CreateProxy(mat, idx, addTo);
}
return nil;
}

View File

@ -1,49 +1,49 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightProxy_inc
#define plLightProxy_inc
#include "plDrawable/plProxyGen.h"
class plLightInfo;
class plLightProxy : public plProxyGen
{
protected:
plLightInfo* fOwner;
virtual plDrawableSpans* ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo=nil);
virtual plKey IGetNode() const;
public:
plLightProxy();
virtual ~plLightProxy();
hsBool Init(plLightInfo* liInfo);
};
#endif // plLightProxy_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightProxy_inc
#define plLightProxy_inc
#include "plDrawable/plProxyGen.h"
class plLightInfo;
class plLightProxy : public plProxyGen
{
protected:
plLightInfo* fOwner;
virtual plDrawableSpans* ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo=nil);
virtual plKey IGetNode() const;
public:
plLightProxy();
virtual ~plLightProxy();
hsBool Init(plLightInfo* liInfo);
};
#endif // plLightProxy_inc

View File

@ -1,76 +1,76 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plLightSpace.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "plMessage/plLightRefMsg.h"
#include "plMessage/plCollideMsg.h"
#include "plgDispatch.h"
hsBool plLightSpace::MsgReceive(plMessage* msg)
{
plCollideMsg* collMsg = plCollideMsg::ConvertNoRef(msg);
if( collMsg )
{
// HACK - CollideMsg doesn't have sufficient info yet. Need at least object
// which is entering and leaving, and whether it is entering or leaving.
plKey otherKey = nil;
hsBool enter = true;
UInt8 ctx = enter ? plRefMsg::kOnRequest : plRefMsg::kOnRemove;
plLightRefMsg* liMsg = TRACKED_NEW plLightRefMsg(GetKey(), otherKey, IGetLightInfo(), ctx);
plgDispatch::MsgSend(liMsg);
return true;
}
plLightRefMsg* liMsg = plLightRefMsg::ConvertNoRef(msg);
if( liMsg )
{
if( liMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fLightInfo = liMsg->GetRef();
else if( liMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fLightInfo = nil;
return true;
}
return false;
}
void plLightSpace::Read(hsStream* s, hsResMgr* mgr)
{
plMultiModifier::Read(s, mgr);
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plLightRefMsg(nil, GetKey(), nil, plRefMsg::kOnCreate), plRefFlags::kPassiveRef);
}
void plLightSpace::Write(hsStream* s, hsResMgr* mgr)
{
plMultiModifier::Write(s, mgr);
mgr->WriteKey(s, fLightInfo);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plLightSpace.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "plMessage/plLightRefMsg.h"
#include "plMessage/plCollideMsg.h"
#include "plgDispatch.h"
hsBool plLightSpace::MsgReceive(plMessage* msg)
{
plCollideMsg* collMsg = plCollideMsg::ConvertNoRef(msg);
if( collMsg )
{
// HACK - CollideMsg doesn't have sufficient info yet. Need at least object
// which is entering and leaving, and whether it is entering or leaving.
plKey otherKey = nil;
hsBool enter = true;
UInt8 ctx = enter ? plRefMsg::kOnRequest : plRefMsg::kOnRemove;
plLightRefMsg* liMsg = TRACKED_NEW plLightRefMsg(GetKey(), otherKey, IGetLightInfo(), ctx);
plgDispatch::MsgSend(liMsg);
return true;
}
plLightRefMsg* liMsg = plLightRefMsg::ConvertNoRef(msg);
if( liMsg )
{
if( liMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fLightInfo = liMsg->GetRef();
else if( liMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fLightInfo = nil;
return true;
}
return false;
}
void plLightSpace::Read(hsStream* s, hsResMgr* mgr)
{
plMultiModifier::Read(s, mgr);
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plLightRefMsg(nil, GetKey(), nil, plRefMsg::kOnCreate), plRefFlags::kPassiveRef);
}
void plLightSpace::Write(hsStream* s, hsResMgr* mgr)
{
plMultiModifier::Write(s, mgr);
mgr->WriteKey(s, fLightInfo);
}

View File

@ -1,59 +1,59 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightSpace_inc
#define plLightSpace_inc
class hsStream;
class hsResMgr;
#include "pnModifier/plMultiModifier.h"
class plLightSpace : public plMultiModifier
{
protected:
hsKeyedObject* fLightInfo;
hsKeyedObject* IGetLightInfo() const { return fLightInfo; }
public:
plLightSpace() : fLightInfo(nil) {}
virtual ~plLightSpace() {}
CLASSNAME_REGISTER( plLightSpace );
GETINTERFACE_ANY( plLightSpace, plMultiModifier );
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plLightSpace_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLightSpace_inc
#define plLightSpace_inc
class hsStream;
class hsResMgr;
#include "pnModifier/plMultiModifier.h"
class plLightSpace : public plMultiModifier
{
protected:
hsKeyedObject* fLightInfo;
hsKeyedObject* IGetLightInfo() const { return fLightInfo; }
public:
plLightSpace() : fLightInfo(nil) {}
virtual ~plLightSpace() {}
CLASSNAME_REGISTER( plLightSpace );
GETINTERFACE_ANY( plLightSpace, plMultiModifier );
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plLightSpace_inc

View File

@ -1,372 +1,372 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plPipeline.h"
#include "plTweak.h"
#include "hsFastMath.h"
#include "plPerspDirSlave.h"
#include <float.h>
void plPerspDirSlave::Init()
{
plShadowSlave::Init();
fFlags |= kCastInCameraSpace;
}
hsPoint3 plPerspDirSlave::IProject(const hsMatrix44& world2NDC, const hsPoint3& pos, hsScalar w) const
{
hsPoint3 retVal;
retVal.fX = world2NDC.fMap[0][0] * pos.fX
+ world2NDC.fMap[0][1] * pos.fY
+ world2NDC.fMap[0][2] * pos.fZ
+ world2NDC.fMap[0][3] * w;
retVal.fY = world2NDC.fMap[1][0] * pos.fX
+ world2NDC.fMap[1][1] * pos.fY
+ world2NDC.fMap[1][2] * pos.fZ
+ world2NDC.fMap[1][3] * w;
retVal.fZ = world2NDC.fMap[2][0] * pos.fX
+ world2NDC.fMap[2][1] * pos.fY
+ world2NDC.fMap[2][2] * pos.fZ
+ world2NDC.fMap[2][3] * w;
hsScalar invW = 1.f / (
world2NDC.fMap[3][0] * pos.fX
+ world2NDC.fMap[3][1] * pos.fY
+ world2NDC.fMap[3][2] * pos.fZ
+ world2NDC.fMap[3][3] * w);
retVal *= invW;
return retVal;
}
hsBounds3Ext plPerspDirSlave::IGetPerspCasterBound(const hsMatrix44& world2NDC) const
{
hsPoint3 corners[8];
fCasterWorldBounds.GetCorners(corners);
hsPoint3 perspCorners[8];
int i;
for( i = 0; i < 8; i++ )
{
perspCorners[i] = IProject(world2NDC, corners[i]);
if( perspCorners[i].fX < -1.f )
perspCorners[i].fX = -1.f;
else if( perspCorners[i].fX > 1.f )
perspCorners[i].fX = 1.f;
if( perspCorners[i].fY < -1.f )
perspCorners[i].fY = -1.f;
else if( perspCorners[i].fY > 1.f )
perspCorners[i].fY = 1.f;
if( perspCorners[i].fZ < 0 )
perspCorners[i].Set(0.f, 0.f, 0.f);
}
hsBounds3Ext bnd;
bnd.MakeEmpty();
for( i = 0; i < 8; i++ )
bnd.Union(&perspCorners[i]);
return bnd;
}
bool plPerspDirSlave::SetupViewTransform(plPipeline* pipe)
{
plViewTransform pipeView = pipe->GetViewTransform();
plConst(hsScalar) kYon(100.f);
plConst(hsScalar) kHither(30.f);
pipeView.SetHither(kHither);
pipeView.SetYon(kYon);
hsMatrix44 cam2NDC = pipeView.GetCameraToNDC();
hsMatrix44 world2NDC = cam2NDC * pipeView.GetWorldToCamera();
fLightDir = fLightToWorld.GetAxis(hsMatrix44::kUp);
hsVector3 worldLiDir = fLightDir;
hsPoint3 pWorldLiDir(worldLiDir.fX, worldLiDir.fY, worldLiDir.fZ);
hsPoint3 perspLiPos = IProject(world2NDC, pWorldLiDir, 0);
hsBool reverseZ = fLightDir.InnerProduct(pipe->GetViewDirWorld()) > 0;
SetFlag(kReverseZ, reverseZ);
SetFlag(kReverseCull, reverseZ);
hsPoint3 lookAt;
plConst(hsBool) kUsePerspCenter(true);
plConst(hsBool) kUseFrustCenter(true);
if( kUsePerspCenter )
{
hsPoint3 lookAtCam = pipeView.GetWorldToCamera() * fCasterWorldBounds.GetCenter();
hsPoint3 lookAtNDC = IProject(pipeView.GetCameraToNDC(), lookAtCam);
lookAt = IProject(world2NDC, fCasterWorldBounds.GetCenter());
}
else if( kUseFrustCenter )
{
plConst(hsScalar) kDist(50.f);
hsPoint3 camFrustCenter(0.f, 0.f, kDist);
lookAt = IProject(cam2NDC, camFrustCenter);
}
else
{
hsBounds3Ext ndcBnd(IGetPerspCasterBound(world2NDC));
lookAt = ndcBnd.GetCenter();
}
hsMatrix44 camNDC2Li;
hsMatrix44 li2CamNDC;
IComputeCamNDCToLight(perspLiPos, lookAt, camNDC2Li, li2CamNDC);
hsScalar minZ, maxZ;
hsScalar cotX, cotY;
plConst(hsBool) kFixedPersp(true);
if( !kFixedPersp )
{
hsBounds3Ext bnd(IGetPerspCasterBound(camNDC2Li * world2NDC));
hsBounds3Ext bnd2(IGetPerspCasterBound(world2NDC));
bnd2.Transform(&camNDC2Li);
plConst(hsBool) kUseBnd2(false);
if( kUseBnd2 )
bnd = bnd2;
minZ = bnd.GetMins().fZ;
maxZ = bnd.GetMaxs().fZ; // THIS IS WRONG
// EAP
// This is my hack to get the Nexus age working. The real problem
// is probably data-side. I take full responsibility for this
// hack-around breaking the entire system, loosing data, causing
// unauthorized credit card transactions, etc.
if (_isnan(bnd.GetMins().fX) || _isnan(bnd.GetMins().fY))
return false;
if (_isnan(bnd.GetMaxs().fX) || _isnan(bnd.GetMaxs().fY))
return false;
// THIS IS EVEN MORE WRONG
plConst(hsBool) kFakeDepth(false);
if( kFakeDepth )
{
plConst(hsScalar) kMin(1.f);
plConst(hsScalar) kMax(30.f);
minZ = kMin;
maxZ = kMax;
}
plConst(hsScalar) kMinMinZ(1.f);
if( minZ < kMinMinZ )
minZ = kMinMinZ;
if( -bnd.GetMins().fX > bnd.GetMaxs().fX )
{
hsAssert(bnd.GetMins().fX < 0, "Empty shadow caster bounds?");
cotX = -minZ / bnd.GetMins().fX;
}
else
{
hsAssert(bnd.GetMaxs().fX > 0, "Empty shadow caster bounds?");
cotX = minZ / bnd.GetMaxs().fX;
}
if( -bnd.GetMins().fY > bnd.GetMaxs().fY )
{
hsAssert(bnd.GetMins().fY < 0, "Empty shadow caster bounds?");
cotY = -minZ / bnd.GetMins().fY;
}
else
{
hsAssert(bnd.GetMaxs().fY > 0, "Empty shadow caster bounds?");
cotY = minZ / bnd.GetMaxs().fY;
}
}
else
{
plConst(hsScalar) kHi(1.f);
hsBounds3Ext bnd;
const hsPoint3 lo(-1.f, -1.f, 0.f);
const hsPoint3 hi(1.f, 1.f, kHi);
bnd.MakeEmpty();
bnd.Union(&lo);
bnd.Union(&hi);
bnd.Transform(&camNDC2Li);
minZ = bnd.GetMins().fZ;
maxZ = bnd.GetMaxs().fZ; // THIS IS WRONG
// EAP
// This is my hack to get the Nexus age working. The real problem
// is probably data-side. I take full responsibility for this
// hack-around breaking the entire system, loosing data, causing
// unauthorized credit card transactions, etc.
if (_isnan(bnd.GetMins().fX) || _isnan(bnd.GetMins().fY))
return false;
if (_isnan(bnd.GetMaxs().fX) || _isnan(bnd.GetMaxs().fY))
return false;
plConst(hsScalar) kMinMinZ(1.f);
if( minZ < kMinMinZ )
minZ = kMinMinZ;
if( -bnd.GetMins().fX > bnd.GetMaxs().fX )
{
hsAssert(bnd.GetMins().fX < 0, "Empty shadow caster bounds?");
cotX = -minZ / bnd.GetMins().fX;
}
else
{
hsAssert(bnd.GetMaxs().fX > 0, "Empty shadow caster bounds?");
cotX = minZ / bnd.GetMaxs().fX;
}
if( -bnd.GetMins().fY > bnd.GetMaxs().fY )
{
hsAssert(bnd.GetMins().fY < 0, "Empty shadow caster bounds?");
cotY = -minZ / bnd.GetMins().fY;
}
else
{
hsAssert(bnd.GetMaxs().fY > 0, "Empty shadow caster bounds?");
cotY = minZ / bnd.GetMaxs().fY;
}
}
hsMatrix44 proj;
proj.Reset();
proj.NotIdentity();
// LightToTexture
// First the LightToTexture, which uses the above pretty much as is.
// Note the remapping to range [0.5..width-0.5] etc. Also, the perspective
// divide is by the 3rd output (not the fourth), so we make the 3rd
// output be W (instead of Z).
// This also means that our translate goes into [i][2] instead of [i][3].
proj.fMap[0][0] = cotX * 0.5f;
proj.fMap[0][2] = 0.5f * (1.f + 0.5f/fWidth);
proj.fMap[1][1] = -cotY * 0.5f;
proj.fMap[1][2] = 0.5f * (1.f + 0.5f/fHeight);
#if 1 // This computes correct Z, but we really just want W in 3rd component. HACKFISH
proj.fMap[2][2] = maxZ / (maxZ - minZ);
proj.fMap[2][3] = -minZ * maxZ / (maxZ - minZ);
#elif 1
proj.fMap[2][2] = 1.f;
proj.fMap[2][3] = 0;
#endif
proj.fMap[3][2] = 1.f;
proj.fMap[3][3] = 0;
// fWorldToTexture = proj * camNDC2Li * pipeView.GetWorldToNDC();
fWorldToTexture = proj * camNDC2Li * world2NDC;
fWorldToTexture.fMap[2][0] = fWorldToTexture.fMap[3][0];
fWorldToTexture.fMap[2][1] = fWorldToTexture.fMap[3][1];
fWorldToTexture.fMap[2][2] = fWorldToTexture.fMap[3][2];
fWorldToTexture.fMap[2][3] = fWorldToTexture.fMap[3][3];
// Now the LightToNDC. This one's a little trickier, because we want to compensate for
// having brought in the viewport to keep our border constant, so we can clamp the
// projected texture and not have the edges smear off to infinity.
cotX -= cotX / (fWidth * 0.5f);
cotY -= cotY / (fHeight * 0.5f);
hsScalar tanX = 1.f / cotX;
hsScalar tanY = 1.f / cotY;
fView.SetScreenSize((UInt16)fWidth, (UInt16)fHeight);
fView.SetCameraTransform(pipe->GetViewTransform().GetWorldToCamera(), pipe->GetViewTransform().GetCameraToWorld());
fView.SetPerspective(true);
fView.SetViewPort(0, 0, (float)fWidth, (float)fHeight, false);
fView.SetView(hsPoint3(-tanX, -tanY, minZ), hsPoint3(tanX, tanY, maxZ));
hsMatrix44 cam2Light = camNDC2Li * pipeView.GetCameraToNDC();
fView.PostMultCameraToNDC(cam2Light);
fLightPos = fLightToWorld.GetTranslate();
SetFlag(kPositional, false);
return true;
}
static inline hsVector3 CrossProd(const hsVector3& a, const hsPoint3& b)
{
return hsVector3(a.fY*b.fZ - a.fZ*b.fY, a.fZ*b.fX - a.fX*b.fZ, a.fX*b.fY - a.fY*b.fX);
}
static inline void InverseOfPureRotTran(const hsMatrix44& src, hsMatrix44& inv)
{
inv = src;
// We know this is a pure rotation and translation matrix, so
// we won't have to do a full inverse. Okay kids, don't try this
// at home.
inv.fMap[0][1] = src.fMap[1][0];
inv.fMap[0][2] = src.fMap[2][0];
inv.fMap[1][0] = src.fMap[0][1];
inv.fMap[1][2] = src.fMap[2][1];
inv.fMap[2][0] = src.fMap[0][2];
inv.fMap[2][1] = src.fMap[1][2];
hsPoint3 newTran(-src.fMap[0][3], -src.fMap[1][3], -src.fMap[2][3]);
inv.fMap[0][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[0][0]);
inv.fMap[1][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[1][0]);
inv.fMap[2][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[2][0]);
}
void plPerspDirSlave::IComputeCamNDCToLight(const hsPoint3& from, const hsPoint3& at, hsMatrix44& camNDC2Li, hsMatrix44& li2CamNDC)
{
hsVector3 atToFrom(&from, &at);
hsScalar distSq = atToFrom.MagnitudeSquared();
atToFrom *= hsFastMath::InvSqrtAppr(distSq);
const hsScalar kMinMag = 0.5f;
hsVector3 up(0,0,1.f);
if( CrossProd(up, (at - from)).MagnitudeSquared() < kMinMag )
{
up.Set(0, 1.f, 0);
}
hsMatrix44 w2light;
w2light.MakeCamera(&from, &at, &up);
hsMatrix44 light2w;
InverseOfPureRotTran(w2light, light2w);
#ifdef CHECK_INVERSE
hsMatrix44 inv;
w2light.GetInverse(&inv);
#endif // CHECK_INVERSE
camNDC2Li = w2light;
li2CamNDC = light2w;
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plPipeline.h"
#include "plTweak.h"
#include "hsFastMath.h"
#include "plPerspDirSlave.h"
#include <float.h>
void plPerspDirSlave::Init()
{
plShadowSlave::Init();
fFlags |= kCastInCameraSpace;
}
hsPoint3 plPerspDirSlave::IProject(const hsMatrix44& world2NDC, const hsPoint3& pos, hsScalar w) const
{
hsPoint3 retVal;
retVal.fX = world2NDC.fMap[0][0] * pos.fX
+ world2NDC.fMap[0][1] * pos.fY
+ world2NDC.fMap[0][2] * pos.fZ
+ world2NDC.fMap[0][3] * w;
retVal.fY = world2NDC.fMap[1][0] * pos.fX
+ world2NDC.fMap[1][1] * pos.fY
+ world2NDC.fMap[1][2] * pos.fZ
+ world2NDC.fMap[1][3] * w;
retVal.fZ = world2NDC.fMap[2][0] * pos.fX
+ world2NDC.fMap[2][1] * pos.fY
+ world2NDC.fMap[2][2] * pos.fZ
+ world2NDC.fMap[2][3] * w;
hsScalar invW = 1.f / (
world2NDC.fMap[3][0] * pos.fX
+ world2NDC.fMap[3][1] * pos.fY
+ world2NDC.fMap[3][2] * pos.fZ
+ world2NDC.fMap[3][3] * w);
retVal *= invW;
return retVal;
}
hsBounds3Ext plPerspDirSlave::IGetPerspCasterBound(const hsMatrix44& world2NDC) const
{
hsPoint3 corners[8];
fCasterWorldBounds.GetCorners(corners);
hsPoint3 perspCorners[8];
int i;
for( i = 0; i < 8; i++ )
{
perspCorners[i] = IProject(world2NDC, corners[i]);
if( perspCorners[i].fX < -1.f )
perspCorners[i].fX = -1.f;
else if( perspCorners[i].fX > 1.f )
perspCorners[i].fX = 1.f;
if( perspCorners[i].fY < -1.f )
perspCorners[i].fY = -1.f;
else if( perspCorners[i].fY > 1.f )
perspCorners[i].fY = 1.f;
if( perspCorners[i].fZ < 0 )
perspCorners[i].Set(0.f, 0.f, 0.f);
}
hsBounds3Ext bnd;
bnd.MakeEmpty();
for( i = 0; i < 8; i++ )
bnd.Union(&perspCorners[i]);
return bnd;
}
bool plPerspDirSlave::SetupViewTransform(plPipeline* pipe)
{
plViewTransform pipeView = pipe->GetViewTransform();
plConst(hsScalar) kYon(100.f);
plConst(hsScalar) kHither(30.f);
pipeView.SetHither(kHither);
pipeView.SetYon(kYon);
hsMatrix44 cam2NDC = pipeView.GetCameraToNDC();
hsMatrix44 world2NDC = cam2NDC * pipeView.GetWorldToCamera();
fLightDir = fLightToWorld.GetAxis(hsMatrix44::kUp);
hsVector3 worldLiDir = fLightDir;
hsPoint3 pWorldLiDir(worldLiDir.fX, worldLiDir.fY, worldLiDir.fZ);
hsPoint3 perspLiPos = IProject(world2NDC, pWorldLiDir, 0);
hsBool reverseZ = fLightDir.InnerProduct(pipe->GetViewDirWorld()) > 0;
SetFlag(kReverseZ, reverseZ);
SetFlag(kReverseCull, reverseZ);
hsPoint3 lookAt;
plConst(hsBool) kUsePerspCenter(true);
plConst(hsBool) kUseFrustCenter(true);
if( kUsePerspCenter )
{
hsPoint3 lookAtCam = pipeView.GetWorldToCamera() * fCasterWorldBounds.GetCenter();
hsPoint3 lookAtNDC = IProject(pipeView.GetCameraToNDC(), lookAtCam);
lookAt = IProject(world2NDC, fCasterWorldBounds.GetCenter());
}
else if( kUseFrustCenter )
{
plConst(hsScalar) kDist(50.f);
hsPoint3 camFrustCenter(0.f, 0.f, kDist);
lookAt = IProject(cam2NDC, camFrustCenter);
}
else
{
hsBounds3Ext ndcBnd(IGetPerspCasterBound(world2NDC));
lookAt = ndcBnd.GetCenter();
}
hsMatrix44 camNDC2Li;
hsMatrix44 li2CamNDC;
IComputeCamNDCToLight(perspLiPos, lookAt, camNDC2Li, li2CamNDC);
hsScalar minZ, maxZ;
hsScalar cotX, cotY;
plConst(hsBool) kFixedPersp(true);
if( !kFixedPersp )
{
hsBounds3Ext bnd(IGetPerspCasterBound(camNDC2Li * world2NDC));
hsBounds3Ext bnd2(IGetPerspCasterBound(world2NDC));
bnd2.Transform(&camNDC2Li);
plConst(hsBool) kUseBnd2(false);
if( kUseBnd2 )
bnd = bnd2;
minZ = bnd.GetMins().fZ;
maxZ = bnd.GetMaxs().fZ; // THIS IS WRONG
// EAP
// This is my hack to get the Nexus age working. The real problem
// is probably data-side. I take full responsibility for this
// hack-around breaking the entire system, loosing data, causing
// unauthorized credit card transactions, etc.
if (_isnan(bnd.GetMins().fX) || _isnan(bnd.GetMins().fY))
return false;
if (_isnan(bnd.GetMaxs().fX) || _isnan(bnd.GetMaxs().fY))
return false;
// THIS IS EVEN MORE WRONG
plConst(hsBool) kFakeDepth(false);
if( kFakeDepth )
{
plConst(hsScalar) kMin(1.f);
plConst(hsScalar) kMax(30.f);
minZ = kMin;
maxZ = kMax;
}
plConst(hsScalar) kMinMinZ(1.f);
if( minZ < kMinMinZ )
minZ = kMinMinZ;
if( -bnd.GetMins().fX > bnd.GetMaxs().fX )
{
hsAssert(bnd.GetMins().fX < 0, "Empty shadow caster bounds?");
cotX = -minZ / bnd.GetMins().fX;
}
else
{
hsAssert(bnd.GetMaxs().fX > 0, "Empty shadow caster bounds?");
cotX = minZ / bnd.GetMaxs().fX;
}
if( -bnd.GetMins().fY > bnd.GetMaxs().fY )
{
hsAssert(bnd.GetMins().fY < 0, "Empty shadow caster bounds?");
cotY = -minZ / bnd.GetMins().fY;
}
else
{
hsAssert(bnd.GetMaxs().fY > 0, "Empty shadow caster bounds?");
cotY = minZ / bnd.GetMaxs().fY;
}
}
else
{
plConst(hsScalar) kHi(1.f);
hsBounds3Ext bnd;
const hsPoint3 lo(-1.f, -1.f, 0.f);
const hsPoint3 hi(1.f, 1.f, kHi);
bnd.MakeEmpty();
bnd.Union(&lo);
bnd.Union(&hi);
bnd.Transform(&camNDC2Li);
minZ = bnd.GetMins().fZ;
maxZ = bnd.GetMaxs().fZ; // THIS IS WRONG
// EAP
// This is my hack to get the Nexus age working. The real problem
// is probably data-side. I take full responsibility for this
// hack-around breaking the entire system, loosing data, causing
// unauthorized credit card transactions, etc.
if (_isnan(bnd.GetMins().fX) || _isnan(bnd.GetMins().fY))
return false;
if (_isnan(bnd.GetMaxs().fX) || _isnan(bnd.GetMaxs().fY))
return false;
plConst(hsScalar) kMinMinZ(1.f);
if( minZ < kMinMinZ )
minZ = kMinMinZ;
if( -bnd.GetMins().fX > bnd.GetMaxs().fX )
{
hsAssert(bnd.GetMins().fX < 0, "Empty shadow caster bounds?");
cotX = -minZ / bnd.GetMins().fX;
}
else
{
hsAssert(bnd.GetMaxs().fX > 0, "Empty shadow caster bounds?");
cotX = minZ / bnd.GetMaxs().fX;
}
if( -bnd.GetMins().fY > bnd.GetMaxs().fY )
{
hsAssert(bnd.GetMins().fY < 0, "Empty shadow caster bounds?");
cotY = -minZ / bnd.GetMins().fY;
}
else
{
hsAssert(bnd.GetMaxs().fY > 0, "Empty shadow caster bounds?");
cotY = minZ / bnd.GetMaxs().fY;
}
}
hsMatrix44 proj;
proj.Reset();
proj.NotIdentity();
// LightToTexture
// First the LightToTexture, which uses the above pretty much as is.
// Note the remapping to range [0.5..width-0.5] etc. Also, the perspective
// divide is by the 3rd output (not the fourth), so we make the 3rd
// output be W (instead of Z).
// This also means that our translate goes into [i][2] instead of [i][3].
proj.fMap[0][0] = cotX * 0.5f;
proj.fMap[0][2] = 0.5f * (1.f + 0.5f/fWidth);
proj.fMap[1][1] = -cotY * 0.5f;
proj.fMap[1][2] = 0.5f * (1.f + 0.5f/fHeight);
#if 1 // This computes correct Z, but we really just want W in 3rd component. HACKFISH
proj.fMap[2][2] = maxZ / (maxZ - minZ);
proj.fMap[2][3] = -minZ * maxZ / (maxZ - minZ);
#elif 1
proj.fMap[2][2] = 1.f;
proj.fMap[2][3] = 0;
#endif
proj.fMap[3][2] = 1.f;
proj.fMap[3][3] = 0;
// fWorldToTexture = proj * camNDC2Li * pipeView.GetWorldToNDC();
fWorldToTexture = proj * camNDC2Li * world2NDC;
fWorldToTexture.fMap[2][0] = fWorldToTexture.fMap[3][0];
fWorldToTexture.fMap[2][1] = fWorldToTexture.fMap[3][1];
fWorldToTexture.fMap[2][2] = fWorldToTexture.fMap[3][2];
fWorldToTexture.fMap[2][3] = fWorldToTexture.fMap[3][3];
// Now the LightToNDC. This one's a little trickier, because we want to compensate for
// having brought in the viewport to keep our border constant, so we can clamp the
// projected texture and not have the edges smear off to infinity.
cotX -= cotX / (fWidth * 0.5f);
cotY -= cotY / (fHeight * 0.5f);
hsScalar tanX = 1.f / cotX;
hsScalar tanY = 1.f / cotY;
fView.SetScreenSize((UInt16)fWidth, (UInt16)fHeight);
fView.SetCameraTransform(pipe->GetViewTransform().GetWorldToCamera(), pipe->GetViewTransform().GetCameraToWorld());
fView.SetPerspective(true);
fView.SetViewPort(0, 0, (float)fWidth, (float)fHeight, false);
fView.SetView(hsPoint3(-tanX, -tanY, minZ), hsPoint3(tanX, tanY, maxZ));
hsMatrix44 cam2Light = camNDC2Li * pipeView.GetCameraToNDC();
fView.PostMultCameraToNDC(cam2Light);
fLightPos = fLightToWorld.GetTranslate();
SetFlag(kPositional, false);
return true;
}
static inline hsVector3 CrossProd(const hsVector3& a, const hsPoint3& b)
{
return hsVector3(a.fY*b.fZ - a.fZ*b.fY, a.fZ*b.fX - a.fX*b.fZ, a.fX*b.fY - a.fY*b.fX);
}
static inline void InverseOfPureRotTran(const hsMatrix44& src, hsMatrix44& inv)
{
inv = src;
// We know this is a pure rotation and translation matrix, so
// we won't have to do a full inverse. Okay kids, don't try this
// at home.
inv.fMap[0][1] = src.fMap[1][0];
inv.fMap[0][2] = src.fMap[2][0];
inv.fMap[1][0] = src.fMap[0][1];
inv.fMap[1][2] = src.fMap[2][1];
inv.fMap[2][0] = src.fMap[0][2];
inv.fMap[2][1] = src.fMap[1][2];
hsPoint3 newTran(-src.fMap[0][3], -src.fMap[1][3], -src.fMap[2][3]);
inv.fMap[0][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[0][0]);
inv.fMap[1][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[1][0]);
inv.fMap[2][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[2][0]);
}
void plPerspDirSlave::IComputeCamNDCToLight(const hsPoint3& from, const hsPoint3& at, hsMatrix44& camNDC2Li, hsMatrix44& li2CamNDC)
{
hsVector3 atToFrom(&from, &at);
hsScalar distSq = atToFrom.MagnitudeSquared();
atToFrom *= hsFastMath::InvSqrtAppr(distSq);
const hsScalar kMinMag = 0.5f;
hsVector3 up(0,0,1.f);
if( CrossProd(up, (at - from)).MagnitudeSquared() < kMinMag )
{
up.Set(0, 1.f, 0);
}
hsMatrix44 w2light;
w2light.MakeCamera(&from, &at, &up);
hsMatrix44 light2w;
InverseOfPureRotTran(w2light, light2w);
#ifdef CHECK_INVERSE
hsMatrix44 inv;
w2light.GetInverse(&inv);
#endif // CHECK_INVERSE
camNDC2Li = w2light;
li2CamNDC = light2w;
}

View File

@ -1,47 +1,47 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plPerspDirSlave_inc
#define plPerspDirSlave_inc
#include "plShadowSlave.h"
class plPerspDirSlave : public plShadowSlave
{
protected:
hsBounds3Ext IGetPerspCasterBound(const hsMatrix44& world2NDC) const;
hsPoint3 IProject(const hsMatrix44& world2NDC, const hsPoint3& pos, hsScalar w=1.f) const;
void IComputeCamNDCToLight(const hsPoint3& from, const hsPoint3& at, hsMatrix44& camNDC2Li, hsMatrix44& li2CamNDC);
public:
virtual void Init();
virtual bool SetupViewTransform(plPipeline* pipe);
};
#endif // plPerspDirSlave_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plPerspDirSlave_inc
#define plPerspDirSlave_inc
#include "plShadowSlave.h"
class plPerspDirSlave : public plShadowSlave
{
protected:
hsBounds3Ext IGetPerspCasterBound(const hsMatrix44& world2NDC) const;
hsPoint3 IProject(const hsMatrix44& world2NDC, const hsPoint3& pos, hsScalar w=1.f) const;
void IComputeCamNDCToLight(const hsPoint3& from, const hsPoint3& at, hsMatrix44& camNDC2Li, hsMatrix44& li2CamNDC);
public:
virtual void Init();
virtual bool SetupViewTransform(plPipeline* pipe);
};
#endif // plPerspDirSlave_inc

View File

@ -1,203 +1,203 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plPointShadowMaster.h"
#include "plShadowSlave.h"
#include "plShadowCaster.h"
#include "plMessage/plShadowCastMsg.h"
#include "plLightInfo.h"
#include "hsMatrix44.h"
#include "hsBounds.h"
#include "hsFastMath.h"
static const hsScalar kMinMinZ = 1.f; // totally random arbitrary number (has to be > 0).
static inline void QuickNorm( hsVector3& a, hsScalar& b )
{
hsScalar len = hsFastMath::InvSqrtAppr((a).MagnitudeSquared());
a *= len;
b *= len;
}
static inline hsVector3 CrossProd(const hsVector3& a, const hsPoint3& b)
{
return hsVector3(a.fY*b.fZ - a.fZ*b.fY, a.fZ*b.fX - a.fX*b.fZ, a.fX*b.fY - a.fY*b.fX);
}
static inline void InverseOfPureRotTran(const hsMatrix44& src, hsMatrix44& inv)
{
inv = src;
// We know this is a pure rotation and translation matrix, so
// we won't have to do a full inverse. Okay kids, don't try this
// at home.
inv.fMap[0][1] = src.fMap[1][0];
inv.fMap[0][2] = src.fMap[2][0];
inv.fMap[1][0] = src.fMap[0][1];
inv.fMap[1][2] = src.fMap[2][1];
inv.fMap[2][0] = src.fMap[0][2];
inv.fMap[2][1] = src.fMap[1][2];
hsPoint3 newTran(-src.fMap[0][3], -src.fMap[1][3], -src.fMap[2][3]);
inv.fMap[0][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[0][0]);
inv.fMap[1][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[1][0]);
inv.fMap[2][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[2][0]);
}
////////////////////////////////////////////////////////////////////////////////////
// Point first
////////////////////////////////////////////////////////////////////////////////////
plPointShadowMaster::plPointShadowMaster()
{
fLastUp.Set(0,0,0);
}
plPointShadowMaster::~plPointShadowMaster()
{
fIsectPool.SetCount(fIsectPool.GetNumAlloc());
int i;
for( i = 0; i < fIsectPool.GetCount(); i++ )
delete fIsectPool[i];
}
plShadowSlave* plPointShadowMaster::INewSlave(const plShadowCaster* caster)
{
return TRACKED_NEW plPointShadowSlave;
}
void plPointShadowMaster::IBeginRender()
{
plShadowMaster::IBeginRender();
fIsectPool.SetCount(0);
}
void plPointShadowMaster::IComputeWorldToLight(const hsBounds3Ext& bnd, plShadowSlave* slave) const
{
const hsScalar kMinMag = 0.5f;
hsPoint3 from = fLightInfo->GetLightToWorld().GetTranslate();
hsPoint3 at = bnd.GetCenter();
hsVector3 atToFrom(&from, &at);
hsScalar distSq = atToFrom.MagnitudeSquared();
atToFrom *= hsFastMath::InvSqrtAppr(distSq);
hsPoint2 depth;
bnd.TestPlane(atToFrom, depth);
hsScalar fromDepth = atToFrom.InnerProduct(from);
hsScalar dist = fromDepth - depth.fY;
static hsScalar kMinDist = 3.f;
if( dist < kMinDist )
{
atToFrom *= kMinDist - dist;
from += atToFrom;
}
hsVector3 up(0,0,1.f);
if( CrossProd(up, (at - from)).MagnitudeSquared() < kMinMag )
{
up.Set(0, 1.f, 0);
}
hsMatrix44 w2light;
w2light.MakeCamera(&from, &at, &up); // mf_flip_up - mf
hsMatrix44 light2w;
InverseOfPureRotTran(w2light, light2w);
#ifdef CHECK_INVERSE
hsMatrix44 inv;
w2light.GetInverse(&inv);
#endif // CHECK_INVERSE
slave->fWorldToLight = w2light;
slave->fLightToWorld = light2w;
}
void plPointShadowMaster::IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const
{
slave->fView.SetPerspective(true);
}
void plPointShadowMaster::IComputeISect(const hsBounds3Ext& bnd, plShadowSlave* slave) const
{
int iIsect = fIsectPool.GetCount();
fIsectPool.ExpandAndZero(iIsect+1);
if( !fIsectPool[iIsect] )
{
fIsectPool[iIsect] = TRACKED_NEW plBoundsIsect;
}
plBoundsIsect* isect = fIsectPool[iIsect];
const hsBounds3Ext& wBnd = slave->fWorldBounds;
isect->SetBounds(wBnd);
slave->fIsect = isect;
}
void plPointShadowMaster::IComputeBounds(const hsBounds3Ext& wBnd, plShadowSlave* slave) const
{
// Plan here is to look at the bounds in the slave's local space.
// Our slave's bounds will clearly contain the shadow caster's bounds. It will also
// contain the bnd's corners projected out along the ray from the slave's position
// through each corner. They will extend fAttenDist farther than the center point
// of the bound.
hsBounds3Ext sBnd = wBnd;
sBnd.Transform(&slave->fWorldToLight);
hsBounds3Ext bnd = sBnd;
hsScalar dist = sBnd.GetCenter().fZ;
dist += slave->fAttenDist;
hsScalar minZ = sBnd.GetMaxs().fZ;
hsPoint3 p(sBnd.GetMins().fX * dist / minZ, sBnd.GetMins().fY * dist / minZ, dist);
bnd.Union(&p);
p.Set(sBnd.GetMaxs().fX * dist / minZ, sBnd.GetMaxs().fY * dist / minZ, dist);
bnd.Union(&p);
bnd.Transform(&slave->fLightToWorld);
slave->fWorldBounds = bnd;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plPointShadowMaster.h"
#include "plShadowSlave.h"
#include "plShadowCaster.h"
#include "plMessage/plShadowCastMsg.h"
#include "plLightInfo.h"
#include "hsMatrix44.h"
#include "hsBounds.h"
#include "hsFastMath.h"
static const hsScalar kMinMinZ = 1.f; // totally random arbitrary number (has to be > 0).
static inline void QuickNorm( hsVector3& a, hsScalar& b )
{
hsScalar len = hsFastMath::InvSqrtAppr((a).MagnitudeSquared());
a *= len;
b *= len;
}
static inline hsVector3 CrossProd(const hsVector3& a, const hsPoint3& b)
{
return hsVector3(a.fY*b.fZ - a.fZ*b.fY, a.fZ*b.fX - a.fX*b.fZ, a.fX*b.fY - a.fY*b.fX);
}
static inline void InverseOfPureRotTran(const hsMatrix44& src, hsMatrix44& inv)
{
inv = src;
// We know this is a pure rotation and translation matrix, so
// we won't have to do a full inverse. Okay kids, don't try this
// at home.
inv.fMap[0][1] = src.fMap[1][0];
inv.fMap[0][2] = src.fMap[2][0];
inv.fMap[1][0] = src.fMap[0][1];
inv.fMap[1][2] = src.fMap[2][1];
inv.fMap[2][0] = src.fMap[0][2];
inv.fMap[2][1] = src.fMap[1][2];
hsPoint3 newTran(-src.fMap[0][3], -src.fMap[1][3], -src.fMap[2][3]);
inv.fMap[0][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[0][0]);
inv.fMap[1][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[1][0]);
inv.fMap[2][3] = newTran.InnerProduct((hsVector3*)&inv.fMap[2][0]);
}
////////////////////////////////////////////////////////////////////////////////////
// Point first
////////////////////////////////////////////////////////////////////////////////////
plPointShadowMaster::plPointShadowMaster()
{
fLastUp.Set(0,0,0);
}
plPointShadowMaster::~plPointShadowMaster()
{
fIsectPool.SetCount(fIsectPool.GetNumAlloc());
int i;
for( i = 0; i < fIsectPool.GetCount(); i++ )
delete fIsectPool[i];
}
plShadowSlave* plPointShadowMaster::INewSlave(const plShadowCaster* caster)
{
return TRACKED_NEW plPointShadowSlave;
}
void plPointShadowMaster::IBeginRender()
{
plShadowMaster::IBeginRender();
fIsectPool.SetCount(0);
}
void plPointShadowMaster::IComputeWorldToLight(const hsBounds3Ext& bnd, plShadowSlave* slave) const
{
const hsScalar kMinMag = 0.5f;
hsPoint3 from = fLightInfo->GetLightToWorld().GetTranslate();
hsPoint3 at = bnd.GetCenter();
hsVector3 atToFrom(&from, &at);
hsScalar distSq = atToFrom.MagnitudeSquared();
atToFrom *= hsFastMath::InvSqrtAppr(distSq);
hsPoint2 depth;
bnd.TestPlane(atToFrom, depth);
hsScalar fromDepth = atToFrom.InnerProduct(from);
hsScalar dist = fromDepth - depth.fY;
static hsScalar kMinDist = 3.f;
if( dist < kMinDist )
{
atToFrom *= kMinDist - dist;
from += atToFrom;
}
hsVector3 up(0,0,1.f);
if( CrossProd(up, (at - from)).MagnitudeSquared() < kMinMag )
{
up.Set(0, 1.f, 0);
}
hsMatrix44 w2light;
w2light.MakeCamera(&from, &at, &up); // mf_flip_up - mf
hsMatrix44 light2w;
InverseOfPureRotTran(w2light, light2w);
#ifdef CHECK_INVERSE
hsMatrix44 inv;
w2light.GetInverse(&inv);
#endif // CHECK_INVERSE
slave->fWorldToLight = w2light;
slave->fLightToWorld = light2w;
}
void plPointShadowMaster::IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const
{
slave->fView.SetPerspective(true);
}
void plPointShadowMaster::IComputeISect(const hsBounds3Ext& bnd, plShadowSlave* slave) const
{
int iIsect = fIsectPool.GetCount();
fIsectPool.ExpandAndZero(iIsect+1);
if( !fIsectPool[iIsect] )
{
fIsectPool[iIsect] = TRACKED_NEW plBoundsIsect;
}
plBoundsIsect* isect = fIsectPool[iIsect];
const hsBounds3Ext& wBnd = slave->fWorldBounds;
isect->SetBounds(wBnd);
slave->fIsect = isect;
}
void plPointShadowMaster::IComputeBounds(const hsBounds3Ext& wBnd, plShadowSlave* slave) const
{
// Plan here is to look at the bounds in the slave's local space.
// Our slave's bounds will clearly contain the shadow caster's bounds. It will also
// contain the bnd's corners projected out along the ray from the slave's position
// through each corner. They will extend fAttenDist farther than the center point
// of the bound.
hsBounds3Ext sBnd = wBnd;
sBnd.Transform(&slave->fWorldToLight);
hsBounds3Ext bnd = sBnd;
hsScalar dist = sBnd.GetCenter().fZ;
dist += slave->fAttenDist;
hsScalar minZ = sBnd.GetMaxs().fZ;
hsPoint3 p(sBnd.GetMins().fX * dist / minZ, sBnd.GetMins().fY * dist / minZ, dist);
bnd.Union(&p);
p.Set(sBnd.GetMaxs().fX * dist / minZ, sBnd.GetMaxs().fY * dist / minZ, dist);
bnd.Union(&p);
bnd.Transform(&slave->fLightToWorld);
slave->fWorldBounds = bnd;
}

View File

@ -1,60 +1,60 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plPointShadowMaster_inc
#define plPointShadowMaster_inc
#include "plShadowMaster.h"
#include "hsGeometry3.h"
class plBoundsIsect;
class plPointShadowMaster : public plShadowMaster
{
protected:
mutable hsVector3 fLastUp;
mutable hsTArray<plBoundsIsect*> fIsectPool;
virtual void IComputeWorldToLight(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual void IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const;
virtual void IComputeISect(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual void IComputeBounds(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual plShadowSlave* INewSlave(const plShadowCaster* caster);
virtual void IBeginRender();
public:
plPointShadowMaster();
virtual ~plPointShadowMaster();
CLASSNAME_REGISTER( plPointShadowMaster );
GETINTERFACE_ANY( plPointShadowMaster, plShadowMaster );
};
#endif // plPointShadowMaster_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plPointShadowMaster_inc
#define plPointShadowMaster_inc
#include "plShadowMaster.h"
#include "hsGeometry3.h"
class plBoundsIsect;
class plPointShadowMaster : public plShadowMaster
{
protected:
mutable hsVector3 fLastUp;
mutable hsTArray<plBoundsIsect*> fIsectPool;
virtual void IComputeWorldToLight(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual void IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const;
virtual void IComputeISect(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual void IComputeBounds(const hsBounds3Ext& bnd, plShadowSlave* slave) const;
virtual plShadowSlave* INewSlave(const plShadowCaster* caster);
virtual void IBeginRender();
public:
plPointShadowMaster();
virtual ~plPointShadowMaster();
CLASSNAME_REGISTER( plPointShadowMaster );
GETINTERFACE_ANY( plPointShadowMaster, plShadowMaster );
};
#endif // plPointShadowMaster_inc

View File

@ -1,208 +1,208 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plShadowCaster.h"
#include "plMessage/plShadowCastMsg.h"
#include "pnSceneObject/plSceneObject.h"
#include "pnSceneObject/plDrawInterface.h"
#include "plDrawable/plDrawableSpans.h"
#include "plDrawable/plSpanTypes.h"
#include "plSurface/hsGMaterial.h"
#include "plSurface/plLayerInterface.h"
#include "plMessage/plRenderMsg.h"
#include "plgDispatch.h"
#include "plShadowMaster.h"
hsBool plShadowCaster::fShadowCastDisabled = false;
hsBool plShadowCaster::fCanShadowCast = true;
plShadowCaster::plShadowCaster()
: fMaxOpacity(0),
fCastFlags(0),
fAttenScale(1.f),
fBlurScale(0.f),
fBoost(1.f)
{
}
plShadowCaster::~plShadowCaster()
{
Deactivate();
}
void plShadowCaster::Read(hsStream* stream, hsResMgr* mgr)
{
plMultiModifier::Read(stream, mgr);
fCastFlags = stream->ReadByte();
// HACKTESTPERSP
// if( !(fCastFlags & kPerspective) )
// fCastFlags |= kPerspective;
// else
fCastFlags &= ~kPerspective;
fBoost = stream->ReadSwapScalar();
fAttenScale = stream->ReadSwapScalar();
fBlurScale = stream->ReadSwapScalar();
Activate();
}
void plShadowCaster::Write(hsStream* stream, hsResMgr* mgr)
{
plMultiModifier::Write(stream, mgr);
stream->WriteByte(fCastFlags);
stream->WriteSwapScalar(fBoost);
stream->WriteSwapScalar(fAttenScale);
stream->WriteSwapScalar(fBlurScale);
}
void plShadowCaster::Activate() const
{
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
}
void plShadowCaster::Deactivate() const
{
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
}
void plShadowCaster::ICollectAllSpans()
{
fSpans.SetCount(0);
int i;
for( i = 0; i < GetNumTargets(); i++ )
{
plSceneObject* so = GetTarget(i);
// Nil target? Shouldn't happen.
if( so )
{
const plDrawInterface* di = so->GetDrawInterface();
// Nil di- either it hasn't loaded yet, or we've been applied to something that isn't visible (oops).
if( di && !di->GetProperty(plDrawInterface::kDisable) )
{
int j;
for( j = 0; j < di->GetNumDrawables(); j++ )
{
plDrawableSpans* dr = plDrawableSpans::ConvertNoRef(di->GetDrawable(j));
// Nil dr - it hasn't loaded yet.
if( dr )
{
plDISpanIndex& diIndex = dr->GetDISpans(di->GetDrawableMeshIndex(j));
if( !diIndex.IsMatrixOnly() )
{
int k;
for( k = 0; k < diIndex.GetCount(); k++ )
{
const plSpan* span = dr->GetSpan(diIndex[k]);
// if( !(span->fProps & plSpan::kPropNoShadowCast) )
{
fSpans.Append(DrawSpan().Set(dr, span, diIndex[k]));
}
}
}
}
}
}
}
}
}
hsBool plShadowCaster::IOnRenderMsg(plRenderMsg* msg)
{
if( ShadowCastDisabled() )
return true;
const UInt8 shadowQuality = UInt8(plShadowMaster::GetGlobalShadowQuality() * 3.9f);
if( !GetKey()->GetUoid().GetLoadMask().MatchesQuality(shadowQuality) )
return true;
// Don't really like having to gather these guys up every frame,
// but with the avatar customization, it's all pretty volatile,
// subject to infrequent change, but change without warning.
// The number of actual targets (and hence shadow casting spans)
// for any ShadowCasterModifier should always be on the order of
// 10, so chances are we can get away with this. If not, we can
// figure some way of caching, like a broadcast message warning us
// that an avatar customization event has occurred.
ICollectAllSpans();
// Max opacity used to fade out shadows during link
//find max opacity of all spans
//clear shadowBits of all spans
fMaxOpacity = 0.f;
int i;
for( i = 0; i < fSpans.GetCount(); i++ )
{
hsGMaterial* mat = fSpans[i].fDraw->GetSubMaterial(fSpans[i].fSpan->fMaterialIdx);
if( mat )
{
plLayerInterface* baseLay = mat->GetLayer(0);
if( baseLay && (baseLay->GetOpacity() > fMaxOpacity) )
fMaxOpacity = baseLay->GetOpacity();
}
fSpans[i].fSpan->ClearShadowBits();
}
if( fMaxOpacity > 0 )
{
plShadowCastMsg* cast = TRACKED_NEW plShadowCastMsg(GetKey(), this, msg->Pipeline());
cast->Send();
}
return true;
}
#include "plProfile.h"
plProfile_CreateTimer("ShadowCaster", "RenderSetup", ShadowCaster);
hsBool plShadowCaster::MsgReceive(plMessage* msg)
{
plRenderMsg* rendMsg = plRenderMsg::ConvertNoRef(msg);
if( rendMsg )
{
plProfile_BeginLap(ShadowCaster, this->GetKey()->GetUoid().GetObjectName());
IOnRenderMsg(rendMsg);
plProfile_EndLap(ShadowCaster, this->GetKey()->GetUoid().GetObjectName());
return true;
}
return plMultiModifier::MsgReceive(msg);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plShadowCaster.h"
#include "plMessage/plShadowCastMsg.h"
#include "pnSceneObject/plSceneObject.h"
#include "pnSceneObject/plDrawInterface.h"
#include "plDrawable/plDrawableSpans.h"
#include "plDrawable/plSpanTypes.h"
#include "plSurface/hsGMaterial.h"
#include "plSurface/plLayerInterface.h"
#include "plMessage/plRenderMsg.h"
#include "plgDispatch.h"
#include "plShadowMaster.h"
hsBool plShadowCaster::fShadowCastDisabled = false;
hsBool plShadowCaster::fCanShadowCast = true;
plShadowCaster::plShadowCaster()
: fMaxOpacity(0),
fCastFlags(0),
fAttenScale(1.f),
fBlurScale(0.f),
fBoost(1.f)
{
}
plShadowCaster::~plShadowCaster()
{
Deactivate();
}
void plShadowCaster::Read(hsStream* stream, hsResMgr* mgr)
{
plMultiModifier::Read(stream, mgr);
fCastFlags = stream->ReadByte();
// HACKTESTPERSP
// if( !(fCastFlags & kPerspective) )
// fCastFlags |= kPerspective;
// else
fCastFlags &= ~kPerspective;
fBoost = stream->ReadSwapScalar();
fAttenScale = stream->ReadSwapScalar();
fBlurScale = stream->ReadSwapScalar();
Activate();
}
void plShadowCaster::Write(hsStream* stream, hsResMgr* mgr)
{
plMultiModifier::Write(stream, mgr);
stream->WriteByte(fCastFlags);
stream->WriteSwapScalar(fBoost);
stream->WriteSwapScalar(fAttenScale);
stream->WriteSwapScalar(fBlurScale);
}
void plShadowCaster::Activate() const
{
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
}
void plShadowCaster::Deactivate() const
{
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
}
void plShadowCaster::ICollectAllSpans()
{
fSpans.SetCount(0);
int i;
for( i = 0; i < GetNumTargets(); i++ )
{
plSceneObject* so = GetTarget(i);
// Nil target? Shouldn't happen.
if( so )
{
const plDrawInterface* di = so->GetDrawInterface();
// Nil di- either it hasn't loaded yet, or we've been applied to something that isn't visible (oops).
if( di && !di->GetProperty(plDrawInterface::kDisable) )
{
int j;
for( j = 0; j < di->GetNumDrawables(); j++ )
{
plDrawableSpans* dr = plDrawableSpans::ConvertNoRef(di->GetDrawable(j));
// Nil dr - it hasn't loaded yet.
if( dr )
{
plDISpanIndex& diIndex = dr->GetDISpans(di->GetDrawableMeshIndex(j));
if( !diIndex.IsMatrixOnly() )
{
int k;
for( k = 0; k < diIndex.GetCount(); k++ )
{
const plSpan* span = dr->GetSpan(diIndex[k]);
// if( !(span->fProps & plSpan::kPropNoShadowCast) )
{
fSpans.Append(DrawSpan().Set(dr, span, diIndex[k]));
}
}
}
}
}
}
}
}
}
hsBool plShadowCaster::IOnRenderMsg(plRenderMsg* msg)
{
if( ShadowCastDisabled() )
return true;
const UInt8 shadowQuality = UInt8(plShadowMaster::GetGlobalShadowQuality() * 3.9f);
if( !GetKey()->GetUoid().GetLoadMask().MatchesQuality(shadowQuality) )
return true;
// Don't really like having to gather these guys up every frame,
// but with the avatar customization, it's all pretty volatile,
// subject to infrequent change, but change without warning.
// The number of actual targets (and hence shadow casting spans)
// for any ShadowCasterModifier should always be on the order of
// 10, so chances are we can get away with this. If not, we can
// figure some way of caching, like a broadcast message warning us
// that an avatar customization event has occurred.
ICollectAllSpans();
// Max opacity used to fade out shadows during link
//find max opacity of all spans
//clear shadowBits of all spans
fMaxOpacity = 0.f;
int i;
for( i = 0; i < fSpans.GetCount(); i++ )
{
hsGMaterial* mat = fSpans[i].fDraw->GetSubMaterial(fSpans[i].fSpan->fMaterialIdx);
if( mat )
{
plLayerInterface* baseLay = mat->GetLayer(0);
if( baseLay && (baseLay->GetOpacity() > fMaxOpacity) )
fMaxOpacity = baseLay->GetOpacity();
}
fSpans[i].fSpan->ClearShadowBits();
}
if( fMaxOpacity > 0 )
{
plShadowCastMsg* cast = TRACKED_NEW plShadowCastMsg(GetKey(), this, msg->Pipeline());
cast->Send();
}
return true;
}
#include "plProfile.h"
plProfile_CreateTimer("ShadowCaster", "RenderSetup", ShadowCaster);
hsBool plShadowCaster::MsgReceive(plMessage* msg)
{
plRenderMsg* rendMsg = plRenderMsg::ConvertNoRef(msg);
if( rendMsg )
{
plProfile_BeginLap(ShadowCaster, this->GetKey()->GetUoid().GetObjectName());
IOnRenderMsg(rendMsg);
plProfile_EndLap(ShadowCaster, this->GetKey()->GetUoid().GetObjectName());
return true;
}
return plMultiModifier::MsgReceive(msg);
}

View File

@ -1,141 +1,141 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plShadowCaster_inc
#define plShadowCaster_inc
#include "pnModifier/plMultiModifier.h"
#include "hsBounds.h"
#include "hsTemplates.h"
class plDrawableSpans;
class plSpan;
class plMessage;
class hsStream;
class hsResMgr;
class plShadowMaster;
class plRenderMsg;
class plShadowCaster : public plMultiModifier
{
public:
enum {
kNone = 0x0,
kSelfShadow = 0x1,
kPerspective = 0x2,
kLimitRes = 0x4
};
class DrawSpan
{
public:
DrawSpan& Set(plDrawableSpans* dr, const plSpan* sp, UInt32 idx) { fDraw = (dr); fSpan = (sp); fIndex = (idx); return *this; }
plDrawableSpans* fDraw;
const plSpan* fSpan;
UInt32 fIndex;
};
protected:
// Global state to just turn off the whole gig. Not just
// debugging, we'll probably want a user option for this.
static hsBool fShadowCastDisabled;
static hsBool fCanShadowCast;
// Properties really just to be read and written,
// never expected to change. Anything that might be
// triggered should go into plMultiModifier::fProps,
// to be network synced.
UInt8 fCastFlags;
hsScalar fBoost;
hsScalar fAttenScale;
hsScalar fBlurScale;
// Casting attributes calculated each frame.
hsScalar fMaxOpacity;
hsTArray<DrawSpan> fSpans;
friend plShadowMaster;
void ICollectAllSpans();
hsBool IOnRenderMsg(plRenderMsg* msg);
friend class plDXPipeline;
static void SetCanShadowCast(hsBool b) { fCanShadowCast = b; }
public:
plShadowCaster();
virtual ~plShadowCaster();
CLASSNAME_REGISTER( plShadowCaster );
GETINTERFACE_ANY( plShadowCaster, plMultiModifier );
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsScalar MaxOpacity() const { return fMaxOpacity; }
const hsTArray<DrawSpan>& Spans() const { return fSpans; }
hsBool GetSelfShadow() const { return 0 != (fCastFlags & kSelfShadow); }
void SetSelfShadow(hsBool on) { if(on) fCastFlags |= kSelfShadow; else fCastFlags &= ~kSelfShadow; }
hsBool GetPerspective() const { return 0 != (fCastFlags & kPerspective); }
void SetPerspective(hsBool on) { if(on) fCastFlags |= kPerspective; else fCastFlags &= ~kPerspective; }
hsBool GetLimitRes() const { return 0 != (fCastFlags & kLimitRes); }
void SetLimitRes(hsBool on) { if(on) fCastFlags |= kLimitRes; else fCastFlags &= ~kLimitRes; }
hsScalar GetAttenScale() const { return fAttenScale; }
void SetAttenScale(hsScalar s) { fAttenScale = s; }
hsScalar GetBlurScale() const { return fBlurScale; }
void SetBlurScale(hsScalar s) { fBlurScale = s; }
hsScalar GetBoost() const { return fBoost; }
void SetBoost(hsScalar s) { fBoost = s; }
// These are usually handled internally, activating on read and deactivating
// on destruct. Made public in case they need to be manually handled, like
// on dynamic construction and use.
void Deactivate() const;
void Activate() const;
static void DisableShadowCast(hsBool on=true) { fShadowCastDisabled = on; }
static void EnableShadowCast(hsBool on=true) { fShadowCastDisabled = !on; }
static void ToggleShadowCast() { fShadowCastDisabled = !fShadowCastDisabled; }
static hsBool ShadowCastDisabled() { return !CanShadowCast() || fShadowCastDisabled; }
static hsBool CanShadowCast() { return fCanShadowCast; }
};
typedef plShadowCaster::DrawSpan plShadowCastSpan;
#endif // plShadowCaster_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plShadowCaster_inc
#define plShadowCaster_inc
#include "pnModifier/plMultiModifier.h"
#include "hsBounds.h"
#include "hsTemplates.h"
class plDrawableSpans;
class plSpan;
class plMessage;
class hsStream;
class hsResMgr;
class plShadowMaster;
class plRenderMsg;
class plShadowCaster : public plMultiModifier
{
public:
enum {
kNone = 0x0,
kSelfShadow = 0x1,
kPerspective = 0x2,
kLimitRes = 0x4
};
class DrawSpan
{
public:
DrawSpan& Set(plDrawableSpans* dr, const plSpan* sp, UInt32 idx) { fDraw = (dr); fSpan = (sp); fIndex = (idx); return *this; }
plDrawableSpans* fDraw;
const plSpan* fSpan;
UInt32 fIndex;
};
protected:
// Global state to just turn off the whole gig. Not just
// debugging, we'll probably want a user option for this.
static hsBool fShadowCastDisabled;
static hsBool fCanShadowCast;
// Properties really just to be read and written,
// never expected to change. Anything that might be
// triggered should go into plMultiModifier::fProps,
// to be network synced.
UInt8 fCastFlags;
hsScalar fBoost;
hsScalar fAttenScale;
hsScalar fBlurScale;
// Casting attributes calculated each frame.
hsScalar fMaxOpacity;
hsTArray<DrawSpan> fSpans;
friend plShadowMaster;
void ICollectAllSpans();
hsBool IOnRenderMsg(plRenderMsg* msg);
friend class plDXPipeline;
static void SetCanShadowCast(hsBool b) { fCanShadowCast = b; }
public:
plShadowCaster();
virtual ~plShadowCaster();
CLASSNAME_REGISTER( plShadowCaster );
GETINTERFACE_ANY( plShadowCaster, plMultiModifier );
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsScalar MaxOpacity() const { return fMaxOpacity; }
const hsTArray<DrawSpan>& Spans() const { return fSpans; }
hsBool GetSelfShadow() const { return 0 != (fCastFlags & kSelfShadow); }
void SetSelfShadow(hsBool on) { if(on) fCastFlags |= kSelfShadow; else fCastFlags &= ~kSelfShadow; }
hsBool GetPerspective() const { return 0 != (fCastFlags & kPerspective); }
void SetPerspective(hsBool on) { if(on) fCastFlags |= kPerspective; else fCastFlags &= ~kPerspective; }
hsBool GetLimitRes() const { return 0 != (fCastFlags & kLimitRes); }
void SetLimitRes(hsBool on) { if(on) fCastFlags |= kLimitRes; else fCastFlags &= ~kLimitRes; }
hsScalar GetAttenScale() const { return fAttenScale; }
void SetAttenScale(hsScalar s) { fAttenScale = s; }
hsScalar GetBlurScale() const { return fBlurScale; }
void SetBlurScale(hsScalar s) { fBlurScale = s; }
hsScalar GetBoost() const { return fBoost; }
void SetBoost(hsScalar s) { fBoost = s; }
// These are usually handled internally, activating on read and deactivating
// on destruct. Made public in case they need to be manually handled, like
// on dynamic construction and use.
void Deactivate() const;
void Activate() const;
static void DisableShadowCast(hsBool on=true) { fShadowCastDisabled = on; }
static void EnableShadowCast(hsBool on=true) { fShadowCastDisabled = !on; }
static void ToggleShadowCast() { fShadowCastDisabled = !fShadowCastDisabled; }
static hsBool ShadowCastDisabled() { return !CanShadowCast() || fShadowCastDisabled; }
static hsBool CanShadowCast() { return fCanShadowCast; }
};
typedef plShadowCaster::DrawSpan plShadowCastSpan;
#endif // plShadowCaster_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,154 +1,154 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plShadowMaster_inc
#define plShadowMaster_inc
#include "pnSceneObject/plObjInterface.h"
class plShadowCaster;
class plShadowSlave;
struct hsMatrix44;
class hsBounds3Ext;
class hsStream;
class hsResMgr;
class plMessage;
class plLightInfo;
class plShadowCastMsg;
class plShadowMaster : public plObjInterface
{
public:
// Props inc by 1 (bit shift in bitvector).
enum plDrawProperties {
kDisable = 0,
kSelfShadow,
kNumProps // last in the list
};
protected:
// Global clamp on shadow map size and stuff
static UInt32 fGlobalMaxSize;
static hsScalar fGlobalMaxDist;
static hsScalar fGlobalVisParm;
// Constant parameter(s) for this master.
hsScalar fAttenDist;
hsScalar fMaxDist;
hsScalar fMinDist;
UInt32 fMaxSize;
UInt32 fMinSize;
hsScalar fPower;
// Temp data used for one frame and recycled.
hsTArray<plShadowSlave*> fSlavePool;
plLightInfo* fLightInfo;
// These are specific to the projection type (perspective or orthogonal), so have to
// be implemented by the derived class.
virtual void IComputeWorldToLight(const hsBounds3Ext& bnd, plShadowSlave* slave) const = 0;
virtual void IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const = 0;
virtual void IComputeISect(const hsBounds3Ext& bnd, plShadowSlave* slave) const = 0;
virtual void IComputeBounds(const hsBounds3Ext& bnd, plShadowSlave* slave) const = 0;
// Base class implementations of the rest. These might need to be overridden later, especially
// on computing the width and height. That's really specific to the projection type, but
// to get started I'll probably just always return 256x256.
virtual void IComputeCasterBounds(const plShadowCaster* caster, hsBounds3Ext& casterBnd);
virtual void IComputeWidthAndHeight(plShadowCastMsg* castMsg, plShadowSlave* slave) const;
virtual void IComputeLUT(plShadowCastMsg* castMsg, plShadowSlave* slave) const;
virtual hsScalar IComputePower(const plShadowCaster* caster, const hsBounds3Ext& casterBnd) const;
virtual plShadowSlave* ILastChanceToBail(plShadowCastMsg* castMsg, plShadowSlave* slave);
virtual plShadowSlave* ICreateShadowSlave(plShadowCastMsg* castMsg, const hsBounds3Ext& casterBnd, hsScalar power);
virtual plShadowSlave* INewSlave(const plShadowCaster* caster) = 0;
virtual plShadowSlave* INextSlave(const plShadowCaster* caster);
virtual plShadowSlave* IRecycleSlave(plShadowSlave* slave);
plLightInfo* ISetLightInfo();
virtual void IBeginRender();
virtual hsBool IOnCastMsg(plShadowCastMsg* castMsg);
public:
plShadowMaster();
virtual ~plShadowMaster();
CLASSNAME_REGISTER( plShadowMaster );
GETINTERFACE_ANY( plShadowMaster, plObjInterface );
virtual hsBool MsgReceive(plMessage* msg);
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) {}
Int32 GetNumProperties() const { return kNumProps; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// These are usually handled internally, activating on read and deactivating
// on destruct. Made public in case they need to be manually handled, like
// on dynamic construction and use.
void Deactivate() const;
void Activate() const;
// These should only be useful on scene conversion.
hsScalar GetAttenDist() const { return fAttenDist; }
void SetAttenDist(hsScalar d) { fAttenDist = d; }
hsScalar GetMaxDist() const { return fMaxDist; }
hsScalar GetMinDist() const { return fMinDist; }
void SetMaxDist(hsScalar m);
UInt32 GetMaxSize() const { return fMaxSize; }
UInt32 GetMinSize() const { return fMinSize; }
void SetMaxSize(UInt32 s) { fMaxSize = s; }
void SetMinSize(UInt32 s) { fMinSize = s; }
hsScalar GetPower() const { return fPower; }
void SetPower(hsScalar f) { fPower = f; }
static void SetGlobalMaxSize(UInt32 s) ;
static UInt32 GetGlobalMaxSize() { return fGlobalMaxSize; }
static void SetGlobalMaxDist(hsScalar s) { fGlobalMaxDist = s; }
static hsScalar GetGlobalMaxDist() { return fGlobalMaxDist; }
static void SetGlobalShadowQuality(hsScalar s);
static hsScalar GetGlobalShadowQuality() { return fGlobalVisParm; }
};
#endif // plShadowMaster_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plShadowMaster_inc
#define plShadowMaster_inc
#include "pnSceneObject/plObjInterface.h"
class plShadowCaster;
class plShadowSlave;
struct hsMatrix44;
class hsBounds3Ext;
class hsStream;
class hsResMgr;
class plMessage;
class plLightInfo;
class plShadowCastMsg;
class plShadowMaster : public plObjInterface
{
public:
// Props inc by 1 (bit shift in bitvector).
enum plDrawProperties {
kDisable = 0,
kSelfShadow,
kNumProps // last in the list
};
protected:
// Global clamp on shadow map size and stuff
static UInt32 fGlobalMaxSize;
static hsScalar fGlobalMaxDist;
static hsScalar fGlobalVisParm;
// Constant parameter(s) for this master.
hsScalar fAttenDist;
hsScalar fMaxDist;
hsScalar fMinDist;
UInt32 fMaxSize;
UInt32 fMinSize;
hsScalar fPower;
// Temp data used for one frame and recycled.
hsTArray<plShadowSlave*> fSlavePool;
plLightInfo* fLightInfo;
// These are specific to the projection type (perspective or orthogonal), so have to
// be implemented by the derived class.
virtual void IComputeWorldToLight(const hsBounds3Ext& bnd, plShadowSlave* slave) const = 0;
virtual void IComputeProjections(plShadowCastMsg* castMsg, plShadowSlave* slave) const = 0;
virtual void IComputeISect(const hsBounds3Ext& bnd, plShadowSlave* slave) const = 0;
virtual void IComputeBounds(const hsBounds3Ext& bnd, plShadowSlave* slave) const = 0;
// Base class implementations of the rest. These might need to be overridden later, especially
// on computing the width and height. That's really specific to the projection type, but
// to get started I'll probably just always return 256x256.
virtual void IComputeCasterBounds(const plShadowCaster* caster, hsBounds3Ext& casterBnd);
virtual void IComputeWidthAndHeight(plShadowCastMsg* castMsg, plShadowSlave* slave) const;
virtual void IComputeLUT(plShadowCastMsg* castMsg, plShadowSlave* slave) const;
virtual hsScalar IComputePower(const plShadowCaster* caster, const hsBounds3Ext& casterBnd) const;
virtual plShadowSlave* ILastChanceToBail(plShadowCastMsg* castMsg, plShadowSlave* slave);
virtual plShadowSlave* ICreateShadowSlave(plShadowCastMsg* castMsg, const hsBounds3Ext& casterBnd, hsScalar power);
virtual plShadowSlave* INewSlave(const plShadowCaster* caster) = 0;
virtual plShadowSlave* INextSlave(const plShadowCaster* caster);
virtual plShadowSlave* IRecycleSlave(plShadowSlave* slave);
plLightInfo* ISetLightInfo();
virtual void IBeginRender();
virtual hsBool IOnCastMsg(plShadowCastMsg* castMsg);
public:
plShadowMaster();
virtual ~plShadowMaster();
CLASSNAME_REGISTER( plShadowMaster );
GETINTERFACE_ANY( plShadowMaster, plObjInterface );
virtual hsBool MsgReceive(plMessage* msg);
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) {}
Int32 GetNumProperties() const { return kNumProps; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// These are usually handled internally, activating on read and deactivating
// on destruct. Made public in case they need to be manually handled, like
// on dynamic construction and use.
void Deactivate() const;
void Activate() const;
// These should only be useful on scene conversion.
hsScalar GetAttenDist() const { return fAttenDist; }
void SetAttenDist(hsScalar d) { fAttenDist = d; }
hsScalar GetMaxDist() const { return fMaxDist; }
hsScalar GetMinDist() const { return fMinDist; }
void SetMaxDist(hsScalar m);
UInt32 GetMaxSize() const { return fMaxSize; }
UInt32 GetMinSize() const { return fMinSize; }
void SetMaxSize(UInt32 s) { fMaxSize = s; }
void SetMinSize(UInt32 s) { fMinSize = s; }
hsScalar GetPower() const { return fPower; }
void SetPower(hsScalar f) { fPower = f; }
static void SetGlobalMaxSize(UInt32 s) ;
static UInt32 GetGlobalMaxSize() { return fGlobalMaxSize; }
static void SetGlobalMaxDist(hsScalar s) { fGlobalMaxDist = s; }
static hsScalar GetGlobalMaxDist() { return fGlobalMaxDist; }
static void SetGlobalShadowQuality(hsScalar s);
static hsScalar GetGlobalShadowQuality() { return fGlobalVisParm; }
};
#endif // plShadowMaster_inc

View File

@ -1,200 +1,200 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plShadowSlave.h"
#include "plTweak.h"
#include <float.h>
static const hsScalar kMinMinZ = 1.f; // totally random arbitrary number (has to be > 0).
bool plShadowSlave::ISetupOrthoViewTransform()
{
hsBounds3Ext bnd = fCasterWorldBounds;
bnd.Transform(&fWorldToLight);
hsScalar minZ = bnd.GetMins().fZ;
hsScalar maxZ = bnd.GetCenter().fZ + fAttenDist;
hsScalar minX = bnd.GetMins().fX;
hsScalar maxX = bnd.GetMaxs().fX;
hsScalar minY = bnd.GetMins().fY;
hsScalar maxY = bnd.GetMaxs().fY;
hsMatrix44 proj;
proj.Reset();
proj.NotIdentity();
// First the LightToTexture, which uses the above pretty much as is.
// Note the remapping to range [0.5..width-0.5] etc.
// About this kAdjustBias. According to the docs, it should be 0.5,
// and on the perspective projection 0.5 works great. But on the
// directional (ortho) projection, it just makes the mapping wrong,
// and an offset of zero works great. This could be a driver bug, or
// hardware "dependency" (read IHV bug), but whatever, zero is working
// now. Might need to adjust for new drivers or other hardware.
const hsScalar kAdjustBias = 0.0f;
proj.fMap[0][0] = 1.f / (maxX - minX);
proj.fMap[0][3] = -minX / (maxX - minX) + kAdjustBias / fWidth;
proj.fMap[1][1] = -1.f / (maxY - minY);
proj.fMap[1][3] = -minY / (maxY - minY) + kAdjustBias / fHeight;
proj.fMap[2][2] = 1.f;
proj.fMap[3][3] = 1.f;
fWorldToTexture = proj * fWorldToLight;
// Now the LightToNDC. This one's a little trickier, because we want to compensate for
// having brought in the viewport to keep our border constant, so we can clamp the
// projected texture and not have the edges smear off to infinity.
// Like the adjust bias above, this part is correct in theory, but only
// screws things up (increases Z-acne).
#if 0
hsScalar delX = maxX - minX;
minX += delX / (fWidth * 0.5f);
maxX -= delX / (fWidth * 0.5f);
hsScalar delY = maxY - minY;
minY += delY / (fHeight * 0.5f);
maxY -= delY / (fHeight * 0.5f);
#endif
fView.SetView(hsPoint3(minX, minY, minZ), hsPoint3(maxX, maxY, maxZ));
fView.SetScreenSize((UInt16)fWidth, (UInt16)fHeight);
fView.SetCameraTransform(fWorldToLight, fLightToWorld);
fView.SetPerspective(false);
fView.SetViewPort(0, 0, hsScalar(fWidth), hsScalar(fHeight), false);
fLightDir = fLightToWorld.GetAxis(hsMatrix44::kUp);
SetFlag(kPositional, false);
SetFlag(kReverseCull, true);
return true;
}
bool plShadowSlave::ISetupPerspViewTransform()
{
hsBounds3Ext bnd = fCasterWorldBounds;
bnd.Transform(&fWorldToLight);
hsScalar minZ = bnd.GetMins().fZ;
hsScalar maxZ = bnd.GetCenter().fZ + fAttenDist;
if( minZ < kMinMinZ )
minZ = kMinMinZ;
// EAP
// This is my hack to get the Nexus age working. The real problem
// is probably data-side. I take full responsibility for this
// hack-around breaking the entire system, loosing data, causing
// unauthorized credit card transactions, etc.
if (_isnan(bnd.GetMins().fX) || _isnan(bnd.GetMins().fY))
return false;
if (_isnan(bnd.GetMaxs().fX) || _isnan(bnd.GetMaxs().fY))
return false;
hsScalar cotX, cotY;
if( -bnd.GetMins().fX > bnd.GetMaxs().fX )
{
hsAssert(bnd.GetMins().fX < 0, "Empty shadow caster bounds?");
cotX = -minZ / bnd.GetMins().fX;
}
else
{
hsAssert(bnd.GetMaxs().fX > 0, "Empty shadow caster bounds?");
cotX = minZ / bnd.GetMaxs().fX;
}
if( -bnd.GetMins().fY > bnd.GetMaxs().fY )
{
hsAssert(bnd.GetMins().fY < 0, "Empty shadow caster bounds?");
cotY = -minZ / bnd.GetMins().fY;
}
else
{
hsAssert(bnd.GetMaxs().fY > 0, "Empty shadow caster bounds?");
cotY = minZ / bnd.GetMaxs().fY;
}
hsMatrix44 proj;
proj.Reset();
proj.NotIdentity();
// First the LightToTexture, which uses the above pretty much as is.
// Note the remapping to range [0.5..width-0.5] etc. Also, the perspective
// divide is by the 3rd output (not the fourth), so we make the 3rd
// output be W (instead of Z).
// This also means that our translate goes into [i][2] instead of [i][3].
#if 0
proj.fMap[0][0] = cotX * 0.5f;
proj.fMap[0][2] = -0.5f * (1.f + 0.5f/fWidth);
proj.fMap[1][1] = cotY * 0.5f;
proj.fMap[1][2] = -0.5f * (1.f + 0.5f/fHeight);
#else
plConst(hsScalar) kBiasScale(1.f);
plConst(hsScalar) kBiasTrans(1.f);
proj.fMap[0][0] = cotX * 0.5f * ( hsScalar(fWidth-2.f) / hsScalar(fWidth) ) * kBiasScale;
proj.fMap[0][2] = 0.5f * (1.f - kBiasTrans * 0.5f/fWidth);
proj.fMap[1][1] = -cotY * 0.5f * ( hsScalar(fHeight-2.f) / hsScalar(fHeight) ) * kBiasScale;
proj.fMap[1][2] = 0.5f * (1.f - kBiasTrans * 0.5f/fHeight);
#endif
#if 0 // This computes correct Z, but we really just want W in 3rd component. HACKFISH
proj.fMap[2][2] = maxZ / (maxZ - minZ);
proj.fMap[2][3] = -minZ * maxZ / (maxZ - minZ);
#elif 1
proj.fMap[2][2] = 1.f;
proj.fMap[2][3] = 0;
#endif
proj.fMap[3][2] = 1.f;
proj.fMap[3][3] = 0;
fWorldToTexture = proj * fWorldToLight;
// Now the LightToNDC. This one's a little trickier, because we want to compensate for
// having brought in the viewport to keep our border constant, so we can clamp the
// projected texture and not have the edges smear off to infinity.
cotX -= cotX / (fWidth * 0.5f);
cotY -= cotY / (fHeight * 0.5f);
hsScalar tanX = 1.f / cotX;
hsScalar tanY = 1.f / cotY;
fView.SetView(hsPoint3(-tanX, -tanY, minZ), hsPoint3(tanX, tanY, maxZ));
fView.SetScreenSize((UInt16)fWidth, (UInt16)fHeight);
fView.SetCameraTransform(fWorldToLight, fLightToWorld);
fView.SetPerspective(true);
fView.SetViewPort(0, 0, hsScalar(fWidth), hsScalar(fHeight), false);
fLightPos = fLightToWorld.GetTranslate();
SetFlag(kPositional, true);
return true;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plShadowSlave.h"
#include "plTweak.h"
#include <float.h>
static const hsScalar kMinMinZ = 1.f; // totally random arbitrary number (has to be > 0).
bool plShadowSlave::ISetupOrthoViewTransform()
{
hsBounds3Ext bnd = fCasterWorldBounds;
bnd.Transform(&fWorldToLight);
hsScalar minZ = bnd.GetMins().fZ;
hsScalar maxZ = bnd.GetCenter().fZ + fAttenDist;
hsScalar minX = bnd.GetMins().fX;
hsScalar maxX = bnd.GetMaxs().fX;
hsScalar minY = bnd.GetMins().fY;
hsScalar maxY = bnd.GetMaxs().fY;
hsMatrix44 proj;
proj.Reset();
proj.NotIdentity();
// First the LightToTexture, which uses the above pretty much as is.
// Note the remapping to range [0.5..width-0.5] etc.
// About this kAdjustBias. According to the docs, it should be 0.5,
// and on the perspective projection 0.5 works great. But on the
// directional (ortho) projection, it just makes the mapping wrong,
// and an offset of zero works great. This could be a driver bug, or
// hardware "dependency" (read IHV bug), but whatever, zero is working
// now. Might need to adjust for new drivers or other hardware.
const hsScalar kAdjustBias = 0.0f;
proj.fMap[0][0] = 1.f / (maxX - minX);
proj.fMap[0][3] = -minX / (maxX - minX) + kAdjustBias / fWidth;
proj.fMap[1][1] = -1.f / (maxY - minY);
proj.fMap[1][3] = -minY / (maxY - minY) + kAdjustBias / fHeight;
proj.fMap[2][2] = 1.f;
proj.fMap[3][3] = 1.f;
fWorldToTexture = proj * fWorldToLight;
// Now the LightToNDC. This one's a little trickier, because we want to compensate for
// having brought in the viewport to keep our border constant, so we can clamp the
// projected texture and not have the edges smear off to infinity.
// Like the adjust bias above, this part is correct in theory, but only
// screws things up (increases Z-acne).
#if 0
hsScalar delX = maxX - minX;
minX += delX / (fWidth * 0.5f);
maxX -= delX / (fWidth * 0.5f);
hsScalar delY = maxY - minY;
minY += delY / (fHeight * 0.5f);
maxY -= delY / (fHeight * 0.5f);
#endif
fView.SetView(hsPoint3(minX, minY, minZ), hsPoint3(maxX, maxY, maxZ));
fView.SetScreenSize((UInt16)fWidth, (UInt16)fHeight);
fView.SetCameraTransform(fWorldToLight, fLightToWorld);
fView.SetPerspective(false);
fView.SetViewPort(0, 0, hsScalar(fWidth), hsScalar(fHeight), false);
fLightDir = fLightToWorld.GetAxis(hsMatrix44::kUp);
SetFlag(kPositional, false);
SetFlag(kReverseCull, true);
return true;
}
bool plShadowSlave::ISetupPerspViewTransform()
{
hsBounds3Ext bnd = fCasterWorldBounds;
bnd.Transform(&fWorldToLight);
hsScalar minZ = bnd.GetMins().fZ;
hsScalar maxZ = bnd.GetCenter().fZ + fAttenDist;
if( minZ < kMinMinZ )
minZ = kMinMinZ;
// EAP
// This is my hack to get the Nexus age working. The real problem
// is probably data-side. I take full responsibility for this
// hack-around breaking the entire system, loosing data, causing
// unauthorized credit card transactions, etc.
if (_isnan(bnd.GetMins().fX) || _isnan(bnd.GetMins().fY))
return false;
if (_isnan(bnd.GetMaxs().fX) || _isnan(bnd.GetMaxs().fY))
return false;
hsScalar cotX, cotY;
if( -bnd.GetMins().fX > bnd.GetMaxs().fX )
{
hsAssert(bnd.GetMins().fX < 0, "Empty shadow caster bounds?");
cotX = -minZ / bnd.GetMins().fX;
}
else
{
hsAssert(bnd.GetMaxs().fX > 0, "Empty shadow caster bounds?");
cotX = minZ / bnd.GetMaxs().fX;
}
if( -bnd.GetMins().fY > bnd.GetMaxs().fY )
{
hsAssert(bnd.GetMins().fY < 0, "Empty shadow caster bounds?");
cotY = -minZ / bnd.GetMins().fY;
}
else
{
hsAssert(bnd.GetMaxs().fY > 0, "Empty shadow caster bounds?");
cotY = minZ / bnd.GetMaxs().fY;
}
hsMatrix44 proj;
proj.Reset();
proj.NotIdentity();
// First the LightToTexture, which uses the above pretty much as is.
// Note the remapping to range [0.5..width-0.5] etc. Also, the perspective
// divide is by the 3rd output (not the fourth), so we make the 3rd
// output be W (instead of Z).
// This also means that our translate goes into [i][2] instead of [i][3].
#if 0
proj.fMap[0][0] = cotX * 0.5f;
proj.fMap[0][2] = -0.5f * (1.f + 0.5f/fWidth);
proj.fMap[1][1] = cotY * 0.5f;
proj.fMap[1][2] = -0.5f * (1.f + 0.5f/fHeight);
#else
plConst(hsScalar) kBiasScale(1.f);
plConst(hsScalar) kBiasTrans(1.f);
proj.fMap[0][0] = cotX * 0.5f * ( hsScalar(fWidth-2.f) / hsScalar(fWidth) ) * kBiasScale;
proj.fMap[0][2] = 0.5f * (1.f - kBiasTrans * 0.5f/fWidth);
proj.fMap[1][1] = -cotY * 0.5f * ( hsScalar(fHeight-2.f) / hsScalar(fHeight) ) * kBiasScale;
proj.fMap[1][2] = 0.5f * (1.f - kBiasTrans * 0.5f/fHeight);
#endif
#if 0 // This computes correct Z, but we really just want W in 3rd component. HACKFISH
proj.fMap[2][2] = maxZ / (maxZ - minZ);
proj.fMap[2][3] = -minZ * maxZ / (maxZ - minZ);
#elif 1
proj.fMap[2][2] = 1.f;
proj.fMap[2][3] = 0;
#endif
proj.fMap[3][2] = 1.f;
proj.fMap[3][3] = 0;
fWorldToTexture = proj * fWorldToLight;
// Now the LightToNDC. This one's a little trickier, because we want to compensate for
// having brought in the viewport to keep our border constant, so we can clamp the
// projected texture and not have the edges smear off to infinity.
cotX -= cotX / (fWidth * 0.5f);
cotY -= cotY / (fHeight * 0.5f);
hsScalar tanX = 1.f / cotX;
hsScalar tanY = 1.f / cotY;
fView.SetView(hsPoint3(-tanX, -tanY, minZ), hsPoint3(tanX, tanY, maxZ));
fView.SetScreenSize((UInt16)fWidth, (UInt16)fHeight);
fView.SetCameraTransform(fWorldToLight, fLightToWorld);
fView.SetPerspective(true);
fView.SetViewPort(0, 0, hsScalar(fWidth), hsScalar(fHeight), false);
fLightPos = fLightToWorld.GetTranslate();
SetFlag(kPositional, true);
return true;
}

View File

@ -1,124 +1,124 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plShadowSlave_inc
#define plShadowSlave_inc
#include "hsMatrix44.h"
#include "hsBounds.h"
#include "plViewTransform.h"
#include "hsGeometry3.h"
class plShadowCaster;
class plVolumeIsect;
class plPipeline;
class plShadowSlave
{
public:
UInt32 fIndex;
hsMatrix44 fWorldToLight;
hsMatrix44 fLightToWorld;
hsPoint3 fLightPos;
hsVector3 fLightDir;
hsMatrix44 fWorldToTexture;
hsMatrix44 fCastLUT;
hsMatrix44 fRcvLUT;
plViewTransform fView;
hsScalar fPower;
hsScalar fBlurScale;
hsBounds3Ext fCasterWorldBounds;
hsBounds3Ext fWorldBounds;
plVolumeIsect* fIsect;
UInt32 fWidth;
UInt32 fHeight;
hsScalar fAttenDist;
hsScalar fPriority;
UInt32 fFlags;
enum SlaveFlag
{
kObeysLightGroups = 0x1,
kIncludesChars = 0x2,
kSelfShadow = 0x4,
kCastInCameraSpace = 0x8,
kReverseZ = 0x10,
kTwoSided = 0x20,
kReverseCull = 0x40,
kPositional = 0x80
};
void SetFlag(SlaveFlag f, hsBool on) { if(on) fFlags |= f; else fFlags &= ~f; }
hsBool HasFlag(SlaveFlag f) const { return 0 != (fFlags & f); }
hsBool ObeysLightGroups() const { return HasFlag(kObeysLightGroups); }
hsBool IncludesChars() const { return HasFlag(kIncludesChars); }
hsBool SelfShadow() const { return HasFlag(kSelfShadow); }
hsBool CastInCameraSpace() const { return HasFlag(kCastInCameraSpace); }
hsBool ReverseZ() const { return HasFlag(kReverseZ); }
hsBool TwoSided() const { return HasFlag(kTwoSided); }
hsBool ReverseCull() const { return HasFlag(kReverseCull); }
hsBool Positional() const { return HasFlag(kPositional); }
virtual void Init() { fFlags = 0; }
const plShadowCaster* fCaster;
// Internal to pipeline, no touch!!!
int fLightIndex;
int fLightRefIdx;
int fSelfShadowOn;
void* fPipeData;
bool ISetupOrthoViewTransform();
bool ISetupPerspViewTransform();
virtual bool SetupViewTransform(plPipeline* pipe) = 0;
};
class plDirectShadowSlave : public plShadowSlave
{
virtual bool SetupViewTransform(plPipeline* pipe) { return ISetupOrthoViewTransform(); }
};
class plPointShadowSlave : public plShadowSlave
{
virtual bool SetupViewTransform(plPipeline* pipe) { return ISetupPerspViewTransform(); }
};
#endif // plShadowSlave_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plShadowSlave_inc
#define plShadowSlave_inc
#include "hsMatrix44.h"
#include "hsBounds.h"
#include "plViewTransform.h"
#include "hsGeometry3.h"
class plShadowCaster;
class plVolumeIsect;
class plPipeline;
class plShadowSlave
{
public:
UInt32 fIndex;
hsMatrix44 fWorldToLight;
hsMatrix44 fLightToWorld;
hsPoint3 fLightPos;
hsVector3 fLightDir;
hsMatrix44 fWorldToTexture;
hsMatrix44 fCastLUT;
hsMatrix44 fRcvLUT;
plViewTransform fView;
hsScalar fPower;
hsScalar fBlurScale;
hsBounds3Ext fCasterWorldBounds;
hsBounds3Ext fWorldBounds;
plVolumeIsect* fIsect;
UInt32 fWidth;
UInt32 fHeight;
hsScalar fAttenDist;
hsScalar fPriority;
UInt32 fFlags;
enum SlaveFlag
{
kObeysLightGroups = 0x1,
kIncludesChars = 0x2,
kSelfShadow = 0x4,
kCastInCameraSpace = 0x8,
kReverseZ = 0x10,
kTwoSided = 0x20,
kReverseCull = 0x40,
kPositional = 0x80
};
void SetFlag(SlaveFlag f, hsBool on) { if(on) fFlags |= f; else fFlags &= ~f; }
hsBool HasFlag(SlaveFlag f) const { return 0 != (fFlags & f); }
hsBool ObeysLightGroups() const { return HasFlag(kObeysLightGroups); }
hsBool IncludesChars() const { return HasFlag(kIncludesChars); }
hsBool SelfShadow() const { return HasFlag(kSelfShadow); }
hsBool CastInCameraSpace() const { return HasFlag(kCastInCameraSpace); }
hsBool ReverseZ() const { return HasFlag(kReverseZ); }
hsBool TwoSided() const { return HasFlag(kTwoSided); }
hsBool ReverseCull() const { return HasFlag(kReverseCull); }
hsBool Positional() const { return HasFlag(kPositional); }
virtual void Init() { fFlags = 0; }
const plShadowCaster* fCaster;
// Internal to pipeline, no touch!!!
int fLightIndex;
int fLightRefIdx;
int fSelfShadowOn;
void* fPipeData;
bool ISetupOrthoViewTransform();
bool ISetupPerspViewTransform();
virtual bool SetupViewTransform(plPipeline* pipe) = 0;
};
class plDirectShadowSlave : public plShadowSlave
{
virtual bool SetupViewTransform(plPipeline* pipe) { return ISetupOrthoViewTransform(); }
};
class plPointShadowSlave : public plShadowSlave
{
virtual bool SetupViewTransform(plPipeline* pipe) { return ISetupPerspViewTransform(); }
};
#endif // plShadowSlave_inc