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:
@ -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})
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user