1 //------------------------------------------------------------------------------
2 // File : SkyRenderableInstanceCloud.hpp
3 //------------------------------------------------------------------------------
4 // SkyWorks : Copyright 2002 Mark J. Harris and
5 // The University of North Carolina at Chapel Hill
6 //------------------------------------------------------------------------------
7 // Permission to use, copy, modify, distribute and sell this software and its
8 // documentation for any purpose is hereby granted without fee, provided that
9 // the above copyright notice appear in all copies and that both that copyright
10 // notice and this permission notice appear in supporting documentation.
11 // Binaries may be compiled with this software without any royalties or
14 // The author(s) and The University of North Carolina at Chapel Hill make no
15 // representations about the suitability of this software for any purpose.
16 // It is provided "as is" without express or implied warranty.
18 * @file SkyRenderableInstanceCloud.hpp
20 * Interface for class SkyRenderableInstanceCloud, an instance of a SkyCloud object.
22 #ifndef __SKYRENDERABLEINSTANCECLOUD_HPP__
23 #define __SKYRENDERABLEINSTANCECLOUD_HPP__
27 //class SkyOffScreenBuffer;
31 #include "SkyContext.hpp"
32 #include "SkyRenderableInstance.hpp"
33 #include "SkyRenderableInstanceGeneric.hpp"
34 #include "SkyCloud.hpp"
36 //------------------------------------------------------------------------------
38 * @class SkyRenderableInstanceCloud
39 * @brief An instance of a cloud. Renders using an impostor.
41 * @todo <WRITE EXTENDED CLASS DESCRIPTION>
43 class SkyRenderableInstanceCloud : public SkyRenderableInstance
46 SkyRenderableInstanceCloud( SkyCloud *pCloud, bool bUseOffScreenBuffer = false);
47 SkyRenderableInstanceCloud( SkyCloud *pCloud,
48 const Vec3f &position,
49 const Mat33f &rotation,
51 bool bUseOffScreenBuffer = false);
52 virtual ~SkyRenderableInstanceCloud();
55 //! Sets the identifier for this cloud (used by SkySceneManager.)
56 void SetID(int id) { _iCloudID = id; }
58 virtual void SetPosition(const Vec3f &position);
60 virtual void SetRotation(const Mat33f &rotation);
62 virtual void SetScale(const float &scale);
64 //! Returns SkySceneManager's id for this cloud.
65 int GetID() const { return _iCloudID; }
66 //! Returns a pointer to the renderable that this instance represents.
67 virtual SkyCloud* GetCloud() const { return _pCloud; }
69 //! Returns the world space bounding box of the cloud instance.
70 const SkyMinMaxBox& GetWorldSpaceBounds() { return *_pWorldSpaceBV; }
72 //! Make this into a split impostor. Will be rendered as two halves, around the split point.
73 void SetSplit(bool bSplit) { _bSplit = bSplit; }
75 //! Set the distance at which the cloud will be split (from the camera position).
76 void SetSplitPoint(const Vec3f& vecSplit) { _vecSplit = vecSplit; }
78 //! Returns true if this is a split impostor (cloud contains objects)
79 bool IsSplit() const { return _bSplit; }
81 //! Returns true if the camera is inside this clouds bounding volume.
82 bool IsScreenImpostor() const { return _bScreenImpostor; }
84 virtual SKYRESULT Update(const Camera& cam);
85 virtual SKYRESULT Display(bool bDisplayFrontOfSplit = false);
86 SKYRESULT DisplayWithoutImpostor(const Camera& cam);
88 virtual bool ViewFrustumCull( const Camera &cam );
90 void ReleaseImpostorTextures();
93 virtual SkyMinMaxBox* GetBoundingVolume() const { return _pWorldSpaceBV; }
95 //----------------------------------------------------------------------------
96 // Determine if the current impostor image is valid for the given viewpoint
97 //----------------------------------------------------------------------------
98 bool IsImpostorValid(const Camera &cam);
100 //------------------------------------------------------------------------------
103 //------------------------------------------------------------------------------
105 * @fn Enable(bool bEnable)
106 * @brief Enable / Disable the use of impostor images (if disabled, displays geometry).
108 void Enable(bool bEnable) { _bEnabled = bEnable; }
110 static void SetErrorToleranceAngle(float rDegrees);
112 protected: // methods
114 inline int _GetRequiredLogResolution(float rObjectDistance, float rObjectRadius, float rCamRadius);
116 inline void _UpdateWorldSpaceBounds();
119 int _iCloudID; // used by the scene manager to identify clouds.
121 SkyCloud *_pCloud; // Pointer to the cloud object
122 SkyMinMaxBox *_pWorldSpaceBV; // Pointer to bounding volume in object space
124 float _rRadius; // Radius of the impostor.
125 bool _bScreenImpostor; // Is this a screen space or world space impostor?
126 bool _bImageExists; // The impostor image exists and is ready to use.
127 bool _bEnabled; // if disabled, draw geometry -- otherwise, draw impostor.
128 bool _bUseOffScreenBuffer; // if enabled, uses off-screen rendering to create impostor images.
130 bool _bSplit; // true if the cloud contains other object instances.
131 Vec3f _vecSplit; // the point about which this cloud is split.
133 Vec3f _vecNearPoint; // Nearest point on bounding sphere to viewpoint.
134 Vec3f _vecFarPoint; // Farthest point on bounding sphere from viewpoint.
136 Camera _impostorCam; // camera used to generate this impostor
138 unsigned int _iLogResolution; // Log base 2 of current impostor image resolution.
140 SkyTexture *_pBackTexture; // Back texture for split clouds or main texture for unsplit.
141 SkyTexture *_pFrontTexture; // Front texture for split clouds.
143 unsigned int _iCulledCount; // used to determine when to release textures
145 static unsigned int s_iCount; // keep track of number of impostors using the render buffer.
146 //JW?? static SkyOffScreenBuffer* s_pRenderBuffer;
147 static float s_rErrorToleranceAngle;
148 static SkyMaterial *s_pMaterial; // shared material for cloud impostors.
152 //------------------------------------------------------------------------------
154 * @class SkyContainerCloud
155 * @brief A class used to organize the rendering order of cloud impostors and the objects in the clouds
157 * @todo <WRITE EXTENDED CLASS DESCRIPTION>
159 class SkyContainerCloud : public SkyRenderableInstance
163 SkyContainerCloud(SkyRenderableInstanceCloud *cloud) : SkyRenderableInstance(), pCloud(cloud) {}
166 { pCloud = NULL; containedOpaqueInstances.clear(); containedTransparentInstances.clear(); }
168 virtual SKYRESULT Display()
170 // display the back half of the split impostor.
171 FAIL_RETURN_MSG(pCloud->Display(false),
172 "SkySceneManager::Display(): cloud instance display failed.");
174 if (pCloud->IsSplit())
176 // display contained instances -- first opaque, then transparent.
178 for (ii = containedOpaqueInstances.begin(); ii != containedOpaqueInstances.end(); ++ii)
179 FAIL_RETURN((*ii)->Display());
180 for (ii = containedTransparentInstances.begin(); ii != containedTransparentInstances.end(); ++ii)
181 FAIL_RETURN((*ii)->Display());
183 // now display the front half of the split impostor.
184 FAIL_RETURN_MSG(pCloud->Display(true),
185 "SkySceneManager::Display(): cloud instance display failed.");
191 virtual const Vec3f& GetPosition() const { return pCloud->GetPosition(); }
193 public: //data -- here the data are public because the interface is minimal.
194 SkyRenderableInstanceCloud *pCloud;
196 InstanceArray containedOpaqueInstances;
197 InstanceArray containedTransparentInstances;
199 // This operator is used to sort ContainerCloud arrays.
200 bool operator<(const SkyContainerCloud& container) const
202 return (*((SkyRenderableInstance*)pCloud) < *((SkyRenderableInstance*)container.pCloud));
207 //------------------------------------------------------------------------------
208 // Function : _GetRequiredLogResolution
210 //------------------------------------------------------------------------------
212 * @fn SkyRenderableInstanceCloud::_GetRequiredLogResolution(float rObjectDistance, float rObjectRadius, float rCamRadius)
213 * @brief Returns the integer logarithm base two of the expected impostor resolution.
215 * Impostor resolution is based on object size, distance, and the FOV of the camera (stored as the
216 * radius of a sphere centered at the camera position and passing through the corners of the
219 inline int SkyRenderableInstanceCloud::_GetRequiredLogResolution(float rObjectDistance,
223 int iScreenWidth, iScreenHeight;
224 GraphicsContext::InstancePtr()->GetWindowSize(iScreenWidth, iScreenHeight);
225 //cout << "SkyRes: w=" << iScreenWidth << "h=" << iScreenHeight << endl; char ff; cin >> ff;
226 int iScreenResolution = (iScreenWidth > iScreenHeight) ? iScreenWidth : iScreenHeight;
227 int iLogMinScreenResolution = (iScreenWidth > iScreenHeight) ? iScreenHeight : iScreenWidth;
228 iLogMinScreenResolution = SkyGetLogBaseTwo(iLogMinScreenResolution) - 1;
230 int iRes = 2 * iScreenResolution * _pWorldSpaceBV->GetRadius() / rObjectDistance;
233 if (rObjectDistance - (0.5f * rObjectRadius) < rCamRadius)
235 iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 8);
237 else if (rObjectDistance - rObjectRadius < rCamRadius)
239 iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 4);
241 else if (iRes > iScreenResolution)
243 iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 2);
247 iLogResolution = SkyGetLogBaseTwo(iRes);
250 // if not rendering to an off screen buffer, make sure the resolution fits in the window!
251 if (!_bUseOffScreenBuffer && (iLogMinScreenResolution < iLogResolution))
252 iLogResolution = iLogMinScreenResolution;
254 return iLogResolution;
258 //------------------------------------------------------------------------------
259 // Function : SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds
261 //------------------------------------------------------------------------------
263 * @fn SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds()
264 * @brief Updates the world space bounding box of the cloud.
266 inline void SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds()
268 SAFE_DELETE(_pWorldSpaceBV);
269 _pWorldSpaceBV = _pCloud->CopyBoundingVolume();
270 _vecPosition = _pCloud->CopyBoundingVolume()->GetCenter();
273 #endif //__SKYRENDERABLEINSTANCECLOUD_HPP__