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.

1254 lines
29 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/>.
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;
}