Files
simgear/simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.hpp
T
2002-09-14 16:03:39 +00:00

274 lines
12 KiB
C++

//------------------------------------------------------------------------------
// File : SkyRenderableInstanceCloud.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyRenderableInstanceCloud.hpp
*
* Interface for class SkyRenderableInstanceCloud, an instance of a SkyCloud object.
*/
#ifndef __SKYRENDERABLEINSTANCECLOUD_HPP__
#define __SKYRENDERABLEINSTANCECLOUD_HPP__
class SkyCloud;
class SkyTexture;
//class SkyOffScreenBuffer;
#include <vector>
#include "camera.hpp"
#include "SkyContext.hpp"
#include "SkyRenderableInstance.hpp"
#include "SkyRenderableInstanceGeneric.hpp"
#include "SkyCloud.hpp"
//------------------------------------------------------------------------------
/**
* @class SkyRenderableInstanceCloud
* @brief An instance of a cloud. Renders using an impostor.
*
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
*/
class SkyRenderableInstanceCloud : public SkyRenderableInstance
{
public:
SkyRenderableInstanceCloud( SkyCloud *pCloud, bool bUseOffScreenBuffer = false);
SkyRenderableInstanceCloud( SkyCloud *pCloud,
const Vec3f &position,
const Mat33f &rotation,
const float scale,
bool bUseOffScreenBuffer = false);
virtual ~SkyRenderableInstanceCloud();
// Setters / Getters
//! Sets the identifier for this cloud (used by SkySceneManager.)
void SetID(int id) { _iCloudID = id; }
virtual void SetPosition(const Vec3f &position);
virtual void SetRotation(const Mat33f &rotation);
virtual void SetScale(const float &scale);
//! Returns SkySceneManager's id for this cloud.
int GetID() const { return _iCloudID; }
//! Returns a pointer to the renderable that this instance represents.
virtual SkyCloud* GetCloud() const { return _pCloud; }
//! Returns the world space bounding box of the cloud instance.
const SkyMinMaxBox& GetWorldSpaceBounds() { return *_pWorldSpaceBV; }
//! Make this into a split impostor. Will be rendered as two halves, around the split point.
void SetSplit(bool bSplit) { _bSplit = bSplit; }
//! Set the distance at which the cloud will be split (from the camera position).
void SetSplitPoint(const Vec3f& vecSplit) { _vecSplit = vecSplit; }
//! Returns true if this is a split impostor (cloud contains objects)
bool IsSplit() const { return _bSplit; }
//! Returns true if the camera is inside this clouds bounding volume.
bool IsScreenImpostor() const { return _bScreenImpostor; }
virtual SKYRESULT Update(const Camera& cam);
virtual SKYRESULT Display(bool bDisplayFrontOfSplit = false);
SKYRESULT DisplayWithoutImpostor(const Camera& cam);
virtual bool ViewFrustumCull( const Camera &cam );
void ReleaseImpostorTextures();
virtual SkyMinMaxBox* GetBoundingVolume() const { return _pWorldSpaceBV; }
//----------------------------------------------------------------------------
// Determine if the current impostor image is valid for the given viewpoint
//----------------------------------------------------------------------------
bool IsImpostorValid(const Camera &cam);
//------------------------------------------------------------------------------
// Function : Enable
// Description :
//------------------------------------------------------------------------------
/**
* @fn Enable(bool bEnable)
* @brief Enable / Disable the use of impostor images (if disabled, displays geometry).
*/
void Enable(bool bEnable) { _bEnabled = bEnable; }
static void SetErrorToleranceAngle(float rDegrees);
protected: // methods
void _Initialize();
inline int _GetRequiredLogResolution(float rObjectDistance, float rObjectRadius, float rCamRadius);
inline void _UpdateWorldSpaceBounds();
protected: // data
int _iCloudID; // used by the scene manager to identify clouds.
SkyCloud *_pCloud; // Pointer to the cloud object
SkyMinMaxBox *_pWorldSpaceBV; // Pointer to bounding volume in object space
float _rRadius; // Radius of the impostor.
bool _bScreenImpostor; // Is this a screen space or world space impostor?
bool _bImageExists; // The impostor image exists and is ready to use.
bool _bEnabled; // if disabled, draw geometry -- otherwise, draw impostor.
bool _bUseOffScreenBuffer; // if enabled, uses off-screen rendering to create impostor images.
bool _bSplit; // true if the cloud contains other object instances.
Vec3f _vecSplit; // the point about which this cloud is split.
Vec3f _vecNearPoint; // Nearest point on bounding sphere to viewpoint.
Vec3f _vecFarPoint; // Farthest point on bounding sphere from viewpoint.
Camera _impostorCam; // camera used to generate this impostor
unsigned int _iLogResolution; // Log base 2 of current impostor image resolution.
SkyTexture *_pBackTexture; // Back texture for split clouds or main texture for unsplit.
SkyTexture *_pFrontTexture; // Front texture for split clouds.
unsigned int _iCulledCount; // used to determine when to release textures
static unsigned int s_iCount; // keep track of number of impostors using the render buffer.
//JW?? static SkyOffScreenBuffer* s_pRenderBuffer;
static float s_rErrorToleranceAngle;
static SkyMaterial *s_pMaterial; // shared material for cloud impostors.
};
//------------------------------------------------------------------------------
/**
* @class SkyContainerCloud
* @brief A class used to organize the rendering order of cloud impostors and the objects in the clouds
*
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
*/
class SkyContainerCloud : public SkyRenderableInstance
{
public: // methods
//! Constructor.
SkyContainerCloud(SkyRenderableInstanceCloud *cloud) : SkyRenderableInstance(), pCloud(cloud) {}
//! Destructor.
~SkyContainerCloud()
{ pCloud = NULL; containedOpaqueInstances.clear(); containedTransparentInstances.clear(); }
virtual SKYRESULT Display()
{
// display the back half of the split impostor.
FAIL_RETURN_MSG(pCloud->Display(false),
"SkySceneManager::Display(): cloud instance display failed.");
if (pCloud->IsSplit())
{
// display contained instances -- first opaque, then transparent.
InstanceIterator ii;
for (ii = containedOpaqueInstances.begin(); ii != containedOpaqueInstances.end(); ++ii)
FAIL_RETURN((*ii)->Display());
for (ii = containedTransparentInstances.begin(); ii != containedTransparentInstances.end(); ++ii)
FAIL_RETURN((*ii)->Display());
// now display the front half of the split impostor.
FAIL_RETURN_MSG(pCloud->Display(true),
"SkySceneManager::Display(): cloud instance display failed.");
}
return SKYRESULT_OK;
}
virtual const Vec3f& GetPosition() const { return pCloud->GetPosition(); }
public: //data -- here the data are public because the interface is minimal.
SkyRenderableInstanceCloud *pCloud;
InstanceArray containedOpaqueInstances;
InstanceArray containedTransparentInstances;
// This operator is used to sort ContainerCloud arrays.
bool operator<(const SkyContainerCloud& container) const
{
return (*((SkyRenderableInstance*)pCloud) < *((SkyRenderableInstance*)container.pCloud));
}
};
//------------------------------------------------------------------------------
// Function : _GetRequiredLogResolution
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::_GetRequiredLogResolution(float rObjectDistance, float rObjectRadius, float rCamRadius)
* @brief Returns the integer logarithm base two of the expected impostor resolution.
*
* Impostor resolution is based on object size, distance, and the FOV of the camera (stored as the
* radius of a sphere centered at the camera position and passing through the corners of the
* projection plane.
*/
inline int SkyRenderableInstanceCloud::_GetRequiredLogResolution(float rObjectDistance,
float rObjectRadius,
float rCamRadius)
{
int iScreenWidth, iScreenHeight;
GraphicsContext::InstancePtr()->GetWindowSize(iScreenWidth, iScreenHeight);
//cout << "SkyRes: w=" << iScreenWidth << "h=" << iScreenHeight << endl; char ff; cin >> ff;
int iScreenResolution = (iScreenWidth > iScreenHeight) ? iScreenWidth : iScreenHeight;
int iLogMinScreenResolution = (iScreenWidth > iScreenHeight) ? iScreenHeight : iScreenWidth;
iLogMinScreenResolution = SkyGetLogBaseTwo(iLogMinScreenResolution) - 1;
int iRes = 2 * iScreenResolution * _pWorldSpaceBV->GetRadius() / rObjectDistance;
int iLogResolution;
if (rObjectDistance - (0.5f * rObjectRadius) < rCamRadius)
{
iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 8);
}
else if (rObjectDistance - rObjectRadius < rCamRadius)
{
iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 4);
}
else if (iRes > iScreenResolution)
{
iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 2);
}
else
{
iLogResolution = SkyGetLogBaseTwo(iRes);
}
// if not rendering to an off screen buffer, make sure the resolution fits in the window!
if (!_bUseOffScreenBuffer && (iLogMinScreenResolution < iLogResolution))
iLogResolution = iLogMinScreenResolution;
return iLogResolution;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds()
* @brief Updates the world space bounding box of the cloud.
*/
inline void SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds()
{
SAFE_DELETE(_pWorldSpaceBV);
_pWorldSpaceBV = _pCloud->CopyBoundingVolume();
_vecPosition = _pCloud->CopyBoundingVolume()->GetCenter();
}
#endif //__SKYRENDERABLEINSTANCECLOUD_HPP__