]> git.mxchange.org Git - simgear.git/blob - simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.hpp
Clouds3D crashes because there is no Light
[simgear.git] / simgear / scene / sky / clouds3d / SkyRenderableInstanceCloud.hpp
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 
12 // restrictions. 
13 //
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.
17 /**
18  * @file SkyRenderableInstanceCloud.hpp
19  * 
20  * Interface for class SkyRenderableInstanceCloud, an instance of a SkyCloud object.
21  */
22 #ifndef __SKYRENDERABLEINSTANCECLOUD_HPP__
23 #define __SKYRENDERABLEINSTANCECLOUD_HPP__
24
25 class  SkyCloud;
26 class  SkyTexture;
27 //class  SkyOffScreenBuffer;
28
29 #include <vector>
30 #include "camera.hpp"
31 #include "SkyContext.hpp"
32 #include "SkyRenderableInstance.hpp"
33 #include "SkyRenderableInstanceGeneric.hpp"
34 #include "SkyCloud.hpp"
35
36 //------------------------------------------------------------------------------
37 /**
38  * @class SkyRenderableInstanceCloud
39  * @brief An instance of a cloud.  Renders using an impostor.
40  * 
41  * @todo <WRITE EXTENDED CLASS DESCRIPTION>
42  */
43 class SkyRenderableInstanceCloud : public SkyRenderableInstance
44 {
45 public:
46   SkyRenderableInstanceCloud( SkyCloud      *pCloud, bool bUseOffScreenBuffer = false);
47   SkyRenderableInstanceCloud( SkyCloud      *pCloud, 
48                               const Vec3f   &position, 
49                               const Mat33f  &rotation, 
50                               const float   scale,
51                               bool          bUseOffScreenBuffer = false);
52   virtual ~SkyRenderableInstanceCloud();
53   
54   // Setters / Getters
55     //! Sets the identifier for this cloud (used by SkySceneManager.)
56   void                   SetID(int id)                        { _iCloudID = id;               }
57   
58   virtual void           SetPosition(const Vec3f  &position);
59   
60   virtual void           SetRotation(const Mat33f &rotation);
61   
62   virtual void           SetScale(const float  &scale);
63
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;               }
68   
69   //! Returns the world space bounding box of the cloud instance.
70   const SkyMinMaxBox&    GetWorldSpaceBounds()                { return *_pWorldSpaceBV;      }
71
72   //! Make this into a split impostor.  Will be rendered as two halves, around the split point.
73   void                   SetSplit(bool bSplit)                { _bSplit = bSplit;             }
74   
75   //! Set the distance at which the cloud will be split (from the camera position).
76   void                   SetSplitPoint(const Vec3f& vecSplit) { _vecSplit = vecSplit;         }
77
78   //! Returns true if this is a split impostor (cloud contains objects)
79   bool                   IsSplit() const                      { return _bSplit;               }
80
81   //! Returns true if the camera is inside this clouds bounding volume.
82   bool                   IsScreenImpostor() const             { return _bScreenImpostor;      }
83   
84   virtual SKYRESULT      Update(const Camera& cam);
85   virtual SKYRESULT      Display(bool bDisplayFrontOfSplit = false);
86   SKYRESULT              DisplayWithoutImpostor(const Camera& cam);
87     
88   virtual bool           ViewFrustumCull( const Camera &cam );
89
90   void                   ReleaseImpostorTextures();
91
92   
93   virtual SkyMinMaxBox*  GetBoundingVolume() const            { return _pWorldSpaceBV;        }
94   
95   //----------------------------------------------------------------------------
96   // Determine if the current impostor image is valid for the given viewpoint
97   //----------------------------------------------------------------------------
98   bool                   IsImpostorValid(const Camera &cam);
99   
100   //------------------------------------------------------------------------------
101   // Function             : Enable
102   // Description            : 
103   //------------------------------------------------------------------------------
104   /**
105   * @fn Enable(bool bEnable)
106   * @brief Enable / Disable the use of impostor images (if disabled, displays geometry).
107   */ 
108   void                   Enable(bool bEnable)                 { _bEnabled = bEnable;          }
109   
110   static void            SetErrorToleranceAngle(float rDegrees);  
111
112 protected: // methods
113   void        _Initialize();
114   inline int  _GetRequiredLogResolution(float rObjectDistance, float rObjectRadius, float rCamRadius);
115   
116   inline void _UpdateWorldSpaceBounds();
117
118 protected: // data
119   int               _iCloudID;        // used by the scene manager to identify clouds.
120
121   SkyCloud          *_pCloud;         // Pointer to the cloud object
122   SkyMinMaxBox      *_pWorldSpaceBV; // Pointer to bounding volume in object space
123   
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.
129   
130   bool              _bSplit;          // true if the cloud contains other object instances.
131   Vec3f             _vecSplit;        // the point about which this cloud is split.
132
133   Vec3f             _vecNearPoint;    // Nearest point on bounding sphere to viewpoint.
134   Vec3f             _vecFarPoint;     // Farthest point on bounding sphere from viewpoint.
135   
136   Camera            _impostorCam;     // camera used to generate this impostor
137   
138   unsigned int      _iLogResolution;  // Log base 2 of current impostor image resolution.
139
140   SkyTexture        *_pBackTexture;   // Back texture for split clouds or main texture for unsplit.
141   SkyTexture        *_pFrontTexture;  // Front texture for split clouds.
142
143   unsigned int      _iCulledCount;    // used to determine when to release textures
144   
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. 
149 };
150
151
152 //------------------------------------------------------------------------------
153 /**
154  * @class SkyContainerCloud
155  * @brief A class used to organize the rendering order of cloud impostors and the objects in the clouds
156  * 
157  * @todo <WRITE EXTENDED CLASS DESCRIPTION>
158  */
159 class SkyContainerCloud : public SkyRenderableInstance
160 {
161 public: // methods
162   //! Constructor.
163   SkyContainerCloud(SkyRenderableInstanceCloud *cloud) : SkyRenderableInstance(), pCloud(cloud) {}
164   //! Destructor.
165   ~SkyContainerCloud() 
166   { pCloud = NULL; containedOpaqueInstances.clear(); containedTransparentInstances.clear(); }
167
168   virtual SKYRESULT Display()                      
169   {
170     // display the back half of the split impostor.
171     FAIL_RETURN_MSG(pCloud->Display(false),
172                     "SkySceneManager::Display(): cloud instance display failed.");
173
174     if (pCloud->IsSplit())
175     {
176       // display contained instances -- first opaque, then transparent.
177       InstanceIterator ii;
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());
182
183       // now display the front half of the split impostor.
184       FAIL_RETURN_MSG(pCloud->Display(true),
185                       "SkySceneManager::Display(): cloud instance display failed.");
186     }  
187
188     return SKYRESULT_OK;
189   }
190
191   virtual const Vec3f& GetPosition() const { return pCloud->GetPosition(); }
192
193 public: //data -- here the data are public because the interface is minimal.
194   SkyRenderableInstanceCloud *pCloud;
195
196   InstanceArray               containedOpaqueInstances;
197   InstanceArray               containedTransparentInstances;
198
199   // This operator is used to sort ContainerCloud arrays. 
200   bool operator<(const SkyContainerCloud& container) const
201   {
202     return (*((SkyRenderableInstance*)pCloud) < *((SkyRenderableInstance*)container.pCloud));
203   }
204 };
205
206
207 //------------------------------------------------------------------------------
208 // Function               : _GetRequiredLogResolution
209 // Description      : 
210 //------------------------------------------------------------------------------
211 /**
212  * @fn SkyRenderableInstanceCloud::_GetRequiredLogResolution(float rObjectDistance, float rObjectRadius, float rCamRadius)
213  * @brief Returns the integer logarithm base two of the expected impostor resolution.
214  * 
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 
217  * projection plane. 
218  */ 
219 inline int SkyRenderableInstanceCloud::_GetRequiredLogResolution(float rObjectDistance, 
220                                                                  float rObjectRadius, 
221                                                                  float rCamRadius)
222 {
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;
229
230   int iRes = 2 * iScreenResolution * _pWorldSpaceBV->GetRadius() / rObjectDistance;
231   int iLogResolution;
232   
233   if (rObjectDistance - (0.5f * rObjectRadius) < rCamRadius) 
234   {
235     iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 8);
236   }
237   else if (rObjectDistance - rObjectRadius < rCamRadius) 
238   {
239     iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 4);
240   }
241   else if (iRes > iScreenResolution) 
242   {
243     iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 2);
244   }
245   else
246   {
247     iLogResolution = SkyGetLogBaseTwo(iRes);
248   }
249
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;
253
254   return iLogResolution;
255 }
256
257
258 //------------------------------------------------------------------------------
259 // Function               : SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds
260 // Description      : 
261 //------------------------------------------------------------------------------
262 /**
263  * @fn SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds()
264  * @brief Updates the world space bounding box of the cloud.
265  */ 
266 inline void SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds()
267 {
268   SAFE_DELETE(_pWorldSpaceBV);
269   _pWorldSpaceBV = _pCloud->CopyBoundingVolume();
270   _vecPosition = _pCloud->CopyBoundingVolume()->GetCenter();
271 }
272
273 #endif //__SKYRENDERABLEINSTANCECLOUD_HPP__