/*==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 . 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; iGetKey()); } #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; iWriteSwap16(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; iReadSwap16(); 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& f) { if( fDevCache ) fDevCache->Validate(false); fFlags |= kFogDistanceSet; fFogDistance = f; } void hsGEnvironment::SetFogDepth(const hsTimedValue& f) { if( fDevCache ) fDevCache->Validate(false); fFlags |= kFogDepthSet; fFogDepth = f; } void hsGEnvironment::SetFogDensity(const hsTimedValue& f) { if( fDevCache ) fDevCache->Validate(false); fFlags |= kFogDensitySet; fFogDensity = f; } void hsGEnvironment::SetFogColor(const hsTimedValue& c) { if( fDevCache ) fDevCache->Validate(false); fFlags |= kFogColorSet; fFogColor = c; } void hsGEnvironment::SetClearColor(const hsTimedValue& c) { fFlags |= kClearColorSet; fClearColor = c; } void hsGEnvironment::SetYon(const hsTimedValue& 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; }