//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #ifndef _SHADOW_H_ #define _SHADOW_H_ #ifndef _DEPTHSORTLIST_H_ #include "collision/depthSortList.h" #endif #ifndef _TSSHAPEINSTANCE_H_ #include "ts/tsShapeInstance.h" #endif class GBitmap; class Shadow { GBitmap * mBitmap; TextureHandle mShadowTexture; F32 mRadius; F32 mInvShadowDistance; MatrixF mLightToWorld; MatrixF mWorldToLight; Vector mPartition; Vector mPartitionVerts; Vector mPartitionTVerts; Vector mPartitionColors; struct ShadowSettings { // set by user (probably just once) bool alwaysUseGenericBmp; bool noAnimate; bool noMove; // determined frame to frame S32 bmpDim; S32 blur; U32 lastBmpTime; bool needBmp; } mSettings; static U32 smShadowMask; static DepthSortList smDepthSortList; static TextureHandle* smGenericShadowTexture; static S32 smGenericShadowDim; static S32 smInstanceCount; static F32 smShapeDetailScale; static S32 smShapeDetailMin; static F32 smSmallestVisibleSize; static F32 smGenericRadiusSkew; static bool smAlwaysUseGenericBmp; static F32 smLightDirSkew; static F32 smLightLenSkew; static F32 smGlobalShadowDetail; static void collisionCallback(SceneObject*,void *); S32 sgLastShadowDetailSize; void detectShadowDetailSizeChange(); public: struct DistanceDetail { F32 dist; F32 directionSkew; /// 0-1, 0 means leave direction alone, 1 means light vector (0,0,-1) F32 lengthSkew; /// 0-1, 0 means leave length alone, 1 means shadow volume has no depth }; struct PixelSizeDetail { F32 size; U32 frameExpiration; S32 bmpDim; S32 blur; bool genericShadowBmp; }; U32 sgLastRenderTime; U32 sgPreviousShadowTime; VectorF sgPreviousShadowLightingVector; void setDetailTables(const DistanceDetail *, S32 ddCount, const PixelSizeDetail *, S32 psdCount); void setDefaultDetailTables(); // this method changes several shadow detail parameters all at once -- range is 0-1, default value is 1 static void setGlobalShadowDetailLevel(F32 d); static F32 getGlobalShadowDetailLevel() { return smGlobalShadowDetail; } void setGeneric(bool b) { mSettings.alwaysUseGenericBmp = b; } void setAnimating(bool b) { mSettings.noAnimate = !b; } void setMoving(bool b) { mSettings.noMove = !b; } static DistanceDetail smDefaultDistanceDetails[]; private: const DistanceDetail * mDistanceDetails; const PixelSizeDetail * mPixelSizeDetails; S32 mNumDistanceDetails; S32 mNumPixelSizeDetails; void findDistanceDetail(F32 dist, DistanceDetail *); void findPixelSizeDetail(F32 pixelSize, const PixelSizeDetail * *); void setLightMatrices(const Point3F & lightDir, const Point3F & pos); void buildPartition(const Point3F & p, const Point3F & lightDir, F32 radius, F32 shadowLen); void updatePartition(F32 fogAmount); public: Shadow(); ~Shadow(); void beginRenderToBitmap(); void endRenderToBitmap(); void renderToBitmap(TSShapeInstance *, const MatrixF &, const Point3F & center, Point3F scale); GBitmap * getBitmap() { return mBitmap; } void setRadius(F32 radius); void setRadius(TSShapeInstance *, const Point3F & scale); bool prepare(const Point3F & pos, Point3F lightDir, F32 shadowLen, const Point3F & scale, F32 dist, F32 fogAmount, TSShapeInstance *); bool needBitmap() { return mSettings.needBmp; } S32 selectShapeDetail(TSShapeInstance*, F32 dist, F32 scale, S32 detailMin = -1); void render(); static GBitmap * generateGenericShadowBitmap(S32 dim); #ifdef TORQUE_DEBUG void dumpSort(); #endif }; #endif // _SHADOW_H_