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.
1270 lines
30 KiB
1270 lines
30 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 "hsGEnviron.h" |
|
#include "../plSurface/hsGLayer.h" |
|
#include "../plSurface/hsGMaterial.h" |
|
//#include "hsG3DDevice.h" |
|
//#include "plCamera.h" |
|
#include "hsFogControl.h" |
|
#include "../plGRenderProcs/hsGRenderProcs.h" |
|
#if 0 // SCENENODE_DEFER |
|
#include "hsScene.h" |
|
#endif // SCENENODE_DEFER |
|
#include "../plResMgr/hsResMgr.h" |
|
#include "hsGStatGather3.h" |
|
#include "../plResMgr/plKey.h" |
|
#include "hsTimer.h" |
|
#include "../plResMgr/plRefMsg.h" |
|
|
|
const UInt16 hsGEnvironment::kSaveMagicNumber = 0x1f7a; |
|
const UInt16 hsGEnvironment::kSaveVersion = 2; |
|
|
|
hsScalar hsGEnvironment::fYonScale = 1.f; |
|
|
|
hsGEnvironment::hsGEnvironment() |
|
: fFlags(0), |
|
fValidScale(1.f), |
|
fMap(nil), |
|
fPos(0,0,0), |
|
fRadius(0), |
|
fFogDistance(0), |
|
fFogDepth(0), |
|
fCurrentDepth(0), |
|
fFogDensity(0), |
|
fDevCache(nil), |
|
fYon(0), |
|
fFogControl(nil) |
|
{ |
|
fFogColor.SetValue(hsColorRGBA().Set(0, 0, 0, hsScalar1)); |
|
SetFogColor(fFogColor.GetValue()); |
|
*fMapName = 0; |
|
} |
|
|
|
hsGEnvironment::~hsGEnvironment() |
|
{ |
|
hsRefCnt_SafeUnRef(fMap); |
|
hsRefCnt_SafeUnRef(fDevCache); |
|
|
|
hsRefCnt_SafeUnRef(fFogControl); |
|
|
|
Int32 i; |
|
for (i=0; i<fFogStateStack.GetCount(); i++) |
|
delete fFogStateStack[i]; |
|
|
|
for( i = 0; i < GetNumRenderProcs(); i++ ) |
|
hsRefCnt_SafeUnRef(GetRenderProc(i)); |
|
|
|
} |
|
|
|
|
|
#if 0 // SCENENODE_DEFER |
|
hsBool32 hsGEnvironment::AddNode(hsSceneNode *node) |
|
{ |
|
return AddNodeKey(node->GetKey()); |
|
} |
|
#endif // SCENENODE_DEFER |
|
|
|
hsBool32 hsGEnvironment::AddNodeKey(plKey *key) |
|
{ |
|
Int32 i; |
|
for (i = 0; i < GetNumNodes(); i++) |
|
{ |
|
if (GetNodeKey(i) == key) // nothing to do |
|
return false; |
|
} |
|
fNodeKeys.Append(key); |
|
|
|
hsSceneNode *node = (hsSceneNode *)(key->GetObjectPtr()); |
|
#if 0 // SCENENODE_DEFER |
|
if (node) |
|
{ |
|
if (!(GetFlags() & hsGEnvironment::kFarOut)) |
|
{ |
|
node->SetEnvironment(this); |
|
} |
|
else |
|
{ |
|
node->SetFarEnvironment(this); |
|
} |
|
} |
|
#endif // SCENENODE_DEFER |
|
|
|
return true; |
|
} |
|
|
|
hsSceneNode* hsGEnvironment::GetNode(Int32 i) |
|
{ |
|
return (hsSceneNode*)(fNodeKeys[i]->GetObjectPtr()); |
|
} |
|
|
|
void hsGEnvironment::FogState::ValidateEnv(hsGEnvironment* env) |
|
{ |
|
char* msg = "hsGEnvironment not in reset state."; |
|
if( fFlags & kYonSet ) |
|
{ |
|
hsAssert(env->GetFlags() & hsGEnvironment::kYonSet, msg); |
|
hsAssert(fYon == env->YonState(), msg); |
|
} |
|
|
|
if( fFlags & kDistanceSet ) |
|
{ |
|
hsAssert(env->GetFlags() & hsGEnvironment::kFogDistanceSet, msg); |
|
hsAssert(fDistance == env->FogDistanceState(), msg); |
|
} |
|
|
|
if( fFlags & kDepthSet ) |
|
{ |
|
hsAssert(env->GetFlags() & hsGEnvironment::kFogDepthSet, msg); |
|
hsAssert(fDepth == env->FogDepthState(), msg); |
|
} |
|
|
|
if( fFlags & kDensitySet ) |
|
{ |
|
hsAssert(env->GetFlags() & hsGEnvironment::kFogDensitySet, msg); |
|
hsAssert(fDensity == env->FogDensityState(), msg); |
|
} |
|
|
|
if( fFlags & kColorSet ) |
|
{ |
|
hsAssert(env->GetFlags() & hsGEnvironment::kFogColorSet, msg); |
|
hsAssert(fColor == env->FogColorState(), msg); |
|
} |
|
|
|
if( fFlags & kClearSet ) |
|
{ |
|
hsAssert(env->GetFlags() & hsGEnvironment::kClearColorSet, msg); |
|
hsAssert(fClear == env->ClearColorState(), msg); |
|
} |
|
|
|
UInt32 envFogType = env->GetFlags() & hsGEnvironment::kFogTypeMask; |
|
switch( fFlags & kTypeMask ) |
|
{ |
|
case kLinear: |
|
hsAssert(envFogType == hsGEnvironment::kFogLinear, msg); |
|
break; |
|
case kExp: |
|
hsAssert(envFogType == hsGEnvironment::kFogExp, msg); |
|
break; |
|
case kExp2: |
|
hsAssert(envFogType == hsGEnvironment::kFogExp2, msg); |
|
break; |
|
default: |
|
hsAssert(false, msg); |
|
break; |
|
} |
|
} |
|
|
|
void hsGEnvironment::FogState::SetFromEnv(hsGEnvironment* env) |
|
{ |
|
if( env->GetFlags() & hsGEnvironment::kYonSet ) |
|
{ |
|
fYon = env->YonState(); |
|
fFlags |= kYonSet; |
|
} |
|
if( env->GetFlags() & hsGEnvironment::kFogDistanceSet ) |
|
{ |
|
fDistance = env->FogDistanceState(); |
|
fFlags |= kDistanceSet; |
|
} |
|
if( env->GetFlags() & hsGEnvironment::kFogDepthSet ) |
|
{ |
|
fDepth = env->FogDepthState(); |
|
fFlags |= kDepthSet; |
|
} |
|
if( env->GetFlags() & hsGEnvironment::kFogDensitySet ) |
|
{ |
|
fDensity = env->FogDensityState(); |
|
fFlags |= kDensitySet; |
|
} |
|
if( env->GetFlags() & hsGEnvironment::kFogColorSet ) |
|
{ |
|
fColor = env->FogColorState(); |
|
fFlags |= kColorSet; |
|
} |
|
if( env->GetFlags() & hsGEnvironment::kClearColorSet ) |
|
{ |
|
fClear = env->ClearColorState(); |
|
fFlags |= kClearSet; |
|
} |
|
|
|
fFlags &= ~kTypeMask; |
|
switch( env->GetFlags() & hsGEnvironment::kFogTypeMask ) |
|
{ |
|
case hsGEnvironment::kFogLinear: |
|
fFlags |= kLinear; |
|
break; |
|
case hsGEnvironment::kFogExp: |
|
fFlags |= kExp; |
|
break; |
|
case hsGEnvironment::kFogExp2: |
|
fFlags |= kExp2; |
|
break; |
|
default: |
|
hsAssert(false, "Fog type should at least default at load"); |
|
break; |
|
} |
|
} |
|
|
|
void hsGEnvironment::FogState::SetToEnv(hsGEnvironment* env) |
|
{ |
|
if( fFlags & kYonSet ) |
|
env->SetYon(fYon); |
|
else |
|
env->UnSetYon(); |
|
|
|
if( fFlags & kDistanceSet ) |
|
env->SetFogDistance(fDistance); |
|
else |
|
env->UnSetFogDistance(); |
|
|
|
if( fFlags & kDepthSet ) |
|
{ |
|
env->SetFogDepth(fDepth); |
|
env->SetCurrentDepth(fDepth.GetValue()); |
|
} |
|
else |
|
env->UnSetFogDepth(); |
|
|
|
if( fFlags & kDensitySet ) |
|
env->SetFogDensity(fDensity); |
|
else |
|
env->UnSetFogDensity(); |
|
|
|
if( fFlags & kColorSet ) |
|
env->SetFogColor(fColor); |
|
else |
|
env->UnSetFogColor(); |
|
|
|
if( fFlags & kClearSet ) |
|
env->SetClearColor(fClear); |
|
else |
|
env->UnSetClearColor(); |
|
|
|
switch( fFlags & kTypeMask ) |
|
{ |
|
case kLinear: |
|
env->SetFogType(hsGEnvironment::kFogLinear); |
|
break; |
|
case kExp: |
|
env->SetFogType(hsGEnvironment::kFogExp); |
|
break; |
|
case kExp2: |
|
env->SetFogType(hsGEnvironment::kFogExp2); |
|
break; |
|
default: |
|
hsAssert(false, "Setting lack of fog type"); |
|
env->SetFogType(0); |
|
break; |
|
} |
|
} |
|
|
|
const UInt16 hsGEnvironment::FogState::kSaveMagicNumber = 0x7385; |
|
const UInt16 hsGEnvironment::FogState::kSaveVersion = 1; |
|
|
|
void hsGEnvironment::FogState::Save(hsStream *stream, hsResMgr* mgr) |
|
{ |
|
stream->WriteSwap16(kSaveMagicNumber); |
|
stream->WriteSwap16(kSaveVersion); |
|
|
|
hsScalar currSecs = hsTimer::GetSysSeconds(); |
|
stream->WriteSwap32(fFlags); |
|
fColor.Write(stream, currSecs); |
|
fClear.Write(stream, currSecs); |
|
fDistance.WriteScalar(stream, currSecs); |
|
fDensity.WriteScalar(stream, currSecs); |
|
fDepth.WriteScalar(stream, currSecs); |
|
fYon.WriteScalar(stream, currSecs); |
|
} |
|
|
|
void hsGEnvironment::FogState::Load(hsStream *stream, hsResMgr* mgr) |
|
{ |
|
UInt16 magic = stream->ReadSwap16(); |
|
hsAssert(magic == kSaveMagicNumber, "Bad magic number in hsGEnvironment::FogState on load."); |
|
|
|
UInt16 version = stream->ReadSwap16(); |
|
hsAssert(version == kSaveVersion, "Bad version in hsGEnvironment::FogState on load."); |
|
|
|
hsScalar currSecs = hsTimer::GetSysSeconds(); |
|
fFlags = stream->ReadSwap32(); |
|
fColor.Read(stream, currSecs); |
|
fClear.Read(stream, currSecs); |
|
fDistance.ReadScalar(stream, currSecs); |
|
fDensity.ReadScalar(stream, currSecs); |
|
fDepth.ReadScalar(stream, currSecs); |
|
fYon.ReadScalar(stream, currSecs); |
|
} |
|
|
|
|
|
void hsGEnvironment::SetResetState() |
|
{ |
|
fResetState.SetFromEnv(this); |
|
} |
|
|
|
void hsGEnvironment::Reset() |
|
{ |
|
fResetState.SetToEnv(this); |
|
|
|
Int32 i; |
|
for (i=0; i<fFogStateStack.GetCount(); i++) |
|
delete fFogStateStack[i]; |
|
fFogStateStack.Reset(); |
|
} |
|
|
|
void hsGEnvironment::ValidateInResetState() |
|
{ |
|
fResetState.ValidateEnv(this); |
|
|
|
hsAssert(fFogStateStack.GetCount() == 0, "Bad fog state stack."); |
|
} |
|
|
|
void hsGEnvironment::Save(hsStream *stream, hsResMgr* mgr) |
|
{ |
|
hsKeyedObject::Save(stream, mgr); |
|
|
|
stream->WriteSwap16(kSaveMagicNumber); |
|
stream->WriteSwap16(kSaveVersion); |
|
|
|
stream->WriteSwap32(fFlags); |
|
|
|
if( fFlags & hsGEnvironment::kCenterSet ) |
|
fPos.Write(stream); |
|
|
|
if( fFlags & hsGEnvironment::kRadiusSet ) |
|
stream->WriteSwapScalar(fRadius); |
|
|
|
FogState tempState; |
|
tempState.SetFromEnv(this); |
|
|
|
tempState.Save(stream, mgr); |
|
fResetState.Save(stream, mgr); |
|
|
|
UInt32 numFogStates = fFogStateStack.GetCount(); |
|
stream->WriteSwap32(numFogStates); |
|
for (UInt32 i = 0; i < numFogStates; i++) |
|
{ |
|
fFogStateStack[i]->Save(stream, mgr); |
|
} |
|
} |
|
|
|
void hsGEnvironment::Load(hsStream *stream, hsResMgr* mgr) |
|
{ |
|
// Clear old data |
|
UInt32 i; |
|
for (i=0; i<fFogStateStack.GetCount(); i++) |
|
delete fFogStateStack[i]; |
|
fFogStateStack.Reset(); |
|
|
|
// Load |
|
hsKeyedObject::Load(stream, mgr); |
|
|
|
UInt16 magic = stream->ReadSwap16(); |
|
hsAssert(magic == kSaveMagicNumber, "Bad magic number in hsGEnvironment on load."); |
|
|
|
UInt16 version = stream->ReadSwap16(); |
|
hsAssert(version == kSaveVersion, "Bad version in hsGEnvironment on load."); |
|
|
|
fFlags = stream->ReadSwap32(); |
|
|
|
if( fFlags & hsGEnvironment::kCenterSet ) |
|
fPos.Read(stream); |
|
|
|
if( fFlags & hsGEnvironment::kRadiusSet ) |
|
fRadius = stream->ReadSwapScalar(); |
|
|
|
FogState tempState; |
|
tempState.Load(stream, mgr); |
|
tempState.SetToEnv(this); |
|
fResetState.Load(stream, mgr); |
|
|
|
UInt32 numFogStates = stream->ReadSwap32(); |
|
for (i = 0; i < numFogStates; i++) |
|
{ |
|
FogState *newFogState = new FogState; |
|
newFogState->Load(stream, mgr); |
|
fFogStateStack.Append(newFogState); |
|
} |
|
} |
|
|
|
void hsGEnvironment::Update(hsScalar s, const hsPoint3& vPos) |
|
{ |
|
if( fFlags & kFogDepthSet ) |
|
fFogDepth.Update(s); |
|
if( fFlags & kFogDensitySet ) |
|
fFogDensity.Update(s); |
|
if( fFlags & kFogColorSet ) |
|
fFogColor.Update(s); |
|
if( fFlags & kClearColorSet ) |
|
fClearColor.Update(s); |
|
if( fFlags & kYonSet ) |
|
fYon.Update(s); |
|
if( fFlags & kMapSet ) |
|
{ |
|
hsGStatGather3::UpdateMaterialBegin(); |
|
fMap->Update(s); |
|
hsGStatGather3::UpdateMaterialEnd(); |
|
|
|
if( fFlags & kClearColorAmbient ) |
|
SetClearColor(fMap->GetLayer(0)->GetAmbientColor()); |
|
|
|
if( fFlags & kFogColorAmbient ) |
|
SetFogColor(fMap->GetLayer(0)->GetAmbientColor()); |
|
else |
|
if( fFlags & kFogColorDiffuse ) |
|
SetFogColor(fMap->GetLayer(0)->GetColor()); |
|
} |
|
|
|
if( fFlags & kFogDistanceSet ) |
|
{ |
|
fFogDistance.Update(s); |
|
|
|
|
|
hsVector3 del(&vPos, &fPos); |
|
hsScalar dist = del.Magnitude(); |
|
|
|
hsScalar yon = hsMaximum(dist, fFogDistance.GetValue()); |
|
|
|
SetYon(yon); |
|
|
|
hsScalar depth = fFogDistance.GetValue(); |
|
if( fFlags & kFogDepthSet ) |
|
depth *= fFogDepth.GetValue(); |
|
|
|
depth += yon - dist; |
|
depth /= yon; |
|
|
|
if( depth > hsScalar1 ) |
|
depth = hsScalar1; |
|
|
|
fCurrentDepth = depth; |
|
fFlags |= kCurrentDepthSet; |
|
} |
|
else if( fFlags & kFogDepthSet ) |
|
{ |
|
fCurrentDepth = fFogDepth.GetValue(); |
|
fFlags |= kCurrentDepthSet; |
|
} |
|
else |
|
fFlags &= ~kCurrentDepthSet; |
|
|
|
if( fValidScale != fYonScale ) |
|
{ |
|
if( fDevCache ) |
|
fDevCache->Validate(false); |
|
fValidScale = fYonScale; |
|
} |
|
} |
|
|
|
void hsGEnvironment::SetTimedFogDistance(const hsScalar g, const hsScalar s) |
|
{ |
|
if( fFlags & kFogDistanceSet ) |
|
{ |
|
fFogDistance.Update(hsTimer::GetSysSeconds()); |
|
fFogDistance.SetGoal(g); |
|
fFogDistance.SetDuration(s); |
|
fFogDistance.StartClock(hsTimer::GetSysSeconds()); |
|
} |
|
else |
|
SetFogDistance(g); |
|
} |
|
|
|
void hsGEnvironment::SetTimedFogDepth(const hsScalar g, const hsScalar s) |
|
{ |
|
if( fFlags & kFogDepthSet ) |
|
{ |
|
fFogDepth.Update(hsTimer::GetSysSeconds()); |
|
fFogDepth.SetGoal(g); |
|
fFogDepth.SetDuration(s); |
|
fFogDepth.StartClock(hsTimer::GetSysSeconds()); |
|
} |
|
else |
|
SetFogDepth(g); |
|
} |
|
|
|
void hsGEnvironment::SetTimedFogDensity(const hsScalar g, const hsScalar s) |
|
{ |
|
if( fFlags & kFogDensitySet ) |
|
{ |
|
fFogDensity.Update(hsTimer::GetSysSeconds()); |
|
fFogDensity.SetGoal(g); |
|
fFogDensity.SetDuration(s); |
|
fFogDensity.StartClock(hsTimer::GetSysSeconds()); |
|
} |
|
else |
|
SetFogDensity(g); |
|
} |
|
|
|
void hsGEnvironment::SetTimedFogColor(const hsColorRGBA& g, const hsScalar s) |
|
{ |
|
if( fFlags & kFogColorSet ) |
|
{ |
|
fFogColor.Update(hsTimer::GetSysSeconds()); |
|
fFogColor.SetGoal(g); |
|
fFogColor.SetDuration(s); |
|
fFogColor.StartClock(hsTimer::GetSysSeconds()); |
|
} |
|
else |
|
SetFogColor(g); |
|
} |
|
|
|
void hsGEnvironment::SetTimedClearColor(const hsColorRGBA& g, const hsScalar s) |
|
{ |
|
if( fFlags & kClearColorSet ) |
|
{ |
|
fClearColor.Update(hsTimer::GetSysSeconds()); |
|
fClearColor.SetGoal(g); |
|
fClearColor.SetDuration(s); |
|
fClearColor.StartClock(hsTimer::GetSysSeconds()); |
|
} |
|
else |
|
SetClearColor(g); |
|
} |
|
|
|
void hsGEnvironment::SetTimedYon(const hsScalar g, const hsScalar s) |
|
{ |
|
if( fFlags & kYonSet ) |
|
{ |
|
fYon.Update(hsTimer::GetSysSeconds()); |
|
fYon.SetGoal(g); |
|
fYon.SetDuration(s); |
|
fYon.StartClock(hsTimer::GetSysSeconds()); |
|
} |
|
else |
|
SetYon(g); |
|
} |
|
|
|
void hsGEnvironment::SetMapName(const char *n) |
|
{ |
|
if( n ) |
|
{ |
|
hsAssert(strlen(n) < 255, "Environment name overflow"); |
|
fFlags |= kMapSet; |
|
strcpy(fMapName, n); |
|
} |
|
else |
|
{ |
|
fFlags &= ~kMapSet; |
|
*fMapName = 0; |
|
} |
|
} |
|
|
|
void hsGEnvironment::SetMap(hsGMaterial *m) |
|
{ |
|
fFlags |= kMapSet; |
|
hsRefCnt_SafeAssign(fMap, m); |
|
} |
|
|
|
void hsGEnvironment::SetCenter(const hsPoint3 &p) |
|
{ |
|
fFlags |= kCenterSet; fPos = p; |
|
} |
|
|
|
void hsGEnvironment::SetRadius(hsScalar r) |
|
{ |
|
fFlags |= kRadiusSet; |
|
fRadius = r; |
|
} |
|
|
|
void hsGEnvironment::SetFogDistance(hsScalar f) |
|
{ |
|
if( fDevCache &&( f != fFogDistance.GetValue()) ) |
|
fDevCache->Validate(false); |
|
fFlags |= kFogDistanceSet; |
|
fFogDistance.SetValue(f); |
|
} |
|
|
|
void hsGEnvironment::SetCurrentDepth(hsScalar f) |
|
{ |
|
if( fDevCache && (f != fCurrentDepth) ) |
|
fDevCache->Validate(false); |
|
fFlags |= kCurrentDepthSet; |
|
fCurrentDepth = f; |
|
} |
|
|
|
void hsGEnvironment::SetFogDepth(hsScalar f) |
|
{ |
|
if( fDevCache && (f != fFogDepth.GetValue()) ) |
|
fDevCache->Validate(false); |
|
fFlags |= kFogDepthSet; |
|
fFogDepth.SetValue(f); |
|
} |
|
|
|
void hsGEnvironment::SetFogDensity(hsScalar f) |
|
{ |
|
if( fDevCache && (f != fFogDensity.GetValue()) ) |
|
fDevCache->Validate(false); |
|
fFlags |= kFogDensitySet; |
|
fFogDensity.SetValue(f); |
|
} |
|
|
|
void hsGEnvironment::SetFogColor(const hsColorRGBA &c) |
|
{ |
|
if( fDevCache |
|
&& ( |
|
(c.r != fFogColor.GetValue().r) |
|
|| (c.g != fFogColor.GetValue().g) |
|
|| (c.b != fFogColor.GetValue().b) |
|
) ) |
|
fDevCache->Validate(false); |
|
fFlags |= kFogColorSet; |
|
fFogColor.SetValue(c); |
|
} |
|
|
|
void hsGEnvironment::SetClearColor(const hsColorRGBA &c) |
|
{ |
|
fFlags |= kClearColorSet; |
|
fClearColor.SetValue(c); |
|
} |
|
|
|
void hsGEnvironment::SetYon(hsScalar f) |
|
{ |
|
if( fDevCache && (f != fYon.GetValue()) ) |
|
fDevCache->Validate(false); |
|
fFlags |= kYonSet; |
|
fYon.SetValue(f); |
|
} |
|
|
|
void hsGEnvironment::SetFogDistance(const hsTimedValue<hsScalar>& f) |
|
{ |
|
if( fDevCache ) |
|
fDevCache->Validate(false); |
|
fFlags |= kFogDistanceSet; |
|
fFogDistance = f; |
|
} |
|
|
|
void hsGEnvironment::SetFogDepth(const hsTimedValue<hsScalar>& f) |
|
{ |
|
if( fDevCache ) |
|
fDevCache->Validate(false); |
|
fFlags |= kFogDepthSet; |
|
fFogDepth = f; |
|
} |
|
|
|
void hsGEnvironment::SetFogDensity(const hsTimedValue<hsScalar>& f) |
|
{ |
|
if( fDevCache ) |
|
fDevCache->Validate(false); |
|
fFlags |= kFogDensitySet; |
|
fFogDensity = f; |
|
} |
|
|
|
void hsGEnvironment::SetFogColor(const hsTimedValue<hsColorRGBA>& c) |
|
{ |
|
if( fDevCache ) |
|
fDevCache->Validate(false); |
|
fFlags |= kFogColorSet; |
|
fFogColor = c; |
|
} |
|
|
|
void hsGEnvironment::SetClearColor(const hsTimedValue<hsColorRGBA>& c) |
|
{ |
|
fFlags |= kClearColorSet; |
|
fClearColor = c; |
|
} |
|
|
|
void hsGEnvironment::SetYon(const hsTimedValue<hsScalar>& f) |
|
{ |
|
if( fDevCache ) |
|
fDevCache->Validate(false); |
|
fFlags |= kYonSet; |
|
fYon = f; |
|
} |
|
|
|
void hsGEnvironment::SetFogType(UInt32 t) |
|
{ |
|
fFlags &= ~kFogTypeMask; |
|
fFlags |= (t & kFogTypeMask); |
|
} |
|
|
|
void hsGEnvironment::SetFogColorAmbient(hsBool32 on) |
|
{ |
|
if( on ) |
|
{ |
|
fFlags &= ~kFogColorDiffuse; |
|
fFlags |= kFogColorAmbient; |
|
} |
|
else |
|
fFlags &= ~kFogColorAmbient; |
|
} |
|
|
|
void hsGEnvironment::SetFogColorDiffuse(hsBool32 on) |
|
{ |
|
if( on ) |
|
{ |
|
fFlags &= ~kFogColorAmbient; |
|
fFlags |= kFogColorDiffuse; |
|
} |
|
else |
|
fFlags &= ~kFogColorDiffuse; |
|
} |
|
|
|
void hsGEnvironment::SetClearColorAmbient(hsBool32 on) |
|
{ |
|
if( on ) |
|
fFlags |= kClearColorAmbient; |
|
else |
|
fFlags &= ~kClearColorAmbient; |
|
} |
|
|
|
void hsGEnvironment::SetOverride(hsBool32 on) |
|
{ |
|
if( on ) |
|
fFlags |= kOverride; |
|
else |
|
fFlags &= ~kOverride; |
|
} |
|
|
|
void hsGEnvironment::SetIsFar(hsBool32 on) |
|
{ |
|
if( on ) |
|
fFlags |= kFarOut; |
|
else |
|
fFlags &= ~kFarOut; |
|
} |
|
|
|
void hsGEnvironment::SetSortObjects(hsBool32 on) |
|
{ |
|
if( on ) |
|
fFlags |= kSortObjects; |
|
else |
|
fFlags &= ~kSortObjects; |
|
} |
|
|
|
void hsGEnvironment::SetHasFogControl(hsBool32 on) |
|
{ |
|
if( on ) |
|
fFlags |= kFogControl; |
|
else |
|
fFlags &= ~kFogControl; |
|
} |
|
|
|
void hsGEnvironment::SetFogControl(hsFogControl* fc) |
|
{ |
|
hsRefCnt_SafeAssign(fFogControl, fc); |
|
} |
|
|
|
void hsGEnvironment::SetDeviceCache(hsGDevEnvCache *p) |
|
{ |
|
hsRefCnt_SafeAssign(fDevCache, p); |
|
} |
|
|
|
hsGEnvironment *hsGEnvironment::Copy(hsGEnvironment *env) |
|
{ |
|
if( env->GetFlags() & kMapSet ) |
|
SetMap(env->GetMap()); |
|
else |
|
fFlags &= ~kMapSet; |
|
if( env->GetFlags() & kCenterSet ) |
|
SetCenter(env->GetCenter()); |
|
else |
|
fFlags &= ~kCenterSet; |
|
if( env->GetFlags() & kRadiusSet ) |
|
SetRadius(env->GetRadius()); |
|
else |
|
fFlags &= ~kRadiusSet; |
|
if( env->GetFlags() & kFogDepthSet ) |
|
SetFogDepth(env->GetFogDepth()); |
|
else |
|
fFlags &= ~kFogDepthSet; |
|
if( env->GetFlags() & kFogDensitySet ) |
|
SetFogDensity(env->GetFogDensity()); |
|
else |
|
fFlags &= ~kFogDensitySet; |
|
if( env->GetFlags() & kFogColorSet ) |
|
SetFogColor(env->GetFogColor()); |
|
else |
|
fFlags &= ~kFogColorSet; |
|
if( env->GetFlags() & kClearColorSet ) |
|
SetClearColor(env->GetClearColor()); |
|
else |
|
fFlags &= ~kClearColorSet; |
|
if( env->GetFlags() & kYonSet ) |
|
SetYon(env->GetUnscaledYon()); |
|
else |
|
fFlags &= ~kYonSet; |
|
|
|
if( env->GetFlags() & kCurrentDepthSet ) |
|
{ |
|
fCurrentDepth = env->GetCurrentDepth(); |
|
fFlags |= kCurrentDepthSet; |
|
} |
|
|
|
fFlags &= ~hsGEnvironment::kFogTypeMask; |
|
fFlags |= env->GetFlags() & hsGEnvironment::kFogTypeMask; |
|
|
|
SetOverride(env->GetOverride()); |
|
|
|
SetDeviceCache(env->GetDeviceCache()); |
|
|
|
if( env->GetFlags() & kCacheInvalid ) |
|
fFlags |= kCacheInvalid; |
|
else |
|
fFlags &= ~kCacheInvalid; |
|
|
|
int i; |
|
for( i = 0; i < env->GetNumRenderProcs(); i++ ) |
|
AddRenderProc(env->GetRenderProc(i)); |
|
|
|
return this; |
|
} |
|
|
|
void hsGEnvironment::MixEnvirons(hsGEnvironment *env, hsGEnvironment *def) |
|
{ |
|
if( env && (env->GetFlags() & kMapSet) ) |
|
{ |
|
SetMap(env->GetMap()); |
|
} |
|
else if( def && (def->GetFlags() & kMapSet) ) |
|
{ |
|
hsGMaterial *map = def->GetMap(); |
|
if( map ) |
|
{ |
|
SetMap(def->GetMap()); |
|
} |
|
else |
|
{ |
|
def->SetMapName(nil); |
|
hsRefCnt_SafeUnRef(fMap); |
|
fMap = nil; |
|
fFlags &= ~kMapSet; |
|
} |
|
} |
|
else |
|
{ |
|
hsRefCnt_SafeUnRef(fMap); |
|
fMap = nil; |
|
fFlags &= ~kMapSet; |
|
} |
|
if( env && (env->GetFlags() & kCenterSet) ) |
|
SetCenter(env->GetCenter()); |
|
else if( def &&(def->GetFlags() & kCenterSet) ) |
|
SetCenter(def->GetCenter()); |
|
else |
|
fFlags &= ~kCenterSet; |
|
if( env && (env->GetFlags() & kRadiusSet) ) |
|
SetRadius(env->GetRadius()); |
|
else if( def &&(def->GetFlags() & kRadiusSet) ) |
|
SetRadius(def->GetRadius()); |
|
else |
|
fFlags &= ~kRadiusSet; |
|
|
|
if( env && (env->GetFlags() & kFogDepthSet) ) |
|
SetFogDepth(env->GetFogDepth()); |
|
else if( def &&(def->GetFlags() & kFogDepthSet) ) |
|
SetFogDepth(def->GetFogDepth()); |
|
else |
|
fFlags &= ~kFogDepthSet; |
|
|
|
if( env &&(env->GetFlags() & kCurrentDepthSet) ) |
|
{ |
|
fCurrentDepth = env->GetCurrentDepth(); |
|
fFlags |= kCurrentDepthSet; |
|
} |
|
else |
|
if( def &&(def->GetFlags() & kCurrentDepthSet) ) |
|
{ |
|
fCurrentDepth = def->GetCurrentDepth(); |
|
fFlags |= kCurrentDepthSet; |
|
} |
|
else |
|
fFlags &= ~kCurrentDepthSet; |
|
|
|
fFlags &= ~kFogTypeMask; |
|
if( env && (env->GetFlags() & kFogTypeMask) ) |
|
fFlags |= env->GetFlags() & kFogTypeMask; |
|
else if( def && (def->GetFlags() & kFogTypeMask) ) |
|
fFlags |= def->GetFlags() & kFogTypeMask; |
|
else |
|
fFlags &= ~kFogTypeMask; |
|
|
|
if( env && (env->GetFlags() & kFogDensitySet) ) |
|
SetFogDensity(env->GetFogDensity()); |
|
else if( def &&(def->GetFlags() & kFogDensitySet) ) |
|
SetFogDensity(def->GetFogDensity()); |
|
else |
|
SetFogDensity(hsScalar1); |
|
|
|
if( env &&(env->GetFlags() & kFogColorSet) ) |
|
SetFogColor(env->GetFogColor()); |
|
else if( def &&(def->GetFlags() & kFogColorSet) ) |
|
SetFogColor(def->GetFogColor()); |
|
else |
|
{ |
|
hsColorRGBA col; |
|
col.r = col.g = col.b = col.a = 0; |
|
SetFogColor(col); |
|
} |
|
if( env &&(env->GetFlags() & kClearColorSet) ) |
|
SetClearColor(env->GetClearColor()); |
|
else if( def &&(def->GetFlags() & kClearColorSet) ) |
|
SetClearColor(def->GetClearColor()); |
|
else |
|
fFlags &= ~kClearColorSet; |
|
|
|
if( env && (env->GetFlags() & kYonSet) ) |
|
SetYon(env->GetUnscaledYon()); |
|
else if( def &&(def->GetFlags() & kYonSet) ) |
|
SetYon(def->GetUnscaledYon()); |
|
else |
|
fFlags &= ~kYonSet; |
|
|
|
if( env && (env->GetOverride()) ) |
|
SetOverride(true); |
|
else if( def &&(def->GetOverride()) ) |
|
SetOverride(true); |
|
else |
|
SetOverride(false); |
|
|
|
if( env && env->GetDeviceCache() ) |
|
SetDeviceCache(env->GetDeviceCache()); |
|
else if( def && def->GetDeviceCache() ) |
|
SetDeviceCache(def->GetDeviceCache()); |
|
else |
|
SetDeviceCache(nil); |
|
|
|
int i; |
|
for( i = 0; i < GetNumRenderProcs(); i++ ) |
|
{ |
|
hsRefCnt_SafeUnRef(GetRenderProc(i)); |
|
} |
|
fRenderProcs.Reset(); |
|
if( env ) |
|
{ |
|
for( i = 0; i < env->GetNumRenderProcs(); i++ ) |
|
AddRenderProc(env->GetRenderProc(i)); |
|
} |
|
if( def ) |
|
{ |
|
for( i = 0; i < def->GetNumRenderProcs(); i++ ) |
|
AddRenderProc(def->GetRenderProc(i)); |
|
} |
|
|
|
} |
|
|
|
void hsGEnvironment::Blend() |
|
{ |
|
if( fFogControl ) |
|
fFogControl->Blend(); |
|
} |
|
|
|
void hsGEnvironment::Restore() |
|
{ |
|
if( fFogControl ) |
|
fFogControl->Restore(); |
|
} |
|
|
|
void hsGEnvironment::Init(hsSceneNode* node) |
|
{ |
|
if (!node) |
|
{ |
|
char str[256]; |
|
sprintf(str, "hsGEnvironment %s initted with nil room. Weirdness may result.", |
|
GetKeyName()); |
|
HSDebugProc(str); |
|
} |
|
else |
|
{ |
|
if( fFogControl ) |
|
fFogControl->Init(node); |
|
} |
|
|
|
SetResetState(); |
|
} |
|
|
|
void hsGEnvironment::SaveFogState() |
|
{ |
|
FogState* curFogState = new FogState; |
|
curFogState->SetFromEnv(this); |
|
fFogStateStack.Push(curFogState); |
|
} |
|
|
|
void hsGEnvironment::RestoreFogState() |
|
{ |
|
FogState* curFogState = fFogStateStack.GetCount() ? fFogStateStack.Pop() : nil; |
|
if (curFogState) |
|
{ |
|
curFogState->SetToEnv(this); |
|
} |
|
delete curFogState; |
|
} |
|
|
|
void hsGEnvironment::Read(hsStream *stream) |
|
{ |
|
fFlags = stream->ReadSwap32(); |
|
|
|
if( fFlags & hsGEnvironment::kFogDistanceSet ) |
|
{ |
|
hsScalar d = stream->ReadSwapScalar(); |
|
SetFogDistance(d); |
|
} |
|
if( fFlags & hsGEnvironment::kFogDepthSet ) |
|
{ |
|
hsScalar d = stream->ReadSwapScalar(); |
|
SetFogDepth(d); |
|
SetCurrentDepth(d); |
|
} |
|
if( fFlags & hsGEnvironment::kFogDensitySet ) |
|
{ |
|
hsScalar d = stream->ReadSwapScalar(); |
|
SetFogDensity(d); |
|
} |
|
if( fFlags & hsGEnvironment::kFogColorSet ) |
|
{ |
|
hsColorRGBA c; |
|
c.r = stream->ReadSwapScalar(); |
|
c.g = stream->ReadSwapScalar(); |
|
c.b = stream->ReadSwapScalar(); |
|
c.a = stream->ReadSwapScalar(); |
|
SetFogColor(c); |
|
} |
|
if( fFlags & hsGEnvironment::kClearColorSet ) |
|
{ |
|
hsColorRGBA c; |
|
c.r = stream->ReadSwapScalar(); |
|
c.g = stream->ReadSwapScalar(); |
|
c.b = stream->ReadSwapScalar(); |
|
c.a = stream->ReadSwapScalar(); |
|
SetClearColor(c); |
|
} |
|
if( fFlags & hsGEnvironment::kYonSet ) |
|
{ |
|
hsScalar d = stream->ReadSwapScalar(); |
|
SetYon(d); |
|
} |
|
|
|
if( fFlags & hsGEnvironment::kCenterSet ) |
|
fPos.Read(stream); |
|
if( fFlags & hsGEnvironment::kRadiusSet ) |
|
fRadius = stream->ReadSwapScalar(); |
|
// still don't write the map out |
|
|
|
if( !(fFlags & kFogTypeMask) ) |
|
{ |
|
if( GetFogDepth() <= 0.5f ) |
|
fFlags |= kFogLinear; |
|
else |
|
fFlags |= kFogExp; |
|
} |
|
} |
|
|
|
void hsGEnvironment::Write(hsStream *stream) |
|
{ |
|
stream->WriteSwap32(fFlags); |
|
|
|
if( fFlags & hsGEnvironment::kFogDistanceSet ) |
|
stream->WriteSwapScalar(GetFogDistance()); |
|
if( fFlags & hsGEnvironment::kFogDepthSet ) |
|
stream->WriteSwapScalar(GetFogDepth()); |
|
if( fFlags & hsGEnvironment::kFogDensitySet ) |
|
stream->WriteSwapScalar(GetFogDensity()); |
|
if( fFlags & hsGEnvironment::kFogColorSet ) |
|
{ |
|
hsColorRGBA c = GetFogColor(); |
|
stream->WriteSwapScalar(c.r); |
|
stream->WriteSwapScalar(c.g); |
|
stream->WriteSwapScalar(c.b); |
|
stream->WriteSwapScalar(c.a); |
|
} |
|
if( fFlags & hsGEnvironment::kClearColorSet ) |
|
{ |
|
hsColorRGBA c = GetClearColor(); |
|
stream->WriteSwapScalar(c.r); |
|
stream->WriteSwapScalar(c.g); |
|
stream->WriteSwapScalar(c.b); |
|
stream->WriteSwapScalar(c.a); |
|
} |
|
if( fFlags & hsGEnvironment::kYonSet ) |
|
stream->WriteSwapScalar(GetUnscaledYon()); |
|
|
|
if( fFlags & hsGEnvironment::kCenterSet ) |
|
fPos.Write(stream); |
|
if( fFlags & hsGEnvironment::kRadiusSet ) |
|
stream->WriteSwapScalar(fRadius); |
|
// still don't write the map out |
|
|
|
} |
|
|
|
void hsGEnvironment::Write(hsStream* stream, hsResMgr* group) |
|
{ |
|
Write(stream); |
|
|
|
if( fFlags & hsGEnvironment::kHasRenderProcs ) |
|
{ |
|
int n = GetNumRenderProcs(); |
|
stream->WriteSwap32(n); |
|
int i; |
|
for( i = 0; i < n; i++ ) |
|
{ |
|
hsAssert(0,"Its Pauls fault"); |
|
// plFactory::LabelAndWrite(stream, group, GetRenderProc(i)); |
|
} |
|
} |
|
|
|
if ((GetFlags() & hsGEnvironment::kEnvironMapSet) == hsGEnvironment::kEnvironMapSet) |
|
{ |
|
group->WriteKey(stream, GetMap()); |
|
} |
|
|
|
stream->WriteSwap32(fNodeKeys.GetCount()); |
|
Int32 i; |
|
for (i = 0; i < fNodeKeys.GetCount(); i++) |
|
{ |
|
group->WriteKey(stream, fNodeKeys[i]); |
|
} |
|
|
|
if( fFlags & hsGEnvironment::kFogControl ) |
|
IWriteFogControl(stream, group); |
|
} |
|
|
|
void hsGEnvironment::Read(hsStream* stream, hsResMgr* group) |
|
{ |
|
Read(stream); |
|
|
|
if( fFlags & hsGEnvironment::kHasRenderProcs ) |
|
{ |
|
int n = stream->ReadSwap32(); |
|
int i; |
|
for( i = 0; i < n; i++ ) |
|
{ |
|
hsAssert(0,"Its Pauls fault"); |
|
// hsGRenderProcs* rp = hsGRenderProcs::ConvertNoRef(plFactory::CreateAndRead(stream, group)); |
|
// AddRenderProc(rp); |
|
// hsRefCnt_SafeUnRef(rp); |
|
} |
|
} |
|
|
|
if ((GetFlags() & hsGEnvironment::kEnvironMapSet) == hsGEnvironment::kEnvironMapSet) |
|
{ |
|
plRefMsg* refMsg = new plRefMsg(GetKey(), plRefMsg::kOnCreate); |
|
group->ReadKeyNotifyMe(stream,refMsg); |
|
} |
|
|
|
hsAssert(fNodeKeys.GetCount() == 0, "fNodeKeys not empty in hsGEnvironment::Read."); |
|
Int32 nodeCount = stream->ReadSwap32(); |
|
hsAssert(nodeCount > 0, "Environment node not in any rooms in hsGEnvironment::Read."); |
|
Int32 i; |
|
for (i = 0; i < nodeCount; i++) |
|
{ |
|
plKey *key = group->ReadKey(stream); |
|
AddNodeKey(key); |
|
} |
|
|
|
if( fFlags & hsGEnvironment::kFogControl ) |
|
IReadFogControl(stream, group); |
|
} |
|
|
|
void hsGEnvironment::IReadFogControl(hsStream* s, hsResMgr* mgr) |
|
{ |
|
hsAssert(0,"Its Pauls fault"); |
|
// hsFogControl* fc = hsFogControl::ConvertNoRef(plFactory::CreateAndRead(s, mgr)); |
|
// SetFogControl(fc); |
|
// hsRefCnt_SafeUnRef(fc); |
|
|
|
} |
|
|
|
void hsGEnvironment::IWriteFogControl(hsStream* s, hsResMgr* mgr) |
|
{ |
|
hsAssert(0,"Its Pauls fault"); |
|
// plFactory::LabelAndWrite(s, mgr, fFogControl); |
|
} |
|
|
|
void hsGEnvironment::Push(hsG3DDevice* d) |
|
{ |
|
#if 0 // Nuking old device - mf |
|
int i; |
|
|
|
for( i = 0; i < GetNumRenderProcs(); i++ ) |
|
d->AddRenderProc(GetRenderProc(i)); |
|
#endif // Nuking old device - mf |
|
} |
|
|
|
void hsGEnvironment::Pop(hsG3DDevice* d) |
|
{ |
|
#if 0 // Nuking old device - mf |
|
int i; |
|
for( i = 0; i < GetNumRenderProcs(); i++ ) |
|
d->RemoveRenderProc(GetRenderProc(i)); |
|
#endif // Nuking old device - mf |
|
} |
|
|
|
void hsGEnvironment::AddRenderProc(hsGRenderProcs* rp) |
|
{ |
|
hsRefCnt_SafeRef(rp); |
|
fRenderProcs.Append(rp); |
|
fFlags |= hsGEnvironment::kHasRenderProcs; |
|
} |
|
|
|
hsGRenderProcs* hsGEnvironment::GetRenderProc(int i) |
|
{ |
|
return fRenderProcs[i]; |
|
} |
|
|
|
UInt32 hsGEnvironment::GetNumRenderProcs() |
|
{ |
|
return fRenderProcs.GetCount(); |
|
} |
|
|
|
hsScalar hsGEnvironment::SetYonScale(hsScalar s) |
|
{ |
|
const hsScalar kMinYonScale = 0.05f; |
|
const hsScalar kMaxYonScale = 100.f; |
|
|
|
if( s < kMinYonScale ) |
|
s = kMinYonScale; |
|
else if( s > kMaxYonScale ) |
|
s = kMaxYonScale; |
|
return fYonScale = s; |
|
} |
|
|
|
hsBool hsGEnvironment::MsgReceive(plMessage* msg) |
|
{ |
|
plRefMsg* refMsg = plRefMsg::ConvertNoRef(msg); |
|
|
|
if( refMsg ) |
|
{ |
|
|
|
hsGMaterial *mat = hsGMaterial::ConvertNoRef(refMsg->GetRef()); |
|
SetMap(mat); |
|
} |
|
return false; |
|
} |