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.
968 lines
28 KiB
968 lines
28 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
|
|
#include "hsTypes.h" |
|
#include "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_t width, uint16_t height, uint8_t bitDepth, uint8_t zDepth, uint8_t 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(float f) |
|
{ |
|
fHither = f; |
|
} |
|
|
|
void plDynamicEnvMap::SetYon(float f) |
|
{ |
|
fYon = f; |
|
} |
|
|
|
void plDynamicEnvMap::SetFogStart(float f) |
|
{ |
|
fFogStart = f; |
|
} |
|
|
|
void plDynamicEnvMap::SetColor(const hsColorRGBA& col) |
|
{ |
|
fColor = col; |
|
} |
|
|
|
void plDynamicEnvMap::SetRefreshRate(float secs) |
|
{ |
|
fRefreshRate = secs / 6.f; |
|
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey()); |
|
} |
|
|
|
void plDynamicEnvMap::ISetupRenderRequests() |
|
{ |
|
uint32_t 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_t sz = plCubicRenderTarget::Read(s); |
|
|
|
fPos.Read(s); |
|
fHither = s->ReadLEScalar(); |
|
fYon = s->ReadLEScalar(); |
|
fFogStart = s->ReadLEScalar(); |
|
fColor.Read(s); |
|
|
|
fRefreshRate = s->ReadLEScalar(); |
|
|
|
SetPosition(fPos); |
|
|
|
sz += sizeof(fPos) + sizeof(fHither) + sizeof(fYon) + sizeof(fFogStart) + sizeof(fColor) + sizeof(fRefreshRate); |
|
|
|
fIncCharacters = s->ReadByte(); |
|
SetIncludeCharacters(fIncCharacters); |
|
int nVis = s->ReadLE32(); |
|
int i; |
|
for( i = 0; i < nVis; i++ ) |
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefVisSet), plRefFlags::kActiveRef); |
|
|
|
nVis = s->ReadLE32(); |
|
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_t sz = plCubicRenderTarget::Write(s); |
|
|
|
fPos.Write(s); |
|
s->WriteLEScalar(fHither); |
|
s->WriteLEScalar(fYon); |
|
s->WriteLEScalar(fFogStart); |
|
fColor.Write(s); |
|
|
|
s->WriteLEScalar(fRefreshRate); |
|
|
|
sz += sizeof(fPos) + sizeof(fHither) + sizeof(fYon) + sizeof(fFogStart) + sizeof(fColor) + sizeof(fRefreshRate); |
|
|
|
s->WriteByte(fIncCharacters); |
|
s->WriteLE32(fVisRegions.GetCount()); |
|
int i; |
|
for( i = 0; i < fVisRegions.GetCount(); i++ ) |
|
mgr->WriteKey(s, fVisRegions[i]); |
|
|
|
s->WriteLE32(fVisRegionNames.Count()); |
|
for( i = 0; i < fVisRegionNames.Count(); i++) |
|
{ |
|
s->WriteSafeString(fVisRegionNames[i]); |
|
} |
|
|
|
mgr->WriteKey(s, fRootNode); |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
uint8_t 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_t width, uint16_t height, uint8_t bitDepth, uint8_t zDepth, uint8_t 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(float 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->ReadLEScalar(); |
|
fYon = s->ReadLEScalar(); |
|
fFogStart = s->ReadLEScalar(); |
|
fColor.Read(s); |
|
|
|
fRefreshRate = s->ReadLEScalar(); |
|
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->ReadLE32(); |
|
for( i = 0; i < nVis; i++ ) |
|
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefVisSet), plRefFlags::kActiveRef); |
|
|
|
nVis = s->ReadLE32(); |
|
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_t 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->WriteLEScalar(fHither); |
|
s->WriteLEScalar(fYon); |
|
s->WriteLEScalar(fFogStart); |
|
fColor.Write(s); |
|
|
|
s->WriteLEScalar(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->WriteLE32(fVisRegions.GetCount()); |
|
for( i = 0; i < fVisRegions.GetCount(); i++ ) |
|
mgr->WriteKey(s, fVisRegions[i]); |
|
|
|
s->WriteLE32(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()); |
|
} |
|
}
|
|
|