You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
953 lines
25 KiB
953 lines
25 KiB
14 years ago
|
/*==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 "plDynamicEnvMap.h"
|
||
|
|
||
|
#include "plPipeline.h"
|
||
|
#include "plPipeDebugFlags.h"
|
||
|
#include "plDrawable.h"
|
||
|
#include "plgDispatch.h"
|
||
|
#include "hsResMgr.h"
|
||
|
|
||
|
#include "hsTimer.h"
|
||
|
#include "hsStream.h"
|
||
|
|
||
|
#include "../plMessage/plRenderRequestMsg.h"
|
||
|
#include "../plMessage/plDynamicEnvMapMsg.h"
|
||
|
#include "../pfCamera/plCameraModifier.h"
|
||
|
#include "../pfCamera/plVirtualCamNeu.h"
|
||
|
#include "../plMessage/plRenderMsg.h"
|
||
|
#include "../plMessage/plAgeLoadedMsg.h"
|
||
|
#include "../plMessage/plLayRefMsg.h"
|
||
|
#include "../pnMessage/plPipeResMakeMsg.h"
|
||
|
#include "../pnMessage/plRefMsg.h"
|
||
|
|
||
|
#include "../plScene/plVisRegion.h"
|
||
|
#include "../plScene/plVisMgr.h"
|
||
|
#include "../plResMgr/plKeyFinder.h"
|
||
|
#include "../plSurface/plLayer.h"
|
||
|
|
||
|
plDynamicEnvMap::plDynamicEnvMap()
|
||
|
: fPos(0,0,0),
|
||
|
fHither(0.3f),
|
||
|
fYon(1000.f),
|
||
|
fFogStart(1000.f),
|
||
|
fRefreshRate(0.f),
|
||
|
fLastRefresh(0.0),
|
||
|
fLastRender(0),
|
||
|
fOutStanding(0),
|
||
|
fIncCharacters(false),
|
||
|
fRootNode(nil)
|
||
|
{
|
||
|
fColor.Set(0,0,0,1.f);
|
||
|
int i;
|
||
|
for( i = 0; i < 6; i++ )
|
||
|
fReqMsgs[i] = TRACKED_NEW plRenderRequestMsg(nil, &fReqs[i]);;
|
||
|
|
||
|
SetPosition(fPos);
|
||
|
}
|
||
|
|
||
|
plDynamicEnvMap::plDynamicEnvMap(UInt16 width, UInt16 height, UInt8 bitDepth, UInt8 zDepth, UInt8 sDepth)
|
||
|
: fPos(0,0,0),
|
||
|
fHither(0.3f),
|
||
|
fYon(0.f), // yon < hither means ignore and use current settings
|
||
|
fFogStart(-1.f), // - fog start means use current settings
|
||
|
fRefreshRate(0.f),
|
||
|
fLastRefresh(0.0),
|
||
|
fLastRender(0),
|
||
|
fOutStanding(0),
|
||
|
fIncCharacters(false),
|
||
|
fRootNode(nil),
|
||
|
plCubicRenderTarget(plRenderTarget::kIsTexture, width, height, bitDepth, zDepth, sDepth)
|
||
|
{
|
||
|
fColor.Set(0,0,0,1.f);
|
||
|
int i;
|
||
|
for( i = 0; i < 6; i++ )
|
||
|
fReqMsgs[i] = TRACKED_NEW plRenderRequestMsg(nil, &fReqs[i]);;
|
||
|
|
||
|
SetPosition(fPos);
|
||
|
}
|
||
|
|
||
|
plDynamicEnvMap::~plDynamicEnvMap()
|
||
|
{
|
||
|
SetDeviceRef(nil);
|
||
|
|
||
|
int i;
|
||
|
for( i = 0; i < 6; i++ )
|
||
|
delete fReqMsgs[i];
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::Init()
|
||
|
{
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plPipeRTMakeMsg::Index(), GetKey());
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), GetKey());
|
||
|
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
|
||
|
|
||
|
ISetupRenderRequests();
|
||
|
}
|
||
|
|
||
|
hsPoint3 plDynamicEnvMap::GetPosition() const
|
||
|
{
|
||
|
if (fRootNode)
|
||
|
{
|
||
|
// This is to catch export issues where we've got a root node, but its iface
|
||
|
// hasn't fully been set up yet.
|
||
|
if (fRootNode->GetCoordinateInterface())
|
||
|
return fRootNode->GetLocalToWorld().GetTranslate();
|
||
|
}
|
||
|
|
||
|
return fPos;
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::SetPosition(const hsPoint3& pos)
|
||
|
{
|
||
|
hsAssert(fRootNode == nil, "Trying to override a cube map's root node.");
|
||
|
fPos = pos;
|
||
|
SetCameraMatrix(fPos);
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::IUpdatePosition()
|
||
|
{
|
||
|
hsPoint3 pos = GetPosition();
|
||
|
if (pos != fPos)
|
||
|
SetCameraMatrix(fPos);
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::SetHither(hsScalar f)
|
||
|
{
|
||
|
fHither = f;
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::SetYon(hsScalar f)
|
||
|
{
|
||
|
fYon = f;
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::SetFogStart(hsScalar f)
|
||
|
{
|
||
|
fFogStart = f;
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::SetColor(const hsColorRGBA& col)
|
||
|
{
|
||
|
fColor = col;
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::SetRefreshRate(hsScalar secs)
|
||
|
{
|
||
|
fRefreshRate = secs / 6.f;
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::ISetupRenderRequests()
|
||
|
{
|
||
|
UInt32 renderState
|
||
|
= plPipeline::kRenderNormal
|
||
|
| plPipeline::kRenderClearColor
|
||
|
| plPipeline::kRenderClearDepth;
|
||
|
|
||
|
int i;
|
||
|
for( i = 0; i < 6; i++ )
|
||
|
{
|
||
|
fReqs[i].SetRenderState(renderState);
|
||
|
|
||
|
fReqs[i].SetDrawableMask(plDrawable::kNormal);
|
||
|
fReqs[i].SetSubDrawableMask(plDrawable::kSubAllTypes);
|
||
|
|
||
|
fReqs[i].SetHither(fHither);
|
||
|
fReqs[i].SetYon(fYon);
|
||
|
|
||
|
fReqs[i].SetFogStart(fFogStart);
|
||
|
|
||
|
fReqs[i].SetFovX(90.f);
|
||
|
fReqs[i].SetFovY(90.f);
|
||
|
|
||
|
fReqs[i].SetClearColor(fColor);
|
||
|
fReqs[i].SetClearDepth(1.f);
|
||
|
|
||
|
fReqs[i].SetClearDrawable(nil);
|
||
|
fReqs[i].SetRenderTarget(GetFace(i));
|
||
|
|
||
|
fReqs[i].SetCameraTransform(GetWorldToCamera(i), GetCameraToWorld(i));
|
||
|
|
||
|
fReqs[i].SetVisForce(fVisSet);
|
||
|
|
||
|
fReqs[i].RequestAck(GetKey());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::ISubmitRenderRequest(int i)
|
||
|
{
|
||
|
IUpdatePosition();
|
||
|
fReqMsgs[i]->SendAndKeep();
|
||
|
fLastRender = i;
|
||
|
fOutStanding++;
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::ISubmitRenderRequests()
|
||
|
{
|
||
|
IUpdatePosition();
|
||
|
int i;
|
||
|
for( i = 0; i < 6; i++ )
|
||
|
fReqMsgs[i]->SendAndKeep();
|
||
|
fLastRefresh = hsTimer::GetSysSeconds();
|
||
|
fOutStanding += 6;
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::ICheckForRefresh(double t, plPipeline *pipe)
|
||
|
{
|
||
|
if( fLastRefresh <= 0 )
|
||
|
{
|
||
|
ISubmitRenderRequests();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( fRefreshRate <= 0 )
|
||
|
return;
|
||
|
|
||
|
#ifndef PLASMA_EXTERNAL_RELEASE
|
||
|
if (pipe->IsDebugFlagSet(plPipeDbg::kFlagNVPerfHUD) && hsTimer::GetDelSysSeconds() == 0)
|
||
|
{
|
||
|
ISubmitRenderRequests();
|
||
|
return;
|
||
|
}
|
||
|
#endif // PLASMA_EXTERNAL_RELEASE
|
||
|
|
||
|
if( t > fLastRefresh + 6.f * fRefreshRate )
|
||
|
{
|
||
|
ISubmitRenderRequests();
|
||
|
return;
|
||
|
}
|
||
|
while( t > fLastRefresh + fRefreshRate )
|
||
|
{
|
||
|
int nextRender = fLastRender+1;
|
||
|
if( nextRender > 5 )
|
||
|
nextRender = 0;
|
||
|
ISubmitRenderRequest(nextRender);
|
||
|
fLastRefresh += fRefreshRate;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::ReRender()
|
||
|
{
|
||
|
ISetupRenderRequests();
|
||
|
ISubmitRenderRequests();
|
||
|
}
|
||
|
|
||
|
hsBool plDynamicEnvMap::INeedReRender()
|
||
|
{
|
||
|
fOutStanding = 0;
|
||
|
fLastRefresh = 0;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
hsBool plDynamicEnvMap::MsgReceive(plMessage* msg)
|
||
|
{
|
||
|
plRenderRequestAck* ack = plRenderRequestAck::ConvertNoRef(msg);
|
||
|
if( ack )
|
||
|
{
|
||
|
fOutStanding--;
|
||
|
return true;
|
||
|
}
|
||
|
plRenderMsg* rendMsg = plRenderMsg::ConvertNoRef(msg);
|
||
|
if( rendMsg )
|
||
|
{
|
||
|
if( fOutStanding )
|
||
|
INeedReRender();
|
||
|
|
||
|
ICheckForRefresh(hsTimer::GetSysSeconds(), rendMsg->Pipeline());
|
||
|
return true;
|
||
|
}
|
||
|
if( plPipeRTMakeMsg::ConvertNoRef(msg) )
|
||
|
{
|
||
|
INeedReRender();
|
||
|
plCubicRenderTarget::MsgReceive(msg);
|
||
|
return true;
|
||
|
}
|
||
|
plAgeLoadedMsg* ageLoaded = plAgeLoadedMsg::ConvertNoRef(msg);
|
||
|
if( ageLoaded && ageLoaded->fLoaded )
|
||
|
return INeedReRender();
|
||
|
|
||
|
if( plInitialAgeStateLoadedMsg::ConvertNoRef(msg) )
|
||
|
return INeedReRender();
|
||
|
|
||
|
plDynamicEnvMapMsg* cmd = plDynamicEnvMapMsg::ConvertNoRef(msg);
|
||
|
if( cmd )
|
||
|
{
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetPosition )
|
||
|
SetPosition(cmd->fPos);
|
||
|
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetHither )
|
||
|
SetHither(cmd->fHither);
|
||
|
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetFogStart )
|
||
|
SetFogStart(cmd->fFogStart);
|
||
|
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetYon )
|
||
|
SetYon(cmd->fYon);
|
||
|
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetColor )
|
||
|
SetColor(cmd->fColor);
|
||
|
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetRefresh )
|
||
|
SetRefreshRate(cmd->fRefresh);
|
||
|
|
||
|
// If we're going to ReRender, make sure we've gotten any
|
||
|
// parameter changes first.
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kReRender )
|
||
|
{
|
||
|
ISetupRenderRequests();
|
||
|
INeedReRender();
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
|
||
|
if( refMsg )
|
||
|
{
|
||
|
if( IOnRefMsg(refMsg) )
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return plCubicRenderTarget::MsgReceive(msg);
|
||
|
}
|
||
|
|
||
|
hsBool plDynamicEnvMap::IOnRefMsg(plGenRefMsg* refMsg)
|
||
|
{
|
||
|
switch( refMsg->fType)
|
||
|
{
|
||
|
case kRefVisSet:
|
||
|
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
|
||
|
{
|
||
|
plVisRegion* reg = plVisRegion::ConvertNoRef(refMsg->GetRef());
|
||
|
int idx = fVisRegions.Find(reg);
|
||
|
if( reg && (fVisRegions.kMissingIndex == idx) )
|
||
|
{
|
||
|
fVisRegions.Append(reg);
|
||
|
fVisSet.SetBit(reg->GetIndex());
|
||
|
}
|
||
|
ISetupRenderRequests();
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
plVisRegion* reg = plVisRegion::ConvertNoRef(refMsg->GetRef());
|
||
|
int idx = fVisRegions.Find(reg);
|
||
|
if( reg && (fVisRegions.kMissingIndex != idx) )
|
||
|
{
|
||
|
fVisRegions.Remove(idx);
|
||
|
fVisSet.ClearBit(reg->GetIndex());
|
||
|
}
|
||
|
ISetupRenderRequests();
|
||
|
return true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case kRefRootNode:
|
||
|
plSceneObject *so = plSceneObject::ConvertNoRef(refMsg->GetRef());
|
||
|
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
|
||
|
fRootNode = so;
|
||
|
else
|
||
|
fRootNode = nil;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::SetIncludeCharacters(hsBool b)
|
||
|
{
|
||
|
fIncCharacters = b;
|
||
|
if( b )
|
||
|
fVisSet.SetBit(plVisMgr::kCharacter);
|
||
|
else
|
||
|
fVisSet.ClearBit(plVisMgr::kCharacter);
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::AddVisRegion(plVisRegion* reg)
|
||
|
{
|
||
|
plGenRefMsg* msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnRequest, 0, kRefVisSet);
|
||
|
hsgResMgr::ResMgr()->AddViaNotify(reg->GetKey(), msg, plRefFlags::kActiveRef);
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::Read(hsStream* s, hsResMgr* mgr)
|
||
|
{
|
||
|
hsKeyedObject::Read(s, mgr);
|
||
|
UInt32 sz = plCubicRenderTarget::Read(s);
|
||
|
|
||
|
fPos.Read(s);
|
||
|
fHither = s->ReadSwapScalar();
|
||
|
fYon = s->ReadSwapScalar();
|
||
|
fFogStart = s->ReadSwapScalar();
|
||
|
fColor.Read(s);
|
||
|
|
||
|
fRefreshRate = s->ReadSwapScalar();
|
||
|
|
||
|
SetPosition(fPos);
|
||
|
|
||
|
sz += sizeof(fPos) + sizeof(fHither) + sizeof(fYon) + sizeof(fFogStart) + sizeof(fColor) + sizeof(fRefreshRate);
|
||
|
|
||
|
fIncCharacters = s->ReadByte();
|
||
|
SetIncludeCharacters(fIncCharacters);
|
||
|
int nVis = s->ReadSwap32();
|
||
|
int i;
|
||
|
for( i = 0; i < nVis; i++ )
|
||
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefVisSet), plRefFlags::kActiveRef);
|
||
|
|
||
|
nVis = s->ReadSwap32();
|
||
|
for( i = 0; i < nVis; i++)
|
||
|
{
|
||
|
char *name = s->ReadSafeString();
|
||
|
plKey key = plKeyFinder::Instance().StupidSearch(nil, nil, plVisRegion::Index(), name);
|
||
|
delete[] name;
|
||
|
if (key)
|
||
|
hsgResMgr::ResMgr()->AddViaNotify(key, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefVisSet), plRefFlags::kActiveRef);
|
||
|
}
|
||
|
|
||
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefRootNode), plRefFlags::kActiveRef);
|
||
|
|
||
|
Init();
|
||
|
}
|
||
|
|
||
|
void plDynamicEnvMap::Write(hsStream* s, hsResMgr* mgr)
|
||
|
{
|
||
|
hsKeyedObject::Write(s, mgr);
|
||
|
|
||
|
UInt32 sz = plCubicRenderTarget::Write(s);
|
||
|
|
||
|
fPos.Write(s);
|
||
|
s->WriteSwapScalar(fHither);
|
||
|
s->WriteSwapScalar(fYon);
|
||
|
s->WriteSwapScalar(fFogStart);
|
||
|
fColor.Write(s);
|
||
|
|
||
|
s->WriteSwapScalar(fRefreshRate);
|
||
|
|
||
|
sz += sizeof(fPos) + sizeof(fHither) + sizeof(fYon) + sizeof(fFogStart) + sizeof(fColor) + sizeof(fRefreshRate);
|
||
|
|
||
|
s->WriteByte(fIncCharacters);
|
||
|
s->WriteSwap32(fVisRegions.GetCount());
|
||
|
int i;
|
||
|
for( i = 0; i < fVisRegions.GetCount(); i++ )
|
||
|
mgr->WriteKey(s, fVisRegions[i]);
|
||
|
|
||
|
s->WriteSwap32(fVisRegionNames.Count());
|
||
|
for( i = 0; i < fVisRegionNames.Count(); i++)
|
||
|
{
|
||
|
s->WriteSafeString(fVisRegionNames[i]);
|
||
|
}
|
||
|
|
||
|
mgr->WriteKey(s, fRootNode);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
UInt8 plDynamicCamMap::fFlags = kReflectionEnabled | kReflectionCapable;
|
||
|
|
||
|
plDynamicCamMap::plDynamicCamMap() :
|
||
|
fHither(0.3f),
|
||
|
fYon(500.f),
|
||
|
fFogStart(1000.f),
|
||
|
fRefreshRate(0.f),
|
||
|
fLastRefresh(0.0),
|
||
|
fOutStanding(0),
|
||
|
fCamera(nil),
|
||
|
fRootNode(nil),
|
||
|
fIncCharacters(false),
|
||
|
fDisableTexture(nil)
|
||
|
{
|
||
|
fColor.Set(0,0,0,1.f);
|
||
|
fReqMsg = TRACKED_NEW plRenderRequestMsg(nil, &fReq);
|
||
|
}
|
||
|
|
||
|
plDynamicCamMap::plDynamicCamMap(UInt16 width, UInt16 height, UInt8 bitDepth, UInt8 zDepth, UInt8 sDepth) :
|
||
|
fHither(0.3f),
|
||
|
fYon(-1.f),
|
||
|
fFogStart(-1.f),
|
||
|
fRefreshRate(0.f),
|
||
|
fLastRefresh(0.0),
|
||
|
fOutStanding(0),
|
||
|
fCamera(nil),
|
||
|
fRootNode(nil),
|
||
|
fIncCharacters(false),
|
||
|
fDisableTexture(nil),
|
||
|
plRenderTarget(plRenderTarget::kIsTexture, width, height, bitDepth, zDepth, sDepth)
|
||
|
{
|
||
|
fColor.Set(0,0,0,1.f);
|
||
|
fReqMsg = TRACKED_NEW plRenderRequestMsg(nil, &fReq);
|
||
|
}
|
||
|
|
||
|
plDynamicCamMap::~plDynamicCamMap()
|
||
|
{
|
||
|
plgDispatch::Dispatch()->UnRegisterForExactType(plPipeRTMakeMsg::Index(), GetKey());
|
||
|
plgDispatch::Dispatch()->UnRegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
|
||
|
plgDispatch::Dispatch()->UnRegisterForExactType(plAgeLoadedMsg::Index(), GetKey());
|
||
|
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
|
||
|
|
||
|
SetDeviceRef(nil);
|
||
|
|
||
|
delete fReqMsg;
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::Init()
|
||
|
{
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plPipeRTMakeMsg::Index(), GetKey());
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), GetKey());
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::SetRefreshRate(hsScalar secs)
|
||
|
{
|
||
|
fRefreshRate = secs;
|
||
|
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::ISetupRenderRequest(plPipeline *pipe)
|
||
|
{
|
||
|
fReq.SetRenderState(plPipeline::kRenderNormal | plPipeline::kRenderClearColor | plPipeline::kRenderClearDepth);
|
||
|
fReq.SetDrawableMask(plDrawable::kNormal);
|
||
|
fReq.SetSubDrawableMask(plDrawable::kSubAllTypes);
|
||
|
fReq.SetHither(fHither);
|
||
|
fReq.SetYon(fYon);
|
||
|
fReq.SetFogStart(fFogStart);
|
||
|
|
||
|
// For a reflection map, this must match the camera FOV, or else the camera based
|
||
|
// texture coordinates for the reflection texture will be off.
|
||
|
//
|
||
|
// For a fixed camera, you might want to use the height in both params, so that
|
||
|
// you're rendering a square FOV into your square texture. In practice, the artists
|
||
|
// don't mind the visual results when just scaling their UVs, so I'll leave it the
|
||
|
// same for both cases.
|
||
|
fReq.SetFovX(fCamera ? fCamera->GetFOVw() : plVirtualCam1::Instance()->GetFOVw());
|
||
|
fReq.SetFovY(fCamera ? fCamera->GetFOVh() : plVirtualCam1::Instance()->GetFOVh());
|
||
|
|
||
|
fReq.SetClearColor(fColor);
|
||
|
fReq.SetClearDepth(1.f);
|
||
|
fReq.SetClearDrawable(nil);
|
||
|
fReq.SetRenderTarget(this);
|
||
|
fReq.SetVisForce(fVisSet);
|
||
|
fReq.SetIgnoreOccluders(true);
|
||
|
fReq.RequestAck(GetKey());
|
||
|
|
||
|
hsMatrix44 w2c, c2w;
|
||
|
if (fCamera)
|
||
|
{
|
||
|
w2c.MakeCamera(&fCamera->GetTargetPos(), &fCamera->GetTargetPOA(), &hsVector3(0.f, 0.f, 1.f));
|
||
|
w2c.GetInverse(&c2w);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!fRootNode)
|
||
|
return;
|
||
|
|
||
|
// Could be optimized, but the matrix construction work here seems cheap relative to the cost
|
||
|
// of rerendering all this stuff to a separate target, so I doubt we'd notice.
|
||
|
hsMatrix44 invert;
|
||
|
invert.MakeScaleMat(&(hsVector3(1.f, 1.f, -1.f)));
|
||
|
w2c = pipe->GetWorldToCamera();
|
||
|
c2w = pipe->GetCameraToWorld();
|
||
|
|
||
|
w2c = w2c * fRootNode->GetLocalToWorld() * invert * fRootNode->GetWorldToLocal();
|
||
|
c2w = fRootNode->GetWorldToLocal() * invert * fRootNode->GetLocalToWorld() * c2w;
|
||
|
}
|
||
|
fReq.SetCameraTransform(w2c, c2w);
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::ISubmitRenderRequest(plPipeline *pipe)
|
||
|
{
|
||
|
ISetupRenderRequest(pipe);
|
||
|
fReqMsg->SendAndKeep();
|
||
|
fOutStanding++;
|
||
|
fLastRefresh = hsTimer::GetSysSeconds();
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::ICheckForRefresh(double t, plPipeline *pipe)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
hsBool useRefl = (fFlags & kReflectionMask) == kReflectionMask;
|
||
|
if (!fCamera)
|
||
|
{
|
||
|
if ((useRefl && fMatLayers[0]->GetTexture() != this) || (!useRefl && fMatLayers[0]->GetTexture() != fDisableTexture))
|
||
|
IPrepTextureLayers();
|
||
|
}
|
||
|
|
||
|
// So no one's using us, eh? Hitting this condition is likely a bug,
|
||
|
// but an assert every frame would be annoying. We'll notice when
|
||
|
// the render target never updates.
|
||
|
if (fTargetNodes.GetCount() == 0)
|
||
|
return;
|
||
|
|
||
|
// If dynamic planar reflections are disabled and we're using our substitute
|
||
|
// texture, don't update. Otherwise, this particular reflection is forced to
|
||
|
// always display.
|
||
|
if (!useRefl && fDisableTexture)
|
||
|
return;
|
||
|
|
||
|
hsBool inView = false;
|
||
|
for (i = 0; i < fTargetNodes.GetCount(); i++)
|
||
|
{
|
||
|
if (pipe->TestVisibleWorld(fTargetNodes[i]))
|
||
|
{
|
||
|
inView = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!inView)
|
||
|
return;
|
||
|
|
||
|
if( fLastRefresh <= 0 )
|
||
|
{
|
||
|
ISubmitRenderRequest(pipe);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( fRefreshRate <= 0 )
|
||
|
return;
|
||
|
|
||
|
#ifndef PLASMA_EXTERNAL_RELEASE
|
||
|
if (pipe->IsDebugFlagSet(plPipeDbg::kFlagNVPerfHUD) && hsTimer::GetDelSysSeconds() == 0)
|
||
|
{
|
||
|
ISubmitRenderRequest(pipe);
|
||
|
}
|
||
|
#endif // PLASMA_EXTERNAL_RELEASE
|
||
|
|
||
|
if (t > fLastRefresh + fRefreshRate)
|
||
|
{
|
||
|
ISubmitRenderRequest(pipe);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hsBool plDynamicCamMap::INeedReRender()
|
||
|
{
|
||
|
fOutStanding = 0;
|
||
|
fLastRefresh = 0;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
hsBool plDynamicCamMap::MsgReceive(plMessage* msg)
|
||
|
{
|
||
|
plRenderRequestAck* ack = plRenderRequestAck::ConvertNoRef(msg);
|
||
|
if( ack )
|
||
|
{
|
||
|
fOutStanding--;
|
||
|
return true;
|
||
|
}
|
||
|
plRenderMsg* rendMsg = plRenderMsg::ConvertNoRef(msg);
|
||
|
if( rendMsg )
|
||
|
{
|
||
|
if( fOutStanding )
|
||
|
INeedReRender();
|
||
|
|
||
|
ICheckForRefresh(hsTimer::GetSysSeconds(), rendMsg->Pipeline());
|
||
|
return true;
|
||
|
}
|
||
|
if( plPipeRTMakeMsg::ConvertNoRef(msg) )
|
||
|
{
|
||
|
INeedReRender();
|
||
|
plRenderTarget::MsgReceive(msg);
|
||
|
return true;
|
||
|
}
|
||
|
plAgeLoadedMsg* ageLoaded = plAgeLoadedMsg::ConvertNoRef(msg);
|
||
|
if( ageLoaded && ageLoaded->fLoaded )
|
||
|
return INeedReRender();
|
||
|
|
||
|
if( plInitialAgeStateLoadedMsg::ConvertNoRef(msg) )
|
||
|
return INeedReRender();
|
||
|
|
||
|
plDynamicEnvMapMsg* cmd = plDynamicEnvMapMsg::ConvertNoRef(msg);
|
||
|
if( cmd )
|
||
|
{
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetFogStart )
|
||
|
fFogStart = cmd->fFogStart;
|
||
|
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetColor )
|
||
|
fColor = cmd->fColor;
|
||
|
|
||
|
if( cmd->fCmd & plDynamicEnvMapMsg::kSetRefresh )
|
||
|
SetRefreshRate(cmd->fRefresh);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
plRefMsg* refMsg = plRefMsg::ConvertNoRef(msg);
|
||
|
if( refMsg )
|
||
|
{
|
||
|
if( IOnRefMsg(refMsg) )
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return plRenderTarget::MsgReceive(msg);
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::IPrepTextureLayers()
|
||
|
{
|
||
|
if (fDisableTexture)
|
||
|
{
|
||
|
int i;
|
||
|
for (i = 0; i < fMatLayers.GetCount(); i++)
|
||
|
{
|
||
|
if ((fFlags & kReflectionMask) == kReflectionMask)
|
||
|
{
|
||
|
fMatLayers[i]->SetUVWSrc(plLayerInterface::kUVWPosition);
|
||
|
fMatLayers[i]->SetMiscFlags(hsGMatState::kMiscCam2Screen | hsGMatState::kMiscPerspProjection);
|
||
|
hsgResMgr::ResMgr()->SendRef(GetKey(), TRACKED_NEW plGenRefMsg(fMatLayers[i]->GetKey(), plRefMsg::kOnRequest, 0, plLayRefMsg::kTexture), plRefFlags::kActiveRef);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fMatLayers[i]->SetUVWSrc(0);
|
||
|
fMatLayers[i]->SetMiscFlags(0);
|
||
|
hsgResMgr::ResMgr()->SendRef(fDisableTexture->GetKey(), TRACKED_NEW plGenRefMsg(fMatLayers[i]->GetKey(), plRefMsg::kOnRequest, 0, plLayRefMsg::kTexture), plRefFlags::kActiveRef);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hsBool plDynamicCamMap::IOnRefMsg(plRefMsg* refMsg)
|
||
|
{
|
||
|
plGenRefMsg* genRefMsg = plGenRefMsg::ConvertNoRef(refMsg);
|
||
|
|
||
|
if (genRefMsg)
|
||
|
{
|
||
|
if (genRefMsg->fType == kRefVisSet)
|
||
|
{
|
||
|
plVisRegion* reg = plVisRegion::ConvertNoRef(refMsg->GetRef());
|
||
|
if (reg)
|
||
|
{
|
||
|
int idx = fVisRegions.Find(reg);
|
||
|
if ((refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace)) && fVisRegions.kMissingIndex == idx)
|
||
|
{
|
||
|
fVisRegions.Append(reg);
|
||
|
fVisSet.SetBit(reg->GetIndex());
|
||
|
}
|
||
|
else if (!(refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace)) && fVisRegions.kMissingIndex != idx)
|
||
|
{
|
||
|
fVisRegions.Remove(idx);
|
||
|
fVisSet.ClearBit(reg->GetIndex());
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else if (genRefMsg->fType == kRefCamera)
|
||
|
{
|
||
|
plCameraModifier1 *cam = plCameraModifier1::ConvertNoRef(refMsg->GetRef());
|
||
|
if (cam)
|
||
|
{
|
||
|
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
|
||
|
fCamera = cam;
|
||
|
else
|
||
|
fCamera = nil;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else if (genRefMsg->fType == kRefRootNode)
|
||
|
{
|
||
|
plSceneObject *so = plSceneObject::ConvertNoRef(refMsg->GetRef());
|
||
|
if (so)
|
||
|
{
|
||
|
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
|
||
|
fRootNode = so;
|
||
|
else
|
||
|
fRootNode = nil;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else if (genRefMsg->fType == kRefTargetNode)
|
||
|
{
|
||
|
plSceneObject *so = plSceneObject::ConvertNoRef(refMsg->GetRef());
|
||
|
if (so)
|
||
|
{
|
||
|
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
|
||
|
{
|
||
|
if (fTargetNodes.Find(so) == fTargetNodes.kMissingIndex)
|
||
|
fTargetNodes.Append(so);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fTargetNodes.RemoveItem(so);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else if (genRefMsg->fType == kRefDisableTexture)
|
||
|
{
|
||
|
plBitmap *bitmap = plBitmap::ConvertNoRef(refMsg->GetRef());
|
||
|
if (bitmap)
|
||
|
{
|
||
|
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
|
||
|
fDisableTexture = bitmap;
|
||
|
else
|
||
|
fDisableTexture = nil;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else if (genRefMsg->fType == kRefMatLayer)
|
||
|
{
|
||
|
plLayer *lay = plLayer::ConvertNoRef(refMsg->GetRef());
|
||
|
if (lay)
|
||
|
{
|
||
|
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
|
||
|
{
|
||
|
if (fMatLayers.Find(lay) == fMatLayers.kMissingIndex)
|
||
|
fMatLayers.Append(lay);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fMatLayers.RemoveItem(lay);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::SetIncludeCharacters(hsBool b)
|
||
|
{
|
||
|
fIncCharacters = b;
|
||
|
if( b )
|
||
|
fVisSet.SetBit(plVisMgr::kCharacter);
|
||
|
else
|
||
|
fVisSet.ClearBit(plVisMgr::kCharacter);
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::AddVisRegion(plVisRegion* reg)
|
||
|
{
|
||
|
hsgResMgr::ResMgr()->AddViaNotify( reg->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plGenRefMsg::kOnReplace, -1, kRefVisSet ), plRefFlags::kActiveRef );
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::SetEnabled(hsBool enable)
|
||
|
{
|
||
|
if (enable)
|
||
|
fFlags |= kReflectionEnabled;
|
||
|
else
|
||
|
fFlags &= ~kReflectionEnabled;
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::SetCapable(hsBool capable)
|
||
|
{
|
||
|
if (capable)
|
||
|
fFlags |= kReflectionCapable;
|
||
|
else
|
||
|
fFlags &= ~kReflectionCapable;
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::Read(hsStream* s, hsResMgr* mgr)
|
||
|
{
|
||
|
hsKeyedObject::Read(s, mgr);
|
||
|
plRenderTarget::Read(s);
|
||
|
|
||
|
fHither = s->ReadSwapScalar();
|
||
|
fYon = s->ReadSwapScalar();
|
||
|
fFogStart = s->ReadSwapScalar();
|
||
|
fColor.Read(s);
|
||
|
|
||
|
fRefreshRate = s->ReadSwapScalar();
|
||
|
fIncCharacters = s->ReadBool();
|
||
|
SetIncludeCharacters(fIncCharacters);
|
||
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefCamera), plRefFlags::kPassiveRef);
|
||
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefRootNode), plRefFlags::kActiveRef);
|
||
|
|
||
|
int numTargs = s->ReadByte();
|
||
|
int i;
|
||
|
for (i = 0; i < numTargs; i++)
|
||
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, i, kRefTargetNode), plRefFlags::kPassiveRef);
|
||
|
|
||
|
int nVis = s->ReadSwap32();
|
||
|
for( i = 0; i < nVis; i++ )
|
||
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefVisSet), plRefFlags::kActiveRef);
|
||
|
|
||
|
nVis = s->ReadSwap32();
|
||
|
for( i = 0; i < nVis; i++)
|
||
|
{
|
||
|
char *name = s->ReadSafeString();
|
||
|
plKey key = plKeyFinder::Instance().StupidSearch(nil, nil, plVisRegion::Index(), name);
|
||
|
delete[] name;
|
||
|
if (key)
|
||
|
hsgResMgr::ResMgr()->AddViaNotify(key, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefVisSet), plRefFlags::kActiveRef);
|
||
|
}
|
||
|
|
||
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefDisableTexture), plRefFlags::kActiveRef);
|
||
|
|
||
|
UInt8 numLayers = s->ReadByte();
|
||
|
for (i = 0; i < numLayers; i++)
|
||
|
{
|
||
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefMatLayer), plRefFlags::kPassiveRef);
|
||
|
}
|
||
|
|
||
|
Init();
|
||
|
}
|
||
|
|
||
|
void plDynamicCamMap::Write(hsStream* s, hsResMgr* mgr)
|
||
|
{
|
||
|
hsKeyedObject::Write(s, mgr);
|
||
|
plRenderTarget::Write(s);
|
||
|
|
||
|
s->WriteSwapScalar(fHither);
|
||
|
s->WriteSwapScalar(fYon);
|
||
|
s->WriteSwapScalar(fFogStart);
|
||
|
fColor.Write(s);
|
||
|
|
||
|
s->WriteSwapScalar(fRefreshRate);
|
||
|
s->WriteByte(fIncCharacters);
|
||
|
mgr->WriteKey(s, (fCamera ? fCamera->GetKey() : nil));
|
||
|
mgr->WriteKey(s, (fRootNode ? fRootNode->GetKey() : nil));
|
||
|
|
||
|
s->WriteByte(fTargetNodes.GetCount());
|
||
|
int i;
|
||
|
for (i = 0; i < fTargetNodes.GetCount(); i++)
|
||
|
mgr->WriteKey(s, fTargetNodes[i]);
|
||
|
|
||
|
s->WriteSwap32(fVisRegions.GetCount());
|
||
|
for( i = 0; i < fVisRegions.GetCount(); i++ )
|
||
|
mgr->WriteKey(s, fVisRegions[i]);
|
||
|
|
||
|
s->WriteSwap32(fVisRegionNames.Count());
|
||
|
for( i = 0; i < fVisRegionNames.Count(); i++)
|
||
|
{
|
||
|
s->WriteSafeString(fVisRegionNames[i]);
|
||
|
}
|
||
|
|
||
|
mgr->WriteKey(s, fDisableTexture ? fDisableTexture->GetKey() : nil);
|
||
|
|
||
|
s->WriteByte(fMatLayers.GetCount());
|
||
|
for (i = 0; i < fMatLayers.GetCount(); i++)
|
||
|
{
|
||
|
mgr->WriteKey(s, fMatLayers[i]->GetKey());
|
||
|
}
|
||
|
}
|