#ifndef SHADOWGEOMETRY_H #define SHADOWGEOMETRY_H #define DEFAULT_SHADOW_COLOR (NiColor(0.7f, 0.7f, 0.7f)) class CShadowGeometry : public NiRefObject { public: enum ShadowType { ST_NULL, ST_STATIC, ST_DYNAMIC, }; static CShadowGeometry* Create(ShadowType eShadowType = ST_DYNAMIC); virtual ~CShadowGeometry(); // Render the shadow texture void Click(const NiPoint3& kPos); void RenderTexture(); void ResetCaster(NiAVObject* pkCaster); NiTriShape* GetShadowGeometry() const { return m_spShadowGeometry; } bool IsDynamicShadow() const { return m_eShadowType == ST_DYNAMIC; } static void SetShadowColor(const NiColor& kColor); static bool _SDMInit(); static void _SDMShutdown(); protected: CShadowGeometry(ShadowType eShadowType); void UpdateShadowCamera(); void UpdateShadowGeometry(); void UpdateShadowGeometryBound(); void RecursiveStoreCasterObjects(NiAVObject* pkObject); bool GenerateCameraRay(unsigned int uiIndex, NiPoint3& kPt, NiPoint3& kDir); void CullTriAgainstCameraFrustum(const NiPoint3 akV[3]); void AddShadowTriangle(const NiPoint3 akV[3]); void TraverseGroundGeometry(); // Initial max triangle and vertex counts allowed when generating the // set of geometry subtended by the shadown (i.e. shadow "recipient" // geometry). This method is independent of "caster" geometry count, as // the system renders the shadow to a texture (or uses a loaded texture) enum { SHADOW_TRIANGLE_COUNT = 60, SHADOW_VERTEX_COUNT = 180 }; // Leaf geometry objects in the shadow caster scene. If the shadow is // dynamically rendered, we will render these as a flat list (a batch // rendering). They are found by traversing the m_spCaster for leaf // geometry NiTObjectSet m_kCastingObjects; NiTObjectSet m_kSkinnedCastingObjects; // The tree containing all objects that will cast a shadow upon the scene // Used only in the case that the shadow is dynamically rendered per frame NiAVObjectPtr m_spCaster; // A very distant camera, designed to represent an infinite light source NiCameraPtr m_spCamera; NiFrustumPlanes m_kPlanes; // The shadow texture, which will either be: // A) Rendered each frame to represent the shadow geometry as seen from // the casting light's POV // B) Loaded from file at initialization time and used each frame NiTexturePtr m_spTexture; // The render target used by the system to render the shadow geometry NiRenderTargetGroupPtr m_spRenderTargetGroup; // Current recipient geometry, created from triangles in the m_spGround // scene that intersect the cast shadow volume. This is a dynamic object // and will be refilled each frame NiTriShapePtr m_spShadowGeometry; NiPoint3 m_kLightDir; NiPoint3 m_kTranslate; float m_fRadius; // Limits on the amount of ground (recipient) geometry that can be added // to m_spShadowGeometry, to avoid overflowing (or having to resize) the // geometry arrays unsigned short m_usMaxTriangleCount; unsigned short m_usMaxVertexCount; ShadowType m_eShadowType; static NiMaterial* ms_pkShadowMaterial; static NiMaterial* ms_pkShadowSkinnedMaterial; static NiTexture* ms_pkStaticShadow; // A property state that causes the shadow caster to be rendered as dark // gray into the white background of the shadow image. Used when drawing // the shadow caster geometry into the shadow texture (dynamically // rendered shadow image only - unused if the shadow is loaded from file) static NiPropertyState* ms_pkPropertyState; static NiMaterialProperty* ms_pkMaterialProperty; }; NiSmartPointer(CShadowGeometry); #endif // SHADOWGEOMETRY_H