/*==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==*/ #ifndef plLightInfo_inc #define plLightInfo_inc #include "pnSceneObject/plObjInterface.h" #include "hsMatrix44.h" #include "hsColorRGBA.h" #include "plIntersect/plVolumeIsect.h" #include "hsBitVector.h" class hsStream; class hsResMgr; class plSpaceTree; class hsGDeviceRef; class hsGMaterial; class plDrawableSpans; class plLayerInterface; class plPipeline; class plDrawable; class plSoftVolume; class hsBounds3Ext; class plVisRegion; class plRenderRequest; class plRenderTarget; class plLightProxy; class plLightInfo : public plObjInterface { public: enum { kDisable = 0x0, // prop 0 is always disable, declared in plObjInterface kLPObsolete, kLPCastShadows, kLPMovable, kLPHasIncludes, kLPIncludesChars, kLP_OBSOLECTE_0, // OLD kLPOverAll, kLPHasSpecular, // This is the same as a non-black specular color, but we use it here to make it faster to check kLPShadowOnly, kLPShadowLightGroup, kLPForceProj, kNumProps }; enum LIRefType { kProjection = 0, k_OBSOLECTE_REF_0, // OLD k_OBSOLECTE_REF_1, // OLD k_OBSOLECTE_REF_2, // OLD kSoftVolume, kVisRegion }; protected: // Volatile properties that shouldn't be network propagated. enum VolatileFlags { kVolNone = 0x0, kVolDirty = 0x1, kVolEmpty = 0x2, kVolZero = 0x4 }; UInt8 fVolFlags; hsBitVector fVisSet; hsBitVector fVisNot; hsTArray fVisRegions; plLightInfo** fPrevDevPtr; plLightInfo* fNextDevPtr; hsGDeviceRef* fDeviceRef; plLayerInterface* fProjection; hsMatrix44 fWorldToProj; hsColorRGBA fAmbient; hsColorRGBA fDiffuse; hsColorRGBA fSpecular; hsMatrix44 fLightToLocal; hsMatrix44 fLocalToLight; hsMatrix44 fLocalToWorld; hsMatrix44 fWorldToLocal; hsMatrix44 fLightToWorld; hsMatrix44 fWorldToLight; plKey fSceneNode; plLightProxy* fProxyGen; plSoftVolume* fSoftVolume; hsScalar fMaxStrength; hsBool fRegisteredForRenderMsg; // Small shadow section hsBitVector fSlaveBits; virtual void IMakeIsect() = 0; virtual plVolumeIsect* IGetIsect() = 0; virtual void IRefresh(); virtual const hsMatrix44& IGetWorldToProj() const { return fWorldToProj; } void IAddVisRegion(plVisRegion* reg); void IRemoveVisRegion(plVisRegion* reg); virtual void ISetSceneNode(plKey node); void ICheckMaxStrength(); public: plLightInfo(); virtual ~plLightInfo(); CLASSNAME_REGISTER( plLightInfo ); GETINTERFACE_ANY( plLightInfo, plObjInterface ); void SetDeviceRef(hsGDeviceRef* ref); hsGDeviceRef* GetDeviceRef() const { return fDeviceRef; } // Dirty state is local to this machine, so shouldn't be in the network synchronized properties. hsBool IsDirty() const { return 0 != (fVolFlags & kVolDirty); } void SetDirty(hsBool on=true) { if(on)fVolFlags |= kVolDirty; else fVolFlags &= ~kVolDirty; } hsBool IsEmpty() const { return 0 != (fVolFlags & kVolEmpty); } void SetEmpty(hsBool on=true) { if(on)fVolFlags |= kVolEmpty; else fVolFlags &= ~kVolEmpty; } hsBool IsZero() const { return 0 != (fVolFlags & kVolZero); } void SetZero(hsBool on) { if(on)fVolFlags |= kVolZero; else fVolFlags &= ~kVolZero; } inline hsBool IsIdle() const; hsBool OverAll() const { return GetProperty(kLPOverAll); } hsBool IsShadowCaster() const { return GetProperty(kLPCastShadows); } void SetShadowCaster(hsBool on) { SetProperty(kLPCastShadows, on); } void Refresh() { if( IsDirty() ) { IRefresh(); SetDirty(false); } } virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const; hsBool AffectsBound(const hsBounds3Ext& bnd) { return IGetIsect() ? IGetIsect()->Test(bnd) != kVolumeCulled : true; } void GetAffectedForced(const plSpaceTree* space, hsBitVector& list, hsBool charac); void GetAffected(const plSpaceTree* space, hsBitVector& list, hsBool charac); const hsTArray& GetAffected(plSpaceTree* space, const hsTArray& visList, hsTArray& litList, hsBool charac); hsBool InVisSet(const hsBitVector& visSet) const { return fVisSet.Overlap(visSet); } hsBool InVisNot(const hsBitVector& visNot) const { return fVisNot.Overlap(visNot); } void SetAmbient(const hsColorRGBA& c) { fAmbient = c; SetDirty(); } void SetDiffuse(const hsColorRGBA& c) { fDiffuse = c; SetDirty(); } void SetSpecular(const hsColorRGBA& c); const hsColorRGBA& GetAmbient() const { return fAmbient; } const hsColorRGBA& GetDiffuse() const { return fDiffuse; } const hsColorRGBA& GetSpecular() const { return fSpecular; } plLayerInterface* GetProjection() const { return fProjection; } virtual void SetProperty(int prop, hsBool on); virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual const hsMatrix44& GetLocalToWorld() const; virtual const hsMatrix44& GetWorldToLocal() const; virtual const hsMatrix44& GetLightToWorld() const; virtual const hsMatrix44& GetWorldToLight() const; virtual Int32 GetNumProperties() const { return kNumProps; } const plSoftVolume* GetSoftVolume() const { return fSoftVolume; } virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const = 0; virtual void Read(hsStream* stream, hsResMgr* mgr); virtual void Write(hsStream* stream, hsResMgr* mgr); virtual hsBool MsgReceive(plMessage* msg); virtual void Unlink( void ); virtual void Link( plLightInfo **back ); virtual plLightInfo *GetNext( void ) { return fNextDevPtr; } virtual hsBool IsLinked( void ) { return ( fNextDevPtr != nil || fPrevDevPtr != nil ) ? true : false; } // New shadow void ClearSlaveBits() { fSlaveBits.Clear(); } void SetSlaveBit(int which) { fSlaveBits.SetBit(which); } const hsBitVector& GetSlaveBits() const { return fSlaveBits; } // These two should only be called internally and on export/convert virtual plKey GetSceneNode() const; // Export only. At runtime, the LocalToLight should be considered const. void SetLocalToLight(const hsMatrix44& l2lt, const hsMatrix44& lt2l); // Visualization virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray& idx, plDrawableSpans* addTo) { return addTo; } }; class plDirectionalLightInfo : public plLightInfo { protected: virtual void IMakeIsect() {} virtual plVolumeIsect* IGetIsect() { return nil; } public: plDirectionalLightInfo(); virtual ~plDirectionalLightInfo(); CLASSNAME_REGISTER( plDirectionalLightInfo ); GETINTERFACE_ANY( plDirectionalLightInfo, plLightInfo ); virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const; hsVector3 GetWorldDirection() const; virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const { return -GetWorldDirection(); } virtual void Read(hsStream* stream, hsResMgr* mgr); virtual void Write(hsStream* stream, hsResMgr* mgr); }; class plLimitedDirLightInfo : public plDirectionalLightInfo { protected: hsScalar fWidth; hsScalar fHeight; hsScalar fDepth; plParallelIsect* fParPlanes; virtual void IMakeIsect(); virtual plVolumeIsect* IGetIsect() { return fParPlanes; } virtual void IRefresh(); public: plLimitedDirLightInfo(); virtual ~plLimitedDirLightInfo(); CLASSNAME_REGISTER( plLimitedDirLightInfo ); GETINTERFACE_ANY( plLimitedDirLightInfo, plDirectionalLightInfo ); virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const; hsScalar GetWidth() const { return fWidth; } hsScalar GetHeight() const { return fHeight; } hsScalar GetDepth() const { return fDepth; } void SetWidth(hsScalar w) { fWidth = w; } void SetHeight(hsScalar h) { fHeight = h; } void SetDepth(hsScalar d) { fDepth = d; } virtual void Read(hsStream* stream, hsResMgr* mgr); virtual void Write(hsStream* stream, hsResMgr* mgr); // Visualization virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray& idx, plDrawableSpans* addTo); }; class plOmniLightInfo : public plLightInfo { protected: // Omni and spot hsScalar fAttenConst; hsScalar fAttenLinear; hsScalar fAttenQuadratic; hsScalar fAttenCutoff; // Only for attenuate-but-not-really mode, 0 otherwise plSphereIsect* fSphere; virtual void IMakeIsect(); virtual plVolumeIsect* IGetIsect() { return fSphere; } virtual void IRefresh(); public: plOmniLightInfo(); virtual ~plOmniLightInfo(); CLASSNAME_REGISTER( plOmniLightInfo ); GETINTERFACE_ANY( plOmniLightInfo, plLightInfo ); virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const; virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const; hsBool IsAttenuated() const { return (fAttenLinear != 0)||(fAttenQuadratic != 0) || ( fAttenCutoff != 0 ); } hsScalar GetRadius() const; hsScalar GetConstantAttenuation() const { return fAttenConst; } hsScalar GetLinearAttenuation() const { return fAttenLinear; } hsScalar GetQuadraticAttenuation() const { return fAttenQuadratic; } hsScalar GetCutoffAttenuation() const { return fAttenCutoff; } hsPoint3 GetWorldPosition() const { return fLightToWorld.GetTranslate(); } void SetConstantAttenuation(hsScalar a) { fAttenConst = a; SetDirty(true); } void SetLinearAttenuation(hsScalar a) { fAttenLinear = a; SetDirty(true); } void SetQuadraticAttenuation(hsScalar a) { fAttenQuadratic = a; SetDirty(true); } void SetCutoffAttenuation( hsScalar a ) { fAttenCutoff = a; SetDirty( true ); } virtual void Read(hsStream* stream, hsResMgr* mgr); virtual void Write(hsStream* stream, hsResMgr* mgr); // Visualization virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray& idx, plDrawableSpans* addTo); }; class plSpotLightInfo : public plOmniLightInfo { protected: // Valid only for spot hsScalar fFalloff; // Note - these are half angles, D3D wants whole angles, so fSpotInner*2 etc. hsScalar fSpotInner; hsScalar fSpotOuter; hsScalar fEffectiveFOV; plConeIsect* fCone; virtual void IMakeIsect(); virtual plVolumeIsect* IGetIsect() { return fCone; } virtual void IRefresh(); public: plSpotLightInfo(); virtual ~plSpotLightInfo(); CLASSNAME_REGISTER( plSpotLightInfo ); GETINTERFACE_ANY( plSpotLightInfo, plOmniLightInfo ); virtual void GetStrengthAndScale(const hsBounds3Ext& bnd, hsScalar& strength, hsScalar& scale) const; hsVector3 GetWorldDirection() const; virtual hsVector3 GetNegativeWorldDirection(const hsPoint3& pos) const { return -GetWorldDirection(); } void SetFalloff(hsScalar f) { fFalloff = f; SetDirty(true); } void SetSpotInner(hsScalar rads) { fSpotInner = rads; SetDirty(true); } void SetSpotOuter(hsScalar rads) { fSpotOuter = rads; SetDirty(true); } hsScalar GetFalloff() const { return fFalloff; } hsScalar GetSpotInner() const { return fSpotInner; } hsScalar GetSpotOuter() const { return fSpotOuter; } virtual void Read(hsStream* stream, hsResMgr* mgr); virtual void Write(hsStream* stream, hsResMgr* mgr); // Visualization virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray& idx, plDrawableSpans* addTo); }; inline hsBool plLightInfo::IsIdle() const { if( GetProperty(kDisable) ) return true; if( IsZero() ) return true; if( IsEmpty() ) return true; return false; } #endif // plLightInfo_inc