Initial revision.
This commit is contained in:
30
simgear/scene/sky/clouds3d/Makefile.am
Normal file
30
simgear/scene/sky/clouds3d/Makefile.am
Normal file
@@ -0,0 +1,30 @@
|
||||
includedir = @includedir@/sky
|
||||
|
||||
lib_LIBRARIES = libsgcloud3d.a
|
||||
|
||||
include_HEADERS = \
|
||||
SkySceneLoader.hpp \
|
||||
SkyUtil.hpp
|
||||
|
||||
libsgcloud3d_a_SOURCES = \
|
||||
vec3fv.cpp \
|
||||
mat16fv.cpp \
|
||||
tri.cpp \
|
||||
plane.cpp \
|
||||
camera.cpp \
|
||||
camutils.cpp \
|
||||
minmaxbox.cpp \
|
||||
SkyMinMaxBox.cpp \
|
||||
SkyLight.cpp \
|
||||
SkyMaterial.cpp \
|
||||
SkyTextureManager.cpp \
|
||||
SkyTextureState.cpp \
|
||||
SkyDynamicTextureManager.cpp \
|
||||
SkyRenderableInstanceCloud.cpp \
|
||||
SkyRenderableInstanceGroup.cpp \
|
||||
SkyCloud.cpp \
|
||||
SkyArchive.cpp \
|
||||
SkyUtil.cpp \
|
||||
SkyContext.cpp \
|
||||
SkySceneManager.cpp \
|
||||
SkySceneLoader.cpp
|
||||
19
simgear/scene/sky/clouds3d/SkyAABBTree.hpp
Normal file
19
simgear/scene/sky/clouds3d/SkyAABBTree.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
//============================================================================
|
||||
// File : SkyAABBTree.hpp
|
||||
//
|
||||
// Author : Wesley Hunt
|
||||
//
|
||||
// Content : axis-aligned bounding box tree
|
||||
//
|
||||
//============================================================================
|
||||
#ifndef __SKYAABBTREE_HPP__
|
||||
#define __SKYAABBTREE_HPP__
|
||||
|
||||
#include "SkyBVTree.hpp"
|
||||
#include "SkyBVTreeSplitter.hpp"
|
||||
|
||||
template <class object>
|
||||
class SkyAABBTree : public SkyBVTree<object, SkyMinMaxBox, SkyAABBTreeSplitter<object> >
|
||||
{};
|
||||
|
||||
#endif //__SKYAABBTREE_HPP__
|
||||
1201
simgear/scene/sky/clouds3d/SkyArchive.cpp
Normal file
1201
simgear/scene/sky/clouds3d/SkyArchive.cpp
Normal file
File diff suppressed because it is too large
Load Diff
243
simgear/scene/sky/clouds3d/SkyArchive.hpp
Normal file
243
simgear/scene/sky/clouds3d/SkyArchive.hpp
Normal file
@@ -0,0 +1,243 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyArchive.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 SkyArchive.hpp
|
||||
*
|
||||
* A hierarchical archive Class for storing data.
|
||||
*/
|
||||
#ifndef __SKYARCHIVE_HPP__
|
||||
#define __SKYARCHIVE_HPP__
|
||||
|
||||
#pragma warning( disable : 4786 )
|
||||
|
||||
#include "vec2f.hpp"
|
||||
#include "vec3f.hpp"
|
||||
#include "vec4f.hpp"
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
#include <map> // for std::multimap
|
||||
|
||||
//! Types supported by the archive system
|
||||
enum SkyArchiveTypeCode
|
||||
{
|
||||
BOOL_TYPE,
|
||||
INT8_TYPE,
|
||||
INT16_TYPE,
|
||||
INT32_TYPE,
|
||||
UINT8_TYPE,
|
||||
UINT16_TYPE,
|
||||
UINT32_TYPE,
|
||||
FLOAT32_TYPE,
|
||||
FLOAT64_TYPE,
|
||||
STRING_TYPE,
|
||||
VEC2F_TYPE,
|
||||
VEC3F_TYPE,
|
||||
VEC4F_TYPE,
|
||||
ARCHIVE_TYPE,
|
||||
ANY_TYPE,
|
||||
NULL_TYPE
|
||||
};
|
||||
|
||||
struct SkyArchiveEntry;
|
||||
|
||||
struct StringLessFunctor
|
||||
{
|
||||
bool operator() (const char* p1, const char* p2) const
|
||||
{
|
||||
return ::strcmp( p1, p2) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Class : SkyArchive
|
||||
//
|
||||
//! A simple hierarchical archive file useful for loading and saving data.
|
||||
//
|
||||
/*! SkyArchive bundles information so that an application can store,
|
||||
manipulate, and retrieve data in a storage-independent manner. Information
|
||||
stored in an SkyArchive file can be modified without breaking
|
||||
compatibility with the code that retrieves the data. In essence, it can be
|
||||
thought of as a very basic database mechanism.
|
||||
|
||||
A SkyArchive is simply a container. The class defines methods that allow
|
||||
you to put information in a SkyArchive, determine the information in a
|
||||
SkyArchive, and retrieve information from a SkyArchive. It's important
|
||||
to note that the SkyArchive is a recursive storage mechanism; a
|
||||
SkyArchive itself can hold one or more other SkyArchives.
|
||||
|
||||
Data are added to an archive in fields. The datum in a field is associated
|
||||
with a name, number of bytes, and a type code. The name can be anything you
|
||||
choose and is not required to be unique. The number of bytes must be accurate.
|
||||
The type code must be one of the SkyArchiveTypeCode enums. Several of the Add
|
||||
functions have been specialized for the common base types. It isn't necessary
|
||||
to provide the number of bytes when using the specialized functions, since it can be
|
||||
inferred from the type code.
|
||||
|
||||
The functions that retrieve fields from an archive are similar to the ones
|
||||
that add data, only their roles are reversed. As with the Add functions,
|
||||
there are several specialized functions for the common base types while
|
||||
custom information can be retrieved using the generic FindData function.
|
||||
|
||||
Querying the contents of an archive is provided through the GetInfo
|
||||
functions. These functions are important as they allow you to write
|
||||
code that can intelligently determine how to retrieve information at
|
||||
run-time: you no longer have to hardcode the order in which you retrieve
|
||||
data from your files.
|
||||
|
||||
archive data fields are held in using an STL multimap. The multimap key
|
||||
is a QString (field name) and the data is held in a SkyArchiveEntry
|
||||
structure (see SkyArchive.cpp for details of this structure).
|
||||
The fields are stored in alphabetical order based on the key names.
|
||||
*/
|
||||
class SkyArchive
|
||||
{
|
||||
public:
|
||||
//=========================================================================
|
||||
// Creation & Destruction
|
||||
//=========================================================================
|
||||
// Empty archive: no name, no data fields.
|
||||
SkyArchive();
|
||||
// Creates a named archive with no data fields.
|
||||
SkyArchive( const char* pName);
|
||||
// Deep copy the contents of one archive to another.
|
||||
SkyArchive( const SkyArchive& src);
|
||||
// Deep copy the contents of one archive to another.
|
||||
SkyArchive& operator=( const SkyArchive& src);
|
||||
|
||||
~SkyArchive();
|
||||
|
||||
//=========================================================================
|
||||
// Basic SkyArchive Information
|
||||
//=========================================================================
|
||||
// Returns true if the archive contains no data fields.
|
||||
bool IsEmpty() const;
|
||||
//! Returns the archive's name.
|
||||
const char* GetName() const { return _pName; };
|
||||
|
||||
//=========================================================================
|
||||
// Adding Content to SkyArchive
|
||||
//=========================================================================
|
||||
// Adds a new datafield to the archive.
|
||||
SKYRESULT AddData(const char* pName,
|
||||
SkyArchiveTypeCode eType,
|
||||
const void* pData,
|
||||
unsigned int iNumBytes,
|
||||
unsigned int iNumItems = 1);
|
||||
|
||||
SKYRESULT AddBool( const char* pName, bool aBool);
|
||||
SKYRESULT AddInt8( const char* pName, char anInt8);
|
||||
SKYRESULT AddInt16( const char* pName, short anInt16);
|
||||
SKYRESULT AddInt32( const char* pName, int anInt32);
|
||||
SKYRESULT AddUInt8( const char* pName, unsigned char anUInt8);
|
||||
SKYRESULT AddUInt16( const char* pName, unsigned short anUInt16);
|
||||
SKYRESULT AddUInt32( const char* pName, unsigned int anUInt32);
|
||||
SKYRESULT AddFloat32( const char* pName, float aFloat32);
|
||||
SKYRESULT AddFloat64( const char* pName, double aFloat64);
|
||||
SKYRESULT AddString( const char* pName, const char* pString);
|
||||
|
||||
SKYRESULT AddArchive( const SkyArchive& anArchive);
|
||||
|
||||
// Vector types (MJH:: only supports float versions for now!!!)
|
||||
SKYRESULT AddVec2f( const char* pName, const Vec2f& aPoint2f);
|
||||
SKYRESULT AddVec3f( const char* pName, const Vec3f& aPoint3f);
|
||||
SKYRESULT AddVec4f( const char* pName, const Vec4f& aPoint4f);
|
||||
|
||||
//=========================================================================
|
||||
// Retrieving Content from SkyArchive
|
||||
//=========================================================================
|
||||
// Retrieves the specified datafield the archive, if it exists.
|
||||
SKYRESULT FindData( const char* pName,
|
||||
SkyArchiveTypeCode eType,
|
||||
void** const pData,
|
||||
unsigned int* pNumBytes,
|
||||
unsigned int index = 0) const;
|
||||
|
||||
SKYRESULT FindBool( const char* pName, bool* pBool, unsigned int index = 0) const;
|
||||
SKYRESULT FindInt8( const char* pName, char* pInt8, unsigned int index = 0) const;
|
||||
SKYRESULT FindInt16( const char* pName, short* pInt16, unsigned int index = 0) const;
|
||||
SKYRESULT FindInt32( const char* pName, int* pInt32, unsigned int index = 0) const;
|
||||
SKYRESULT FindUInt8( const char* pName, unsigned char* pUInt8, unsigned int index = 0) const;
|
||||
SKYRESULT FindUInt16( const char* pName, unsigned short* pUInt16, unsigned int index = 0) const;
|
||||
SKYRESULT FindUInt32( const char* pName, unsigned int* pUInt32, unsigned int index = 0) const;
|
||||
SKYRESULT FindFloat32(const char* pName, float* pFloat32, unsigned int index = 0) const;
|
||||
SKYRESULT FindFloat64(const char* pName, double* pFloat64, unsigned int index = 0) const;
|
||||
SKYRESULT FindString( const char* pName, char** const pString, unsigned int index = 0) const;
|
||||
SKYRESULT FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index = 0) const;
|
||||
|
||||
SKYRESULT FindVec2f( const char* pName, Vec2f* pVec2f, unsigned int index = 0) const;
|
||||
SKYRESULT FindVec3f( const char* pName, Vec3f* pVec3f, unsigned int index = 0) const;
|
||||
SKYRESULT FindVec4f( const char* pName, Vec4f* pVec4f, unsigned int index = 0) const;
|
||||
|
||||
SKYRESULT AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index = 0) const;
|
||||
|
||||
//=========================================================================
|
||||
// Querying Contents of SkyArchive
|
||||
//=========================================================================
|
||||
// Computes the number of fields that contain the given name and type.
|
||||
SKYRESULT GetInfo(const char* pName,
|
||||
SkyArchiveTypeCode eType,
|
||||
unsigned int* pNumFound = NULL) const;
|
||||
|
||||
// Returns information about the key at the specified index.
|
||||
SKYRESULT GetInfo(unsigned int iNameIndex,
|
||||
char** pNameFound,
|
||||
SkyArchiveTypeCode* pTypeCode,
|
||||
unsigned int* pNumFound);
|
||||
|
||||
// Computes the number of unique key names in _dataTableable.
|
||||
unsigned int GetNumUniqueNames() const;
|
||||
|
||||
|
||||
// Remove the contents of the SkyArchive.
|
||||
SKYRESULT MakeEmpty();
|
||||
|
||||
// Loads the contents from a file.
|
||||
SKYRESULT Load(const char* pFileName);
|
||||
|
||||
// Commits the contents of a SkyArchive to file storage.
|
||||
SKYRESULT Save(const char* pFileName) const;
|
||||
|
||||
private:
|
||||
|
||||
char* _pName; // this archive's name
|
||||
|
||||
//=========================================================================
|
||||
// Data storage
|
||||
//=========================================================================
|
||||
typedef std::multimap<char*, SkyArchiveEntry*, StringLessFunctor> SkyArchiveMMap;
|
||||
typedef SkyArchiveMMap::const_iterator SkyMMapConstIter;
|
||||
typedef SkyArchiveMMap::iterator SkyMMapIter;
|
||||
|
||||
SkyArchiveMMap _dataTable; // this is where the data reside.
|
||||
|
||||
// Performs a deep-copy of one archive's archive_mmap_t to another.
|
||||
void _CopyDataTable( const SkyArchiveMMap& src);
|
||||
|
||||
// Locates an archive entry in _dataTable
|
||||
const SkyArchiveEntry* _FindEntry( const char* pName,
|
||||
unsigned int index,
|
||||
SkyArchiveTypeCode eType) const;
|
||||
|
||||
// Saves the archive to a file stream.
|
||||
SKYRESULT _Save(FILE* pDestFile) const;
|
||||
// Initializes the archive from a file stream.
|
||||
SKYRESULT _Load(FILE* pSrcFile);
|
||||
};
|
||||
|
||||
#endif //__SKYARCHIVE_HPP__
|
||||
297
simgear/scene/sky/clouds3d/SkyBVTree.hpp
Normal file
297
simgear/scene/sky/clouds3d/SkyBVTree.hpp
Normal file
@@ -0,0 +1,297 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyBVTree.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// Empyrean / SkyWorks : Copyright 2002 Mark J. Harris
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @file SkyBVTree.hpp
|
||||
*
|
||||
* This source was written by Wesley Hunt. Many thanks to him for providing it.
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
// SkyBVTree.hpp
|
||||
//
|
||||
// Author: Wesley Hunt (hunt@cs.unc.edu)
|
||||
// Date: 2000/12/19
|
||||
//-----------------------------------------------------------------------------
|
||||
// Overview
|
||||
// --------
|
||||
// declare an SkyBVTree with whatever object type and bounding volume type you
|
||||
// want. The hard part is to pass in a NodeSplitter class that determines how
|
||||
// to split a node up. See below for a description of its requirements.
|
||||
// Finally, use that tree like so:
|
||||
// * BeginTree()
|
||||
// * AddObject(Object, ObjectBV)
|
||||
// * ...
|
||||
// * EndTree()
|
||||
// < Do whatever you want with GetRoot() >
|
||||
// < Use GetLeftChild() and GetRightChild() to traverse the nodes >
|
||||
//
|
||||
// The class hierarchy is designed for a flexible, simple public interface.
|
||||
// This pushes some extra complexity into the class hierarchy, but there are two
|
||||
// main advantages to the final approach:
|
||||
// 1. There are no interface requirements for the Object and BoundingVolume
|
||||
// template parameters. This means you don't have to modify your existing
|
||||
// class interfaces to use them with the tree.
|
||||
// 2. All the dependent logic for dealing with the bounding volumes is pushed
|
||||
// into the NodeSplitter class. So there is one centralized location for
|
||||
// adapting your bounding volume classes to work with the tree. See the
|
||||
// description of the NodeSplitter template requirements for more details.
|
||||
//
|
||||
// Class Descriptions
|
||||
// ------------------
|
||||
//
|
||||
// SkyBaseBVTree
|
||||
// -------------
|
||||
// declares the node class that the tree holds. It exposes
|
||||
// the public functions of the nodes and defines protected accessors that
|
||||
// the derived tree class can use to manipulate nodes and build the tree.
|
||||
//
|
||||
// Node
|
||||
// ----
|
||||
// This is the class that gives access to the tree. You can access each
|
||||
// object and bounding volume owned by a node, along with that node's
|
||||
// children.
|
||||
//
|
||||
// NodeObject
|
||||
// ----------------
|
||||
// An aggregation of an object and its associated bounding volume.
|
||||
// Each node in the tree essentially owns an array of NodeObjects. This
|
||||
// array is passed to the NodeSplitter class to allow it to examine a
|
||||
// node's contained objects before making a decision on how to split the
|
||||
// node up.
|
||||
//
|
||||
// SkyBVTree
|
||||
// ---------
|
||||
// The main tree class. To use it, supply and object type, a bounding volume
|
||||
// type, and a NodeSplitter class that is used to split the nodes up during
|
||||
// tree construction.
|
||||
//
|
||||
// Template class requirements
|
||||
// ---------------------------
|
||||
//
|
||||
// Object
|
||||
// ------
|
||||
// None
|
||||
//
|
||||
// BoundingVolume
|
||||
// --------------
|
||||
// None
|
||||
//
|
||||
// NodeSplitter
|
||||
// ------------
|
||||
// This is the user-supplied class that decides how to split a node during
|
||||
// tree construction. It is given an array of NodeObjects that the node owns and
|
||||
// is responsible for determining the node's bounding volume as well as how to
|
||||
// split the node up into left and right children.
|
||||
// The required API is as follows:
|
||||
//
|
||||
// * a constructor that takes an array of NodeObject and an unsigned int giving
|
||||
// the size of the array. These are the objects owned by the node to be split.
|
||||
// * a method GetNodeBV() that returns the BoundingVolume of the node.
|
||||
// Typically this is the union of the bounding volumes of the objects owned
|
||||
// by the node.
|
||||
// * A unary function operator used to partition the objects in the node. The
|
||||
// operator must take a single NodeObject as a parameter and return as
|
||||
// a bool whether to place the NodeObject in the left or right child.
|
||||
// Basically, it should be compatible with std::partition using NodeObjects.
|
||||
// * A binary function operator used to sort the objects. If a partition fails,
|
||||
// the nodes are then sorted based on this function and half are sent to each child.
|
||||
// This operator must define a total ordering of the NodeObjects.
|
||||
// Basically, it should be compatible with std::sort using NodeObjects.
|
||||
//
|
||||
// Example:
|
||||
// struct NodeSplitter
|
||||
// {
|
||||
// NodeSplitter(const NodeObject* objs, unsigned int numObjs);
|
||||
// BoundingVolume& GetNodeBV() const;
|
||||
// // Partition predicate
|
||||
// bool operator()(const NodeObject& obj) const;
|
||||
// // Sort predicate
|
||||
// bool operator()(const NodeObject& obj1, const NodeObject& obj2) const;
|
||||
// };
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __SKYBVTREE_HPP__
|
||||
#define __SKYBVTREE_HPP__
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SkyBaseBVTree<Object, BoundingVolume>
|
||||
//-----------------------------------------------------------------------------
|
||||
// See header description for details.
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Object, class BoundingVolume>
|
||||
class SkyBaseBVTree
|
||||
{
|
||||
public:
|
||||
typedef BoundingVolume BV;
|
||||
class NodeObject;
|
||||
|
||||
public:
|
||||
class Node
|
||||
{
|
||||
friend class SkyBaseBVTree<Object, BoundingVolume>;
|
||||
public:
|
||||
Node() : _pObjs(NULL), _iNumObjs(0) {}
|
||||
Node(NodeObject* pObjs, unsigned int iNumObjs) : _pObjs(pObjs), _iNumObjs(iNumObjs) {}
|
||||
|
||||
// Public interface
|
||||
const Object& GetObj(unsigned int index) const { assert(_iNumObjs != 0 && _pObjs != NULL && index < _iNumObjs); return _pObjs[index].GetObj(); }
|
||||
const BV& GetBV(unsigned int index) const { assert(_iNumObjs != 0 && _pObjs != NULL && index < _iNumObjs); return _pObjs[index].GetBV(); }
|
||||
unsigned int GetNumObjs() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _iNumObjs; }
|
||||
const BV& GetNodeBV() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _volume; }
|
||||
const Node* GetLeftChild() const { assert(_iNumObjs != 0 && _pObjs != NULL); return this+1; }
|
||||
const Node* GetRightChild() const { assert(_iNumObjs != 0 && _pObjs != NULL); return this+(GetLeftChild()->GetNumObjs()<<1); }
|
||||
bool IsLeaf() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _iNumObjs == 1; }
|
||||
|
||||
private:
|
||||
// List of Objects owned by the node
|
||||
NodeObject *_pObjs;
|
||||
unsigned int _iNumObjs;
|
||||
BV _volume;
|
||||
};
|
||||
|
||||
public:
|
||||
class NodeObject
|
||||
{
|
||||
public:
|
||||
NodeObject(const Object& o, const BV& v) : _obj(o), _volume(v) {}
|
||||
|
||||
const Object& GetObj() const { return _obj; }
|
||||
const BV& GetBV() const { return _volume; }
|
||||
private:
|
||||
Object _obj;
|
||||
BV _volume;
|
||||
};
|
||||
|
||||
protected:
|
||||
// Give non-const access to the node for descendant classes to build the tree
|
||||
BV& GetNodeBV(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode->_volume; }
|
||||
Node* GetLeftChild(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode+1; }
|
||||
Node* GetRightChild(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode+(GetLeftChild(pNode)->GetNumObjs()<<1); }
|
||||
NodeObject* GetObjs(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode->_pObjs; }
|
||||
|
||||
// Links a node's children by assigning the given number of objects to each child
|
||||
// assumes the node has already had it's objects partitioned
|
||||
void LinkNodeChildren(Node* pNode, unsigned int iLeftNumObjs)
|
||||
{
|
||||
assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL);
|
||||
GetLeftChild(pNode)->_pObjs = pNode->_pObjs;
|
||||
GetLeftChild(pNode)->_iNumObjs = iLeftNumObjs;
|
||||
GetRightChild(pNode)->_pObjs = pNode->_pObjs + iLeftNumObjs;
|
||||
GetRightChild(pNode)->_iNumObjs = pNode->_iNumObjs - iLeftNumObjs;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : ClearVector
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn ClearVector(std::vector<T>& vec)
|
||||
* @brief This utility function uses the std::vector::swap trick to free the memory of a vector
|
||||
*
|
||||
* This is necessary since clear() doesn't actually free anything.
|
||||
*/
|
||||
template<class T>
|
||||
void ClearVector(std::vector<T>& vec)
|
||||
{
|
||||
std::vector<T>().swap(vec);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SkyBVTree<Object, BoundingVolume, NodeSplitter>
|
||||
//-----------------------------------------------------------------------------
|
||||
// See header description for details.
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Object, class BoundingVolume, class NodeSplitter>
|
||||
class SkyBVTree : public SkyBaseBVTree<Object, BoundingVolume>
|
||||
{
|
||||
public:
|
||||
typedef SkyBaseBVTree<Object, BoundingVolume> BaseTree;
|
||||
typedef BaseTree::BV BV;
|
||||
typedef BaseTree::NodeObject NodeObject;
|
||||
typedef BaseTree::Node Node;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
BeginTree();
|
||||
}
|
||||
|
||||
void BeginTree(unsigned int iNumObjs = 0)
|
||||
{
|
||||
ClearVector(_objList);
|
||||
ClearVector(_nodes);
|
||||
if (iNumObjs > 0) _objList.reserve(iNumObjs);
|
||||
}
|
||||
|
||||
void AddObject(const Object &obj, const BV& volume)
|
||||
{
|
||||
_objList.push_back(NodeObject(obj, volume));
|
||||
}
|
||||
|
||||
void EndTree()
|
||||
{
|
||||
if (_objList.size() == 0) return;
|
||||
// Initialize the root node with all the objects
|
||||
_nodes.push_back(Node(&_objList[0], _objList.size()));
|
||||
// create room for the other nodes. They are initialized in BuildTree().
|
||||
_nodes.reserve(_objList.size()*2-1);
|
||||
_nodes.resize(_objList.size()*2-1);
|
||||
BuildTree(&_nodes[0]);
|
||||
}
|
||||
|
||||
const Node *GetRoot() const { return _nodes.empty() ? NULL : &_nodes[0]; }
|
||||
|
||||
// Memory usage info
|
||||
unsigned int CalcMemUsage() const
|
||||
{
|
||||
unsigned int usage = 0;
|
||||
usage += sizeof(*this);
|
||||
usage += _objList.capacity() * sizeof(_objList[0]);
|
||||
usage += _nodes.capacity() * sizeof(_nodes[0]);
|
||||
return usage;
|
||||
}
|
||||
|
||||
public:
|
||||
private:
|
||||
// Does the real work
|
||||
void BuildTree(Node *pCurNode)
|
||||
{
|
||||
int iLeftNumObjs;
|
||||
{
|
||||
// Initialize the node splitter with the current node
|
||||
NodeSplitter splitter(GetObjs(pCurNode), pCurNode->GetNumObjs());
|
||||
|
||||
// set the node's bounding volume using the splitter
|
||||
GetNodeBV(pCurNode) = splitter.GetNodeBV();
|
||||
|
||||
// When a node has one object we can stop
|
||||
if (pCurNode->GetNumObjs() == 1) return;
|
||||
|
||||
// Try and partition the objects
|
||||
iLeftNumObjs = std::partition(GetObjs(pCurNode), &GetObjs(pCurNode)[pCurNode->GetNumObjs()], splitter) - GetObjs(pCurNode);
|
||||
|
||||
if ((iLeftNumObjs == 0) || (iLeftNumObjs == pCurNode->GetNumObjs()))
|
||||
{
|
||||
// Partition failed. Sort and split again to force a complete tree
|
||||
std::sort(GetObjs(pCurNode), &GetObjs(pCurNode)[pCurNode->GetNumObjs()], splitter);
|
||||
iLeftNumObjs = pCurNode->GetNumObjs() / 2;
|
||||
}
|
||||
}
|
||||
|
||||
LinkNodeChildren(pCurNode, iLeftNumObjs);
|
||||
BuildTree(GetLeftChild(pCurNode));
|
||||
BuildTree(GetRightChild(pCurNode));
|
||||
}
|
||||
|
||||
std::vector<Node> _nodes;
|
||||
std::vector<NodeObject> _objList;
|
||||
};
|
||||
|
||||
#endif //__SKYBVTREE_HPP__
|
||||
242
simgear/scene/sky/clouds3d/SkyBVTreeSplitter.hpp
Normal file
242
simgear/scene/sky/clouds3d/SkyBVTreeSplitter.hpp
Normal file
@@ -0,0 +1,242 @@
|
||||
//============================================================================
|
||||
// File : SkyBVTreeSplitter.hpp
|
||||
//
|
||||
// Author : Wesley Hunt
|
||||
//
|
||||
// Content : NodeSplitter classes for SkyBVTrees using SkyBoundingBox or
|
||||
// SkyBoundingSphere (not implemented).
|
||||
//
|
||||
//============================================================================
|
||||
#ifndef __SKYBVTREESPLITTER_HPP__
|
||||
#define __SKYBVTREESPLITTER_HPP__
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//-- Includes ----------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
#include "SkyBVTree.hpp"
|
||||
#include "SkyMinMaxBox.hpp"
|
||||
//#include <Mlx/MlxBoundingSphere.hpp>
|
||||
//#if _MSC_VER == 1200
|
||||
//#include <Auxlib/AuxCompileTimeChecker.hpp>
|
||||
//#endif
|
||||
//----------------------------------------------------------------------------
|
||||
//-- Forward Declarations ----------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
// A strategy for splitting nodes compatible with bounding boxes and spheres.
|
||||
template<class Object> class SkyBoundingBoxSplitter;
|
||||
// SkyBVTree compatible node splitters implemented using the above strategy.
|
||||
template<class Object> class SkyAABBTreeSplitter;
|
||||
//template<class Object> class SkySphereTreeSplitter;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//-- Defines, Constants, Enumerated Types ------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
const float rLongObjectPercentageTolerance = 0.75f;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// SkyBoundingBoxSplitter
|
||||
//----------------------------------------------------------------------------
|
||||
// This class defines a NodeSplitter strategy that has the functionality
|
||||
// required by SkyBVTree's NodeSplitter template class. Can be used with
|
||||
// SkyMinMaxBox and SkyBoundingSphere.
|
||||
//
|
||||
// It defines a two-tiered split strategy:
|
||||
//
|
||||
// * First it tries to separate large objects from any smaller objects.
|
||||
// * If there are no large objects, it splits along the midpoint of the longest
|
||||
// axis defined by the objects.
|
||||
// * Finally, if all else fails, it defines a total ordering along the longest
|
||||
// axis based on the center of each node.
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Object>
|
||||
class SkyBoundingBoxSplitter
|
||||
{
|
||||
public:
|
||||
typedef SkyBaseBVTree<Object, SkyMinMaxBox>::NodeObject NodeObjectBox;
|
||||
//typedef SkyBaseBVTree<Object, SkyBoundingSphere>::NodeObject NodeObjectSphere;
|
||||
|
||||
#if _MSC_VER == 1200
|
||||
// !!! WRH HACK MSVC++6 SP5 Workaround.
|
||||
// VC6 can't disambiguate this constructor because it doesn't consider the two
|
||||
// NodeObject templates to be different classes for the purposes of
|
||||
// overloading. It won't recognize that the second template parameters are
|
||||
// different. Forcing them to be explicit template specializations fixes
|
||||
// the problem.
|
||||
template<class BV>
|
||||
SkyBoundingBoxSplitter(const SkyBaseBVTree<Object, BV>::NodeObject*, unsigned int)
|
||||
{
|
||||
//AUX_STATIC_CHECK(false, VisualC_6_WorkAround); ???
|
||||
}
|
||||
template<>
|
||||
#endif
|
||||
SkyBoundingBoxSplitter(const NodeObjectBox* pObjs, unsigned int iNumObjs)
|
||||
{
|
||||
for (unsigned int i = 0; i < iNumObjs; ++i)
|
||||
{
|
||||
_nodeBBox.Union(pObjs[i].GetBV());
|
||||
}
|
||||
Init(pObjs, iNumObjs);
|
||||
}
|
||||
/*#if _MSC_VER == 1200
|
||||
template<>
|
||||
#endif
|
||||
SkyBoundingBoxSplitter(const NodeObjectSphere* objs,
|
||||
#ifdef _PLATFORM_XBOX
|
||||
Int32
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
numObjs)
|
||||
{
|
||||
for (int i=0; i<numObjs; ++i)
|
||||
{
|
||||
SkyMinMaxBox box;
|
||||
box.AddPoint(objs[i].GetBV().GetCenter());
|
||||
box.Bloat(objs[i].GetBV().GetRadius());
|
||||
_nodeBBox.Union(box);
|
||||
}
|
||||
Init(objs, numObjs);
|
||||
}*/
|
||||
|
||||
template<class nodeObj>
|
||||
bool SplitLeft(const nodeObj& obj) const
|
||||
{
|
||||
if (_bIsolateLongObjects)
|
||||
return GetSplitAxisLength(obj.GetBV()) < _rMaxObjectLength;
|
||||
else
|
||||
return GetSplitAxisCenter(obj.GetBV()) < _rSplitValue;
|
||||
}
|
||||
|
||||
template<class nodeObj>
|
||||
bool LessThan(const nodeObj& obj1, const nodeObj& obj2) const
|
||||
{
|
||||
return GetSplitAxisCenter(obj1.GetBV()) < GetSplitAxisCenter(obj2.GetBV());
|
||||
}
|
||||
|
||||
const SkyMinMaxBox& GetNodeBBox() const { return _nodeBBox; }
|
||||
|
||||
private:
|
||||
template<class nodeObj>
|
||||
void Init(const nodeObj* pObjs, unsigned int iNumObjs)
|
||||
{
|
||||
_iSplitAxis = FindSplitAxis(_nodeBBox);
|
||||
_rSplitValue = FindSplitValue(_nodeBBox, _iSplitAxis);
|
||||
_rMaxObjectLength = GetSplitAxisLength(_nodeBBox) * rLongObjectPercentageTolerance;
|
||||
|
||||
_bIsolateLongObjects = false;
|
||||
for (unsigned int i = 0; i < iNumObjs; ++i)
|
||||
{
|
||||
if (GetSplitAxisLength(pObjs[i].GetBV()) > _rMaxObjectLength)
|
||||
{
|
||||
_bIsolateLongObjects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FindSplitAxis(const SkyMinMaxBox& bbox)
|
||||
{
|
||||
int iAxis = 0, i;
|
||||
Vec3f vecExt = bbox.GetMax() - bbox.GetMin();
|
||||
for (i = 1; i < 3; ++i) if (vecExt[i] > vecExt[iAxis]) iAxis = i;
|
||||
return iAxis;
|
||||
}
|
||||
float FindSplitValue(const SkyMinMaxBox& bbox, int iSplitAxis)
|
||||
{
|
||||
return (bbox.GetMin()[iSplitAxis] + bbox.GetMax()[iSplitAxis])*0.5f;
|
||||
}
|
||||
|
||||
/*float GetSplitAxisLength(const SkyBoundingSphere& sphere) const
|
||||
{
|
||||
return 2.f*sphere.GetRadius();
|
||||
}*/
|
||||
float GetSplitAxisLength(const SkyMinMaxBox& bbox) const
|
||||
{
|
||||
return bbox.GetMax()[_iSplitAxis] - bbox.GetMin()[_iSplitAxis];
|
||||
}
|
||||
|
||||
float GetSplitAxisCenter(const SkyMinMaxBox& bbox) const
|
||||
{
|
||||
return (bbox.GetMin()[_iSplitAxis] + bbox.GetMax()[_iSplitAxis]) * 0.5f;
|
||||
}
|
||||
/*float GetSplitAxisCenter(const SkyBoundingSphere& sphere) const
|
||||
{
|
||||
return sphere.GetCenter()[SplitAxis];
|
||||
}*/
|
||||
|
||||
int _iSplitAxis;
|
||||
float _rSplitValue;
|
||||
bool _bIsolateLongObjects;
|
||||
float _rMaxObjectLength;
|
||||
|
||||
SkyMinMaxBox _nodeBBox;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// SkyAABBTreeSplitter
|
||||
//----------------------------------------------------------------------------
|
||||
// A NodeSplitter that is compatible with SkyBVTree for SkyMinMaxBox.
|
||||
// Implemented using the SkyBoundingBoxSplitter strategy.
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Object>
|
||||
class SkyAABBTreeSplitter
|
||||
{
|
||||
public:
|
||||
typedef SkyMinMaxBox BV;
|
||||
typedef SkyBaseBVTree<Object, BV>::NodeObject NodeObject;
|
||||
|
||||
SkyAABBTreeSplitter(const NodeObject* pObjs, unsigned int iNumObjs) : _splitter(pObjs, iNumObjs) {}
|
||||
|
||||
const BV& GetNodeBV() const { return _splitter.GetNodeBBox(); }
|
||||
|
||||
bool operator()(const NodeObject& obj) const
|
||||
{
|
||||
return _splitter.SplitLeft(obj);
|
||||
}
|
||||
|
||||
bool operator()(const NodeObject& obj1, const NodeObject& obj2) const
|
||||
{
|
||||
return _splitter.LessThan(obj1, obj2);
|
||||
}
|
||||
|
||||
private:
|
||||
SkyBoundingBoxSplitter<Object> _splitter;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// SkySphereTreeSplitter
|
||||
//----------------------------------------------------------------------------
|
||||
// A NodeSplitter that is compatible with SkyBVTree for SkyBoundingSphere.
|
||||
// Implemented using the SkyBoundingBoxSplitter strategy.
|
||||
//----------------------------------------------------------------------------
|
||||
/*template<class Object>
|
||||
class SkySphereTreeSplitter
|
||||
{
|
||||
public:
|
||||
typedef SkyBoundingSphere BV;
|
||||
typedef SkyBaseBVTree<Object, BV>::NodeObject NodeObject;
|
||||
|
||||
MlxSphereTreeSplitter(const NodeObject* pObjs, unsigned int iNumObjs) : _splitter(pObjs, iNumObjs)
|
||||
{
|
||||
_nodeBV = pObjs[0].GetBV();
|
||||
for (unsigned int i = 1; i < iNumObjs; ++i) _nodeBV.Union(pObjs[i].GetBV());
|
||||
}
|
||||
|
||||
const BV& GetNodeBV() const { return _nodeBV; }
|
||||
|
||||
bool operator()(const NodeObject& obj) const
|
||||
{
|
||||
return _splitter.SplitLeft(obj);
|
||||
}
|
||||
|
||||
bool operator()(const NodeObject& obj1, const NodeObject& obj2) const
|
||||
{
|
||||
return _splitter.LessThan(obj1, obj2);
|
||||
}
|
||||
|
||||
private:
|
||||
BV _nodeBV;
|
||||
SkyBoundingBoxSplitter<Object> _splitter;
|
||||
};*/
|
||||
|
||||
#endif //__SKYBVTREESPLITTER_HPP__
|
||||
151
simgear/scene/sky/clouds3d/SkyBoundingVolume.hpp
Normal file
151
simgear/scene/sky/clouds3d/SkyBoundingVolume.hpp
Normal file
@@ -0,0 +1,151 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyBoundingVolume.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 SkyBoundingVolume.hpp
|
||||
*
|
||||
* Base class interface definition for a bounding volume.
|
||||
*/
|
||||
#ifndef __SKYBOUNDINGVOLUME_HPP__
|
||||
#define __SKYBOUNDINGVOLUME_HPP__
|
||||
|
||||
#include <vec3f.hpp>
|
||||
#include <mat44.hpp>
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class Camera;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyBoundingVolume
|
||||
* @brief An abstract base class for bounding volumes (AABB,OBB,Sphere,etc.)
|
||||
*
|
||||
* This base class maintains a center and a radius, so it is effectively a bounding
|
||||
* sphere. Derived classes may represent other types of bounding volumes, but they
|
||||
* should be sure to update the radius and center, because some objects will treat
|
||||
* all bounding volumes as spheres.
|
||||
*
|
||||
*/
|
||||
class SkyBoundingVolume
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
SkyBoundingVolume() : _vecCenter(0, 0, 0), _rRadius(0) {}
|
||||
//! Destructor
|
||||
virtual ~SkyBoundingVolume() {}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SetCenter
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SetCenter(const Vec3f ¢er)
|
||||
* @brief Sets the center of the bounding volume.
|
||||
*/
|
||||
virtual void SetCenter(const Vec3f ¢er) { _vecCenter = center; }
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SetRadius
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SetRadius(float radius)
|
||||
* @brief Sets the radius of the bounding volume.
|
||||
*/
|
||||
virtual void SetRadius(float radius) { _rRadius = radius; }
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Vec3f& GetCenter
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Vec3f& GetCenter() const
|
||||
* @brief Returns the center of the bounding volume.
|
||||
*/
|
||||
virtual const Vec3f& GetCenter() const { return _vecCenter; }
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : GetRadius
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn GetRadius() const
|
||||
* @brief Returns the radius ofthe bounding volume.
|
||||
*/
|
||||
virtual float GetRadius() const { return _rRadius; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : ViewFrustumCull
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn ViewFrustumCull( const Camera &cam, const Mat44f &mat )
|
||||
* @brief Cull a bounding volume.
|
||||
*
|
||||
* Returns false if the bounding volume is entirely outside the camera's frustum,
|
||||
* true otherwise.
|
||||
*/
|
||||
virtual bool ViewFrustumCull( const Camera &cam, const Mat44f &mat ) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : AddPoint
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* @fn AddPoint( const Vec3f &pt )
|
||||
* @brief Add a point to a bounding volume.
|
||||
*
|
||||
* One way to create a bounding volume is to add points. What should/could happen
|
||||
* is that the BV will store an object space BV and then when a call to SetPosition
|
||||
* is called, the stored values will be transformed and stored separately, so that
|
||||
* the original values always exist.
|
||||
*
|
||||
*/
|
||||
//virtual void AddPoint( const Vec3f &point ) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : AddPoint
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* @fn AddPoint( float x, float y, float z )
|
||||
* @brief Add a point to a bounding volume.
|
||||
*
|
||||
* @see AddPoint(const Vec3f &pt)
|
||||
*/
|
||||
//virtual void AddPoint( float x, float y, float z ) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Clear
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* @fn Clear()
|
||||
* @brief Clear all data from the bounding volume.
|
||||
*/
|
||||
//virtual void Clear() = 0;
|
||||
|
||||
protected:
|
||||
Vec3f _vecCenter;
|
||||
float _rRadius;
|
||||
};
|
||||
|
||||
#endif //__SKYBOUNDINGVOLUME_HPP__
|
||||
966
simgear/scene/sky/clouds3d/SkyCloud.cpp
Normal file
966
simgear/scene/sky/clouds3d/SkyCloud.cpp
Normal file
@@ -0,0 +1,966 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyCloud.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyCloud.cpp
|
||||
*
|
||||
* Implementation of class SkyCloud.
|
||||
*/
|
||||
|
||||
// warning for truncation of template name for browse info
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
//#include "glvu.hpp"
|
||||
#include "SkyCloud.hpp"
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
#include "SkyMaterial.hpp"
|
||||
#include "SkyLight.hpp"
|
||||
#include "SkyTextureManager.hpp"
|
||||
#include "SkySceneManager.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
//! The version used for cloud archive files.
|
||||
#define CLOUD_ARCHIVE_VERSION 0.1f
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Static initialization
|
||||
//------------------------------------------------------------------------------
|
||||
SkyMaterial* SkyCloud::s_pMaterial = NULL;
|
||||
SkyMaterial* SkyCloud::s_pShadeMaterial = NULL;
|
||||
unsigned int SkyCloud::s_iShadeResolution = 32;
|
||||
float SkyCloud::s_rAlbedo = 0.9f;
|
||||
float SkyCloud::s_rExtinction = 80.0f;
|
||||
float SkyCloud::s_rTransparency = exp(-s_rExtinction);
|
||||
float SkyCloud::s_rScatterFactor = s_rAlbedo * s_rExtinction * SKY_INV_4PI;
|
||||
float SkyCloud::s_rSortAngleErrorTolerance = 0.8f;
|
||||
float SkyCloud::s_rSortSquareDistanceTolerance = 100;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::SkyCloud
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::SkyCloud()
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyCloud::SkyCloud()
|
||||
: SkyRenderable(),
|
||||
_bUsePhaseFunction(true),
|
||||
_vecLastSortViewDir(Vec3f::ZERO),
|
||||
_vecLastSortCamPos(Vec3f::ZERO)
|
||||
{
|
||||
if (!s_pShadeMaterial)
|
||||
{
|
||||
s_pShadeMaterial = new SkyMaterial;
|
||||
s_pShadeMaterial->SetAmbient(Vec4f(0.1f, 0.1f, 0.1f, 1));
|
||||
s_pShadeMaterial->EnableDepthTest(false);
|
||||
s_pShadeMaterial->SetBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
s_pShadeMaterial->EnableBlending(true);
|
||||
s_pShadeMaterial->SetAlphaFunc(GL_GREATER);
|
||||
s_pShadeMaterial->SetAlphaRef(0);
|
||||
s_pShadeMaterial->EnableAlphaTest(true);
|
||||
s_pShadeMaterial->SetColorMaterialMode(GL_DIFFUSE);
|
||||
s_pShadeMaterial->EnableColorMaterial(true);
|
||||
s_pShadeMaterial->EnableLighting(false);
|
||||
s_pShadeMaterial->SetTextureApplicationMode(GL_MODULATE);
|
||||
}
|
||||
if (!s_pMaterial)
|
||||
{
|
||||
s_pMaterial = new SkyMaterial;
|
||||
s_pMaterial->SetAmbient(Vec4f(0.3f, 0.3f, 0.3f, 1));
|
||||
s_pMaterial->SetDepthMask(false);
|
||||
s_pMaterial->SetBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
s_pMaterial->EnableBlending(true);
|
||||
s_pMaterial->SetAlphaFunc(GL_GREATER);
|
||||
s_pMaterial->SetAlphaRef(0);
|
||||
s_pMaterial->EnableAlphaTest(true);
|
||||
s_pMaterial->SetColorMaterialMode(GL_DIFFUSE);
|
||||
s_pMaterial->EnableColorMaterial(true);
|
||||
s_pMaterial->EnableLighting(false);
|
||||
s_pMaterial->SetTextureApplicationMode(GL_MODULATE);
|
||||
_CreateSplatTexture(32); // will assign the texture to both static materials
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::~SkyCloud
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::~SkyCloud()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkyCloud::~SkyCloud()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::Update
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::Update(const Camera &cam, SkyRenderableInstance* pInstance)
|
||||
* @brief Currently does nothing.
|
||||
*/
|
||||
SKYRESULT SkyCloud::Update(const Camera &cam, SkyRenderableInstance* pInstance)
|
||||
{
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : DrawQuad
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn DrawQuad(Vec3f pos, Vec3f x, Vec3f y, Vec4f color)
|
||||
* @brief Draw a quad.
|
||||
*/
|
||||
inline void DrawQuad(Vec3f pos, Vec3f x, Vec3f y, Vec4f color)
|
||||
{
|
||||
glColor4fv(&(color.x));
|
||||
Vec3f left = pos; left -= y;
|
||||
Vec3f right = left; right += x;
|
||||
left -= x;
|
||||
glTexCoord2f(0, 0); glVertex3fv(&(left.x));
|
||||
glTexCoord2f(1, 0); glVertex3fv(&(right.x));
|
||||
left += y; left += y;
|
||||
right += y; right += y;
|
||||
glTexCoord2f(1, 1); glVertex3fv(&(right.x));
|
||||
glTexCoord2f(0, 1); glVertex3fv(&(left.x));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::Display(const Camera &camera, SkyRenderableInstance *pInstance)
|
||||
* @brief Renders the cloud.
|
||||
*
|
||||
* The cloud is rendered by splatting the particles from back to front with respect
|
||||
* to @a camera. Since instances of clouds each have their own particles, which
|
||||
* are pre-transformed into world space, @a pInstance is not used.
|
||||
*
|
||||
* An alternative method is to store the particles untransformed, and transform the
|
||||
* camera and light into cloud space for rendering. This is more complicated,
|
||||
* and not as straightforward. Since I have to store the particles with each instance
|
||||
* anyway, I decided to pre-transform them instead.
|
||||
*/
|
||||
SKYRESULT SkyCloud::Display(const Camera &camera, SkyRenderableInstance *pInstance)
|
||||
{
|
||||
// copy the current camera
|
||||
Camera cam(camera);
|
||||
|
||||
// This cosine computation, along with the if() below, are an optimization. The goal
|
||||
// is to avoid sorting when it will make no visual difference. This will be true when the
|
||||
// cloud particles are almost sorted for the current viewpoint. This is the case most of the
|
||||
// time, since the viewpoint does not move very far in a single frame. Each time we sort,
|
||||
// we cache the current view direction. Then, each time the cloud is displayed, if the
|
||||
// current view direction is very close to the current view direction (dot product is nearly 1)
|
||||
// then we do not resort the particles.
|
||||
float rCosAngleSinceLastSort =
|
||||
_vecLastSortViewDir * cam.ViewDir(); // dot product
|
||||
|
||||
float rSquareDistanceSinceLastSort =
|
||||
(cam.Orig - _vecLastSortCamPos).LengthSqr();
|
||||
|
||||
if (rCosAngleSinceLastSort < s_rSortAngleErrorTolerance ||
|
||||
rSquareDistanceSinceLastSort > s_rSortSquareDistanceTolerance)
|
||||
{
|
||||
// compute the sort position for particles.
|
||||
// don't just use the camera position -- if it is too far away from the cloud, then
|
||||
// precision limitations may cause the STL sort to hang. Instead, put the sort position
|
||||
// just outside the bounding sphere of the cloud in the direction of the camera.
|
||||
Vec3f vecSortPos = -cam.ViewDir();
|
||||
vecSortPos *= (1.1 * _boundingBox.GetRadius());
|
||||
|
||||
// sort the particles from back to front wrt the camera position.
|
||||
_SortParticles(cam.ViewDir(), vecSortPos, SKY_CLOUD_SORT_TOWARD);
|
||||
|
||||
//_vecLastSortViewDir = GLVU::GetCurrent()->GetCurrentCam()->ViewDir();
|
||||
//_vecLastSortCamPos = GLVU::GetCurrent()->GetCurrentCam()->Orig;
|
||||
_vecLastSortViewDir = cam.ViewDir();
|
||||
_vecLastSortCamPos = cam.Orig;
|
||||
}
|
||||
|
||||
// set the material state / properties that clouds use for rendering:
|
||||
// Enables blending, with blend func (ONE, ONE_MINUS_SRC_ALPHA).
|
||||
// Enables alpha test to discard completely transparent fragments.
|
||||
// Disables depth test.
|
||||
// Enables texturing, with modulation, and the texture set to the shared splat texture.
|
||||
s_pMaterial->Activate();
|
||||
|
||||
Vec4f color;
|
||||
Vec3f eyeDir;
|
||||
|
||||
// Draw the particles using immediate mode.
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
int i = 0;
|
||||
for (ParticleIterator iter = _particles.begin(); iter != _particles.end(); iter++)
|
||||
{
|
||||
i++;
|
||||
SkyCloudParticle *p = *iter;
|
||||
|
||||
// Start with ambient light
|
||||
color = p->GetBaseColor();
|
||||
|
||||
if (_bUsePhaseFunction) // use the phase function for anisotropic scattering.
|
||||
{
|
||||
|
||||
eyeDir = cam.Orig;
|
||||
eyeDir -= p->GetPosition();
|
||||
eyeDir.Normalize();
|
||||
float pf;
|
||||
|
||||
// add the color contribution to this particle from each light source, modulated by
|
||||
// the phase function. See _PhaseFunction() documentation for details.
|
||||
for (int i = 0; i < p->GetNumLitColors(); i++)
|
||||
{
|
||||
pf = _PhaseFunction(_lightDirections[i], eyeDir);
|
||||
// expand this to avoid temporary vector creation in the inner loop
|
||||
color.x += p->GetLitColor(i).x * pf;
|
||||
color.y += p->GetLitColor(i).y * pf;
|
||||
color.z += p->GetLitColor(i).z * pf;
|
||||
}
|
||||
}
|
||||
else // just use isotropic scattering instead.
|
||||
{
|
||||
for (int i = 0; i < (*iter)->GetNumLitColors(); ++i)
|
||||
{
|
||||
color += p->GetLitColor(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the transparency independently of the colors
|
||||
color.w = 1 - s_rTransparency;
|
||||
|
||||
// draw the particle as a textured billboard.
|
||||
DrawQuad((*iter)->GetPosition(), cam.X * p->GetRadius(), cam.Y * p->GetRadius(), color);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::DisplaySplit
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::DisplaySplit(const Camera &camera, const Vec3f &vecSplitPoint, bool bBackHalf, SkyRenderableInstance *pInstance)
|
||||
* @brief The same as Display(), except it displays only the particles in front of or behind the split point.
|
||||
*
|
||||
* This is used to render clouds into two impostor images for displaying clouds that contain objects.
|
||||
*
|
||||
* @see SkyRenderableInstanceCloud
|
||||
*/
|
||||
SKYRESULT SkyCloud::DisplaySplit(const Camera &camera,
|
||||
const Vec3f &vecSplitPoint,
|
||||
bool bBackHalf,
|
||||
SkyRenderableInstance *pInstance /* = NULL */)
|
||||
{
|
||||
// copy the current camera
|
||||
Camera cam(camera);
|
||||
|
||||
Vec3f vecCloudSpaceSplit = vecSplitPoint;
|
||||
|
||||
if (bBackHalf) // only sort when rendering the back half. Reuse sort for front half.
|
||||
{
|
||||
// compute the sort position for particles.
|
||||
// don't just use the camera position -- if it is too far away from the cloud, then
|
||||
// precision limitations may cause the STL sort to hang. Instead, put the sort position
|
||||
// just outside the bounding sphere of the cloud in the direction of the camera.
|
||||
_vecSortPos = -cam.ViewDir();
|
||||
_vecSortPos *= (1.1 * _boundingBox.GetRadius());
|
||||
|
||||
// sort the particles from back to front wrt the camera position.
|
||||
_SortParticles(cam.ViewDir(), _vecSortPos, SKY_CLOUD_SORT_TOWARD);
|
||||
|
||||
// we can't use the view direction optimization when the cloud is split, or we get a lot
|
||||
// of popping of objects in and out of cloud cover. For consistency, though, we need to update
|
||||
// the cached sort direction, since we just sorted the particles.
|
||||
///_vecLastSortViewDir = GLVU::GetCurrent()->GetCurrentCam()->ViewDir();
|
||||
|
||||
// compute the split distance.
|
||||
vecCloudSpaceSplit -= _vecSortPos;
|
||||
_rSplitDistance = vecCloudSpaceSplit * cam.ViewDir();
|
||||
}
|
||||
|
||||
// set the material state / properties that clouds use for rendering:
|
||||
// Enables blending, with blend func (ONE, ONE_MINUS_SRC_ALPHA).
|
||||
// Enables alpha test to discard completely transparent fragments.
|
||||
// Disables depth test.
|
||||
// Enables texturing, with modulation, and the texture set to the shared splat texture.
|
||||
s_pMaterial->Activate();
|
||||
|
||||
Vec4f color;
|
||||
Vec3f eyeDir;
|
||||
|
||||
// Draw the particles using immediate mode.
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
// if bBackHalf is false, then we just continue where we left off. If it is true, we
|
||||
// reset the iterator to the beginning of the sorted list.
|
||||
static ParticleIterator iter;
|
||||
if (bBackHalf)
|
||||
iter = _particles.begin();
|
||||
|
||||
// iterate over the particles and render them.
|
||||
for (; iter != _particles.end(); ++iter)
|
||||
{
|
||||
SkyCloudParticle *p = *iter;
|
||||
|
||||
if (bBackHalf && (p->GetSquareSortDistance() < _rSplitDistance))
|
||||
break;
|
||||
|
||||
// Start with ambient light
|
||||
color = p->GetBaseColor();
|
||||
|
||||
if (_bUsePhaseFunction) // use the phase function for anisotropic scattering.
|
||||
{
|
||||
eyeDir = cam.Orig;
|
||||
eyeDir -= p->GetPosition();
|
||||
eyeDir.Normalize();
|
||||
float pf;
|
||||
|
||||
// add the color contribution to this particle from each light source, modulated by
|
||||
// the phase function. See _PhaseFunction() documentation for details.
|
||||
for (int i = 0; i < p->GetNumLitColors(); i++)
|
||||
{
|
||||
pf = _PhaseFunction(_lightDirections[i], eyeDir);
|
||||
// expand this to avoid temporary vector creation in the inner loop
|
||||
color.x += p->GetLitColor(i).x * pf;
|
||||
color.y += p->GetLitColor(i).y * pf;
|
||||
color.z += p->GetLitColor(i).z * pf;
|
||||
}
|
||||
}
|
||||
else // just use isotropic scattering instead.
|
||||
{
|
||||
for (int i = 0; i < p->GetNumLitColors(); ++i)
|
||||
{
|
||||
color += p->GetLitColor(i);
|
||||
}
|
||||
}
|
||||
|
||||
// set the transparency independently of the colors.
|
||||
color.w = 1 - s_rTransparency;
|
||||
|
||||
// draw the particle as a textured billboard.
|
||||
DrawQuad((*iter)->GetPosition(), cam.X * p->GetRadius(), cam.Y * p->GetRadius(), color);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::Illuminate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::Illuminate(SkyLight *pLight, SkyRenderableInstance* pInstance, bool bReset)
|
||||
* @brief Compute the illumination of the cloud by the lightsource @a pLight
|
||||
*
|
||||
* This method uses graphics hardware to compute multiple forward scattering at each cloud
|
||||
* in the cloud of light from the directional light source @a pLight. The algorithm works
|
||||
* by successively subtracting "light" from an initially white (fully lit) frame buffer by
|
||||
* using hardware blending and read back. The method stores the illumination from each light
|
||||
* source passed to it separately at each particle, unless @a bReset is true, in which case
|
||||
* the lists of illumination in the particles are reset before the lighting is computed.
|
||||
*
|
||||
*/
|
||||
SKYRESULT SkyCloud::Illuminate(SkyLight *pLight, SkyRenderableInstance* pInstance, bool bReset)
|
||||
{
|
||||
int iOldVP[4];
|
||||
|
||||
glGetIntegerv(GL_VIEWPORT, iOldVP);
|
||||
glViewport(0, 0, s_iShadeResolution, s_iShadeResolution);
|
||||
|
||||
Vec3f vecDir(pLight->GetDirection());
|
||||
|
||||
// if this is the first pass through the lights, reset will be true, and the cached light
|
||||
// directions should be updated. Light directions are cached in cloud space to accelerate
|
||||
// computation of the phase function, which depends on light direction and view direction.
|
||||
if (bReset)
|
||||
_lightDirections.clear();
|
||||
_lightDirections.push_back(vecDir); // cache the (unit-length) light direction
|
||||
|
||||
// compute the light/sort position for particles from the light direction.
|
||||
// don't just use the camera position -- if it is too far away from the cloud, then
|
||||
// precision limitations may cause the STL sort to hang. Instead, put the sort position
|
||||
// just outside the bounding sphere of the cloud in the direction of the camera.
|
||||
Vec3f vecLightPos(vecDir);
|
||||
vecLightPos *= (1.1*_boundingBox.GetRadius());
|
||||
vecLightPos += _boundingBox.GetCenter();
|
||||
|
||||
// Set up a camera to look at the cloud from the light position. Since the sun is an infinite
|
||||
// light source, this camera will use an orthographic projection tightly fit to the bounding
|
||||
// sphere of the cloud.
|
||||
Camera cam;
|
||||
|
||||
// Avoid degenerate camera bases.
|
||||
Vec3f vecUp(0, 1, 0);
|
||||
if (fabs(vecDir * vecUp) - 1 < 1e-6) // check that the view and up directions are not parallel.
|
||||
vecUp.Set(1, 0, 0);
|
||||
|
||||
cam.LookAt(vecLightPos, _boundingBox.GetCenter(), vecUp);
|
||||
|
||||
// sort the particles away from the light source.
|
||||
_SortParticles(cam.ViewDir(), vecLightPos, SKY_CLOUD_SORT_AWAY);
|
||||
|
||||
// projected dist to cntr along viewdir
|
||||
float DistToCntr = (_boundingBox.GetCenter() - vecLightPos) * cam.ViewDir();
|
||||
|
||||
// calc tight-fitting near and far distances for the orthographic frustum
|
||||
float rNearDist = DistToCntr - _boundingBox.GetRadius();
|
||||
float rFarDist = DistToCntr + _boundingBox.GetRadius();
|
||||
|
||||
// set the modelview matrix from this camera.
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
float M[16];
|
||||
|
||||
|
||||
cam.GetModelviewMatrix(M);
|
||||
glLoadMatrixf(M);
|
||||
|
||||
// switch to parallel projection
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(-_boundingBox.GetRadius(), _boundingBox.GetRadius(),
|
||||
-_boundingBox.GetRadius(), _boundingBox.GetRadius(),
|
||||
rNearDist, rFarDist);
|
||||
|
||||
// set the material state / properties that clouds use for shading:
|
||||
// Enables blending, with blend func (ONE, ONE_MINUS_SRC_ALPHA).
|
||||
// Enables alpha test to discard completely transparent fragments.
|
||||
// Disables depth test.
|
||||
// Enables texturing, with modulation, and the texture set to the shared splat texture.
|
||||
s_pShadeMaterial->Activate();
|
||||
|
||||
// these are used for projecting the particle position to determine where to read pixels.
|
||||
double MM[16], PM[16];
|
||||
int VP[4] = { 0, 0, s_iShadeResolution, s_iShadeResolution };
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, MM);
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, PM);
|
||||
|
||||
// initialize back buffer to all white -- modulation darkens areas where cloud particles
|
||||
// absorb light, and lightens it where they scatter light in the forward direction.
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
float rPixelsPerLength = s_iShadeResolution / (2 * _boundingBox.GetRadius());
|
||||
|
||||
// the solid angle over which we will sample forward-scattered light.
|
||||
float rSolidAngle = 0.09;
|
||||
int i = 0;
|
||||
int iNumFailed = 0;
|
||||
for (ParticleIterator iter = _particles.begin(); iter != _particles.end(); ++iter, ++i)
|
||||
{
|
||||
Vec3f vecParticlePos = (*iter)->GetPosition();
|
||||
|
||||
Vec3f vecOffset(vecLightPos);
|
||||
vecOffset -= vecParticlePos;
|
||||
|
||||
// compute the pixel area to read back in order to integrate the illumination of the particle
|
||||
// over a constant solid angle.
|
||||
float rDistance = fabs(cam.ViewDir() * vecOffset) - rNearDist;
|
||||
|
||||
float rArea = rSolidAngle * rDistance * rDistance;
|
||||
int iPixelDim = sqrt(rArea) * rPixelsPerLength;
|
||||
int iNumPixels = iPixelDim * iPixelDim;
|
||||
if (iNumPixels < 1)
|
||||
{
|
||||
iNumPixels = 1;
|
||||
iPixelDim = 1;
|
||||
}
|
||||
|
||||
// the scale factor to convert the read back pixel colors to an average illumination of the area.
|
||||
float rColorScaleFactor = rSolidAngle / (iNumPixels * 255.0f);
|
||||
|
||||
unsigned char *c = new unsigned char[4 * iNumPixels];
|
||||
|
||||
Vec3d vecWinPos;
|
||||
|
||||
// find the position in the buffer to which the particle position projects.
|
||||
if (!gluProject(vecParticlePos.x, vecParticlePos.y, vecParticlePos.z,
|
||||
MM, PM, VP,
|
||||
&(vecWinPos.x), &(vecWinPos.y), &(vecWinPos.z)))
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"Error: SkyCloud::Illuminate(): failed to project particle position.");
|
||||
}
|
||||
|
||||
// offset the projected window position by half the size of the readback region.
|
||||
vecWinPos.x -= 0.5 * iPixelDim;
|
||||
if (vecWinPos.x < 0) vecWinPos.x = 0;
|
||||
vecWinPos.y -= 0.5 * iPixelDim;
|
||||
if (vecWinPos.y < 0) vecWinPos.y = 0;
|
||||
|
||||
// read back illumination of this particle from the buffer.
|
||||
glReadBuffer(GL_BACK);
|
||||
glReadPixels(vecWinPos.x, vecWinPos.y, iPixelDim, iPixelDim, GL_RGBA, GL_UNSIGNED_BYTE, c);
|
||||
|
||||
// scattering coefficient vector.
|
||||
Vec4f vecScatter(s_rScatterFactor, s_rScatterFactor, s_rScatterFactor, 1);
|
||||
|
||||
// add up the read back pixels (only need one component -- its grayscale)
|
||||
int iSum = 0;
|
||||
for (int k = 0; k < 4 * iNumPixels; k+=4)
|
||||
iSum += c[k];
|
||||
delete [] c;
|
||||
|
||||
// compute the amount of light scattered to this particle by particles closer to the light.
|
||||
// this is the illumination over the solid angle that we measured (using glReadPixels) times
|
||||
// the scattering coefficient (vecScatter);
|
||||
Vec4f vecScatteredAmount(iSum * rColorScaleFactor,
|
||||
iSum * rColorScaleFactor,
|
||||
iSum * rColorScaleFactor,
|
||||
1 - s_rTransparency);
|
||||
vecScatteredAmount &= vecScatter;
|
||||
|
||||
// the color of th particle (iter) contributed by this light source (pLight) is the
|
||||
// scattered light from the part of the cloud closer to the light, times the diffuse color
|
||||
// of the light source. The alpha is 1 - the uniform transparency of all particles (modulated
|
||||
// by the splat texture).
|
||||
Vec4f vecColor = vecScatteredAmount;
|
||||
vecColor &= pLight->GetDiffuse();
|
||||
vecColor.w = 1 - s_rTransparency;
|
||||
|
||||
// add this color to the list of lit colors for the particle. The contribution from each light
|
||||
// is kept separate because the phase function we apply at runtime depends on the light vector
|
||||
// for each light source separately. This view-dependent effect is impossible without knowing
|
||||
// the amount of light contributed for each light. This, of course, assumes the clouds will
|
||||
// be lit by a reasonably small number of lights (The sun plus some simulation of light reflected
|
||||
// from the sky and / or ground.) This technique works very well for simulating anisotropic
|
||||
// illumination by skylight.
|
||||
if (bReset)
|
||||
{
|
||||
(*iter)->SetBaseColor(s_pMaterial->GetAmbient());
|
||||
(*iter)->ClearLitColors();
|
||||
(*iter)->AddLitColor(vecColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*iter)->AddLitColor(vecColor);
|
||||
}
|
||||
|
||||
// the following computation (scaling of the scattered amount by the phase function) is done
|
||||
// after the lit color is stored so we don't add the scattering to this particle twice.
|
||||
vecScatteredAmount *= 1.5; // rayleigh scattering phase function for angle of zero or 180 = 1.5!
|
||||
|
||||
// clamp the color
|
||||
if (vecScatteredAmount.x > 1) vecScatteredAmount.x = 1;
|
||||
if (vecScatteredAmount.y > 1) vecScatteredAmount.y = 1;
|
||||
if (vecScatteredAmount.z > 1) vecScatteredAmount.z = 1;
|
||||
vecScatteredAmount.w = 1 - s_rTransparency;
|
||||
|
||||
vecScatteredAmount.x = 0.50; vecScatteredAmount.y = 0.60; vecScatteredAmount.z = 0.70;
|
||||
|
||||
// Draw the particle as a texture billboard. Use the scattered light amount as the color to
|
||||
// simulate forward scattering of light by this particle.
|
||||
glBegin(GL_QUADS);
|
||||
DrawQuad(vecParticlePos, cam.X * (*iter)->GetRadius(), cam.Y * (*iter)->GetRadius(), vecScatteredAmount);
|
||||
glEnd();
|
||||
|
||||
//glutSwapBuffers(); // Uncomment this swap buffers to visualize cloud illumination computation.
|
||||
}
|
||||
|
||||
// Note: here we could optionally store the current back buffer as a shadow image
|
||||
// to be projected from the light position onto the scene. This way we can have clouds shadow
|
||||
// the environment.
|
||||
|
||||
// restore matrix stack and viewport.
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glViewport(iOldVP[0], iOldVP[1], iOldVP[2], iOldVP[3]);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::CopyBoundingVolume
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::CopyBoundingVolume() const
|
||||
* @brief Returns a new copy of the SkyMinMaxBox for this cloud.
|
||||
*/
|
||||
SkyMinMaxBox* SkyCloud::CopyBoundingVolume() const
|
||||
{
|
||||
SkyMinMaxBox *pBox = new SkyMinMaxBox();
|
||||
pBox->SetMax(_boundingBox.GetMax());
|
||||
pBox->SetMin(_boundingBox.GetMin());
|
||||
return pBox;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::Load
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::Load(const SkyArchive &archive, float rScale, bool bLocal)
|
||||
* @brief Loads the cloud data from @a archive.
|
||||
*
|
||||
* If @a rScale does not equal 1.0, then the cloud is scaled by an amount rScale.
|
||||
*/
|
||||
SKYRESULT SkyCloud::Load(const SkyArchive &archive,
|
||||
float rScale /* = 1.0f */,
|
||||
bool bLocal /* = false */)
|
||||
{
|
||||
unsigned int iNumParticles;
|
||||
Vec3f vecCenter = Vec3f::ZERO;
|
||||
//Vec3f vecCenter;
|
||||
//float rRadius;
|
||||
//archive.FindVec3f("CldCenter", &vecCenter);
|
||||
//archive.FindFloat32("CldRadius", &rRadius);
|
||||
|
||||
//_boundingBox.SetMin(vecCenter - Vec3f(rRadius, rRadius, rRadius));
|
||||
//_boundingBox.SetMax(vecCenter + Vec3f(rRadius, rRadius, rRadius));
|
||||
|
||||
archive.FindUInt32("CldNumParticles", &iNumParticles);
|
||||
if (!bLocal)
|
||||
archive.FindVec3f("CldCenter", &vecCenter);
|
||||
|
||||
Vec3f *pParticlePositions = new Vec3f[iNumParticles];
|
||||
float *pParticleRadii = new float[iNumParticles];
|
||||
Vec4f *pParticleColors = new Vec4f[iNumParticles];
|
||||
|
||||
unsigned int iNumBytes;
|
||||
archive.FindData("CldParticlePositions", ANY_TYPE, (void**const)&pParticlePositions, &iNumBytes);
|
||||
archive.FindData("CldParticleRadii", ANY_TYPE, (void**const)&pParticleRadii, &iNumBytes);
|
||||
archive.FindData("CldParticleColors", ANY_TYPE, (void**const)&pParticleColors, &iNumBytes);
|
||||
|
||||
for (unsigned int i = 0; i < iNumParticles; ++i)
|
||||
{
|
||||
SkyCloudParticle *pParticle = new SkyCloudParticle((pParticlePositions[i] + vecCenter) * rScale,
|
||||
pParticleRadii[i] * rScale,
|
||||
pParticleColors[i]);
|
||||
_boundingBox.AddPoint(pParticle->GetPosition());
|
||||
|
||||
_particles.push_back(pParticle);
|
||||
}
|
||||
// this is just a bad hack to align cloud field from skyworks with local horizon at KSFO
|
||||
// we need to develop out own scheme for loading and positioning clouds
|
||||
Mat33f rot_mat;
|
||||
Vec3f moveit;
|
||||
|
||||
//moveit.Set( -10000.0, 1500.0, 1500.0 );
|
||||
moveit.Set( 0.0, 0.0, 1050.0 );
|
||||
|
||||
rot_mat.Set( 1, 0, 0,
|
||||
0, 0, -1,
|
||||
0, 1, 0);
|
||||
// flip the y and z axis
|
||||
Rotate( rot_mat );
|
||||
|
||||
// adjust for lon af KSFO -122.357
|
||||
rot_mat.Set( -0.5352f, 0.8447f, 0.0f,
|
||||
-0.8447f, -0.5352f, 0.0f,
|
||||
-0.0f, 0.0f, 1.0f);
|
||||
|
||||
Rotate( rot_mat );
|
||||
|
||||
// and about x for latitude 37.6135
|
||||
rot_mat.Set( 1.0f, 0.0, 0.0f,
|
||||
0.0f, 0.7921f, -0.6103f,
|
||||
0.0f, 0.6103f, 0.7921f);
|
||||
|
||||
Rotate( rot_mat );
|
||||
|
||||
Translate( moveit );
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::Save
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::Save(SkyArchive &archive) const
|
||||
* @brief Saves the cloud data to @a archive.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyCloud::Save FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyCloud::Save(SkyArchive &archive) const
|
||||
{
|
||||
SkyArchive myArchive("Cloud");
|
||||
//myArchive.AddVec3f("CldCenter", _center);
|
||||
//myArchive.AddFloat32("CldRadius", _boundingBox.GetRadius());
|
||||
myArchive.AddUInt32("CldNumParticles", _particles.size());
|
||||
|
||||
// make temp arrays
|
||||
Vec3f *pParticlePositions = new Vec3f[_particles.size()];
|
||||
float *pParticleRadii = new float[_particles.size()];
|
||||
Vec4f *pParticleColors = new Vec4f[_particles.size()];
|
||||
|
||||
unsigned int i = 0;
|
||||
|
||||
for (ParticleConstIterator iter = _particles.begin(); iter != _particles.end(); ++iter, ++i)
|
||||
{
|
||||
pParticlePositions[i] = (*iter)->GetPosition(); // position around origin
|
||||
pParticleRadii[i] = (*iter)->GetRadius();
|
||||
pParticleColors[i] = (*iter)->GetBaseColor();
|
||||
}
|
||||
|
||||
myArchive.AddData("CldParticlePositions",
|
||||
ANY_TYPE,
|
||||
pParticlePositions,
|
||||
sizeof(Vec3f),
|
||||
_particles.size());
|
||||
|
||||
myArchive.AddData("CldParticleRadii",
|
||||
ANY_TYPE,
|
||||
pParticleRadii,
|
||||
sizeof(float),
|
||||
_particles.size());
|
||||
|
||||
myArchive.AddData("CldParticleColors",
|
||||
ANY_TYPE,
|
||||
pParticleColors,
|
||||
sizeof(Vec3f),
|
||||
_particles.size());
|
||||
|
||||
archive.AddArchive(myArchive);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::Rotate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::Rotate(const Mat33f& rot)
|
||||
* @brief @todo <WRITE BRIEF SkyCloud::Rotate DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyCloud::Rotate FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyCloud::Rotate(const Mat33f& rot)
|
||||
{
|
||||
_boundingBox.Clear();
|
||||
for (int i = 0; i < _particles.size(); ++i)
|
||||
{
|
||||
_particles[i]->SetPosition(rot * _particles[i]->GetPosition());
|
||||
_boundingBox.AddPoint(_particles[i]->GetPosition());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::Translate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::Translate(const Vec3f& trans)
|
||||
* @brief @todo <WRITE BRIEF SkyCloud::Translate DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyCloud::Translate FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyCloud::Translate(const Vec3f& trans)
|
||||
{
|
||||
for (int i = 0; i < _particles.size(); ++i)
|
||||
{
|
||||
_particles[i]->SetPosition(_particles[i]->GetPosition() + trans);
|
||||
}
|
||||
_boundingBox.SetMax(_boundingBox.GetMax() + trans);
|
||||
_boundingBox.SetMin(_boundingBox.GetMin() + trans);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::Scale
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::Scale(const float scale)
|
||||
* @brief @todo <WRITE BRIEF SkyCloud::Scale DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyCloud::Scale FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyCloud::Scale(const float scale)
|
||||
{
|
||||
_boundingBox.Clear();
|
||||
for (int i = 0; i < _particles.size(); ++i)
|
||||
{
|
||||
_particles[i]->SetPosition(_particles[i]->GetPosition() * scale);
|
||||
_boundingBox.AddPoint(_particles[i]->GetPosition());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::_SortParticles
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::_SortParticles(const Vec3f& vecViewDir, const Vec3f& sortPoint, SortDirection dir)
|
||||
* @brief Sorts the cloud particles in the direction specified by @a dir.
|
||||
*
|
||||
* @vecSortPoint is assumed to already be transformed into the basis space of the cloud.
|
||||
*/
|
||||
void SkyCloud::_SortParticles(const Vec3f& vecViewDir,
|
||||
const Vec3f& vecSortPoint,
|
||||
SortDirection dir)
|
||||
{
|
||||
Vec3f partPos;
|
||||
for (int i = 0; i < _particles.size(); ++i)
|
||||
{
|
||||
partPos = _particles[i]->GetPosition();
|
||||
partPos -= vecSortPoint;
|
||||
_particles[i]->SetSquareSortDistance(partPos * vecViewDir);//partPos.LengthSqr());
|
||||
}
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case SKY_CLOUD_SORT_TOWARD:
|
||||
std::sort(_particles.begin(), _particles.end(), _towardComparator);
|
||||
break;
|
||||
case SKY_CLOUD_SORT_AWAY:
|
||||
std::sort(_particles.begin(), _particles.end(), _awayComparator);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : EvalHermite
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* EvalHermite(float pA, float pB, float vA, float vB, float u)
|
||||
* @brief Evaluates Hermite basis functions for the specified coefficients.
|
||||
*/
|
||||
inline float EvalHermite(float pA, float pB, float vA, float vB, float u)
|
||||
{
|
||||
float u2=(u*u), u3=u2*u;
|
||||
float B0 = 2*u3 - 3*u2 + 1;
|
||||
float B1 = -2*u3 + 3*u2;
|
||||
float B2 = u3 - 2*u2 + u;
|
||||
float B3 = u3 - u;
|
||||
return( B0*pA + B1*pB + B2*vA + B3*vB );
|
||||
}
|
||||
|
||||
// NORMALIZED GAUSSIAN INTENSITY MAP (N must be a power of 2)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : CreateGaussianMap
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* CreateGaussianMap(int N)
|
||||
*
|
||||
* Creates a 2D gaussian image using a hermite surface.
|
||||
*/
|
||||
unsigned char* CreateGaussianMap(int N)
|
||||
{
|
||||
float *M = new float[2*N*N];
|
||||
unsigned char *B = new unsigned char[4*N*N];
|
||||
float X,Y,Y2,Dist;
|
||||
float Incr = 2.0f/N;
|
||||
int i=0;
|
||||
int j = 0;
|
||||
Y = -1.0f;
|
||||
for (int y=0; y<N; y++, Y+=Incr)
|
||||
{
|
||||
Y2=Y*Y;
|
||||
X = -1.0f;
|
||||
for (int x=0; x<N; x++, X+=Incr, i+=2, j+=4)
|
||||
{
|
||||
Dist = (float)sqrt(X*X+Y2);
|
||||
if (Dist>1) Dist=1;
|
||||
M[i+1] = M[i] = EvalHermite(0.4f,0,0,0,Dist);// * (1 - noise);
|
||||
B[j+3] = B[j+2] = B[j+1] = B[j] = (unsigned char)(M[i] * 255);
|
||||
}
|
||||
}
|
||||
SAFE_DELETE_ARRAY(M);
|
||||
return(B);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::_CreateSplatTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::_CreateSplatTexture(unsigned int iResolution)
|
||||
* @brief Creates the texture map used for cloud particles.
|
||||
*/
|
||||
void SkyCloud::_CreateSplatTexture(unsigned int iResolution)
|
||||
{
|
||||
unsigned char *splatTexture = CreateGaussianMap(iResolution);
|
||||
SkyTexture texture;
|
||||
TextureManager::InstancePtr()->Create2DTextureObject(texture, iResolution, iResolution,
|
||||
GL_RGBA, splatTexture);
|
||||
|
||||
s_pMaterial->SetTexture(0, GL_TEXTURE_2D, texture);
|
||||
s_pShadeMaterial->SetTexture(0, GL_TEXTURE_2D, texture);
|
||||
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
s_pShadeMaterial->SetTextureParameter(0, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
s_pShadeMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
s_pShadeMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
s_pMaterial->EnableTexture(0, true);
|
||||
s_pShadeMaterial->EnableTexture(0, true);
|
||||
|
||||
SAFE_DELETE_ARRAY(splatTexture);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloud::_PhaseFunction
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloud::_PhaseFunction(const Vec3f& vecLightDir, const Vec3f& vecViewDir)
|
||||
* @brief Computes the phase (scattering) function of the given light and view directions.
|
||||
*
|
||||
* A phase function is a transfer function that determines, for any angle between incident
|
||||
* and outgoing directions, how much of the incident light intensity will be
|
||||
* scattered in the outgoing direction. For example, scattering by very small
|
||||
* particles such as those found in clear air, can be approximated using <i>Rayleigh
|
||||
* scattering</i>. The phase function for Rayleigh scattering is
|
||||
* p(q) = 0.75*(1 + cos<sup>2</sup>(q)), where q is the angle between incident
|
||||
* and scattered directions. Scattering by larger particles is more complicated.
|
||||
* It is described by Mie scattering theory. Cloud particles are more in the regime
|
||||
* of Mie scattering than Rayleigh scattering. However, we obtain good visual
|
||||
* results by using the simpler Rayleigh scattering phase function as an approximation.
|
||||
*/
|
||||
float SkyCloud::_PhaseFunction(const Vec3f& vecLightDir, const Vec3f& vecViewDir)
|
||||
{
|
||||
float rCosAlpha = vecLightDir * vecViewDir;
|
||||
return .75f * (1 + rCosAlpha * rCosAlpha); // rayleigh scattering = (3/4) * (1+cos^2(alpha))
|
||||
175
simgear/scene/sky/clouds3d/SkyCloud.hpp
Normal file
175
simgear/scene/sky/clouds3d/SkyCloud.hpp
Normal file
@@ -0,0 +1,175 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyCloud.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 SkyCloud.hpp
|
||||
*
|
||||
* Interface definition for class SkyCloud.
|
||||
*/
|
||||
#ifndef __SKYCLOUD_HPP__
|
||||
#define __SKYCLOUD_HPP__
|
||||
|
||||
// warning for truncation of template name for browse info
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "SkyCloudParticle.hpp"
|
||||
#include "SkyRenderable.hpp"
|
||||
#include "SkyMinMaxBox.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "SkyArchive.hpp"
|
||||
#include "mat33.hpp"
|
||||
|
||||
class SkyMaterial;
|
||||
class SkyLight;
|
||||
class SkyRenderableInstance;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyCloud
|
||||
* @brief A renderable that represents a volumetric cloud.
|
||||
*
|
||||
* A SkyCloud is made up of particles, and is rendered using particle splatting.
|
||||
* SkyCloud is intended to represent realisticly illuminated volumetric clouds
|
||||
* through which the viewer and / or other objects can realistically pass.
|
||||
*
|
||||
* Realistic illumination is performed by the Illuminate() method, which uses a
|
||||
* graphics hardware algorithm to precompute and store multiple forward scattering
|
||||
* of light by each particle in the cloud. Clouds may be illuminated by multiple
|
||||
* light sources. The light from each source is precomputed and stored at each
|
||||
* particle. Each light's contribution is stored separately so that we can
|
||||
* compute view-dependent (anisotropic) scattering at run-time. This gives realistic
|
||||
* effects such as the "silver lining" that you see on a thick cloud when it crosses
|
||||
* in front of the sun.
|
||||
*
|
||||
* At run-time, the cloud is rendered by drawing each particle as a view-oriented
|
||||
* textured billboard (splat), with lighting computed from the precomputed illumination
|
||||
* as follows: for each light source <i>l</i>, compute the scattering function (See _PhaseFunction())
|
||||
* based on the view direction and the direction from the particle to the viewer. This
|
||||
* scattering function modulates the lighting contribution of <i>l</i>. The modulated
|
||||
* contributions are then added and used to modulate the color of the particle. The result
|
||||
* is view-dependent scattering.
|
||||
*
|
||||
* If the phase (scattering) function is not enabled (see IsPhaseFunctionEnabled()), then the
|
||||
* contributions of the light sources are simply added.
|
||||
*
|
||||
* @see SkyRenderableInstanceCloud, SkyCloudParticle, SkySceneManager
|
||||
*/
|
||||
class SkyCloud : public SkyRenderable
|
||||
{
|
||||
public:
|
||||
SkyCloud();
|
||||
virtual ~SkyCloud();
|
||||
|
||||
virtual SKYRESULT Update(const Camera &cam, SkyRenderableInstance* pInstance = NULL);
|
||||
|
||||
virtual SKYRESULT Display(const Camera &camera, SkyRenderableInstance *pInstance = NULL);
|
||||
|
||||
SKYRESULT DisplaySplit(const Camera &camera,
|
||||
const Vec3f &vecSplitPoint,
|
||||
bool bBackHalf,
|
||||
SkyRenderableInstance *pInstance = NULL);
|
||||
|
||||
SKYRESULT Illuminate( SkyLight *pLight,
|
||||
SkyRenderableInstance* pInstance,
|
||||
bool bReset = false);
|
||||
|
||||
virtual SkyMinMaxBox* CopyBoundingVolume() const;
|
||||
|
||||
//! Enables the use of a scattering function for anisotropic light scattering.
|
||||
void EnablePhaseFunction(bool bEnable) { _bUsePhaseFunction = bEnable; }
|
||||
//! Returns true if the use of a scattering function is enabled.
|
||||
bool IsPhaseFunctionEnabled() const { return _bUsePhaseFunction; }
|
||||
|
||||
SKYRESULT Save(SkyArchive &archive) const;
|
||||
SKYRESULT Load(const SkyArchive &archive, float rScale = 1.0f, bool bLocal = false);
|
||||
|
||||
void Rotate(const Mat33f& rot);
|
||||
void Translate(const Vec3f& trans);
|
||||
void Scale(const float scale);
|
||||
|
||||
protected: // methods
|
||||
enum SortDirection
|
||||
{
|
||||
SKY_CLOUD_SORT_TOWARD,
|
||||
SKY_CLOUD_SORT_AWAY
|
||||
};
|
||||
|
||||
void _SortParticles( const Vec3f& vecViewDir,
|
||||
const Vec3f& vecSortPoint,
|
||||
SortDirection dir);
|
||||
|
||||
void _CreateSplatTexture( unsigned int iResolution);
|
||||
|
||||
float _PhaseFunction(const Vec3f& vecLightDir, const Vec3f& vecViewDir);
|
||||
|
||||
protected: // datatypes
|
||||
typedef std::vector<SkyCloudParticle*> ParticleArray;
|
||||
typedef ParticleArray::iterator ParticleIterator;
|
||||
typedef ParticleArray::const_iterator ParticleConstIterator;
|
||||
|
||||
typedef std::vector<Vec3f> DirectionArray;
|
||||
typedef DirectionArray::iterator DirectionIterator;
|
||||
|
||||
class ParticleAwayComparator
|
||||
{
|
||||
public:
|
||||
bool operator()(SkyCloudParticle* pA, SkyCloudParticle *pB)
|
||||
{
|
||||
return ((*pA) < (*pB));
|
||||
}
|
||||
};
|
||||
|
||||
class ParticleTowardComparator
|
||||
{
|
||||
public:
|
||||
bool operator()(SkyCloudParticle* pA, SkyCloudParticle *pB)
|
||||
{
|
||||
return ((*pA) > (*pB));
|
||||
}
|
||||
};
|
||||
|
||||
protected: // data
|
||||
ParticleArray _particles; // cloud particles
|
||||
// particle sorting functors for STL sort.
|
||||
ParticleTowardComparator _towardComparator;
|
||||
ParticleAwayComparator _awayComparator;
|
||||
|
||||
DirectionArray _lightDirections; // light directions in cloud space (cached)
|
||||
|
||||
SkyMinMaxBox _boundingBox; // bounds
|
||||
|
||||
bool _bUsePhaseFunction;
|
||||
|
||||
Vec3f _vecLastSortViewDir;
|
||||
Vec3f _vecLastSortCamPos;
|
||||
Vec3f _vecSortPos;
|
||||
|
||||
float _rSplitDistance;
|
||||
|
||||
static SkyMaterial *s_pMaterial; // shared material for clouds.
|
||||
static SkyMaterial *s_pShadeMaterial;// shared material for illumination pass.
|
||||
static unsigned int s_iShadeResolution; // the resolution of the viewport used for shading
|
||||
static float s_rAlbedo; // the cloud albedo
|
||||
static float s_rExtinction; // the extinction of the clouds
|
||||
static float s_rTransparency; // the transparency of the clouds
|
||||
static float s_rScatterFactor; // How much the clouds scatter
|
||||
static float s_rSortAngleErrorTolerance; // how far the view must turn to cause a resort.
|
||||
static float s_rSortSquareDistanceTolerance; // how far the view must move to cause a resort.
|
||||
};
|
||||
|
||||
#endif //__SKYCLOUD_HPP__
|
||||
175
simgear/scene/sky/clouds3d/SkyCloudParticle.hpp
Normal file
175
simgear/scene/sky/clouds3d/SkyCloudParticle.hpp
Normal file
@@ -0,0 +1,175 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyCloudParticle.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 SkyCloudParticle.hpp
|
||||
*
|
||||
* Definition of a simple cloud particle class.
|
||||
*/
|
||||
#ifndef __SKYCLOUDPARTICLE_HPP__
|
||||
#define __SKYCLOUDPARTICLE_HPP__
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include "vec4f.hpp"
|
||||
#include <vector>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyCloudParticle
|
||||
* @brief A class for particles that make up a cloud.
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyCloudParticle
|
||||
{
|
||||
public:
|
||||
inline SkyCloudParticle();
|
||||
inline SkyCloudParticle(const Vec3f& pos,
|
||||
float rRadius,
|
||||
const Vec4f& baseColor,
|
||||
float rTransparency = 0);
|
||||
inline ~SkyCloudParticle();
|
||||
|
||||
//! Returns the radius of the particle.
|
||||
float GetRadius() const { return _rRadius; }
|
||||
//! Returns the transparency of the particle.
|
||||
float GetTransparency() const { return _rTransparency; }
|
||||
//! Returns the position of the particle.
|
||||
const Vec3f& GetPosition() const { return _vecPosition; }
|
||||
//! Returns the base color of the particle. This is often used for ambient color.
|
||||
const Vec4f& GetBaseColor() const { return _vecBaseColor; }
|
||||
//! Returns the number of light contributions to this particle's color.
|
||||
unsigned int GetNumLitColors() const { return _vecLitColors.size(); }
|
||||
//! Returns the light contribution to the color of this particle from light @a index.
|
||||
inline const Vec4f& GetLitColor(unsigned int index) const;
|
||||
//! Returns the square distance from the sort position used for the operator< in sorts / splits.
|
||||
float GetSquareSortDistance() const { return _rSquareSortDistance; }
|
||||
|
||||
//! Sets the radius of the particle.
|
||||
void SetRadius(float rad) { _rRadius = rad; }
|
||||
//! Returns the transparency of the particle.
|
||||
void SetTransparency(float trans) { _rTransparency = trans; }
|
||||
//! Sets the position of the particle.
|
||||
void SetPosition(const Vec3f& pos) { _vecPosition = pos; }
|
||||
//! Sets the base color of the particle. This is often used for ambient color.
|
||||
void SetBaseColor(const Vec4f& col) { _vecBaseColor = col; }
|
||||
//! Sets the light contribution to the color of this particle from light @a index.
|
||||
void AddLitColor(const Vec4f& col) { _vecLitColors.push_back(col); }
|
||||
//! Clears the list of light contributions.
|
||||
void ClearLitColors() { _vecLitColors.clear(); }
|
||||
//! Sets the square distance from the sort position used for the operator< in sorts.
|
||||
void SetSquareSortDistance(float rSquareDistance) { _rSquareSortDistance = rSquareDistance; }
|
||||
|
||||
//! This operator is used to sort particle arrays from nearest to farthes.
|
||||
bool operator<(const SkyCloudParticle& p) const
|
||||
{
|
||||
return (_rSquareSortDistance < p._rSquareSortDistance);
|
||||
}
|
||||
|
||||
//! This operator is used to sort particle arrays from farthest to nearest.
|
||||
bool operator>(const SkyCloudParticle& p) const
|
||||
{
|
||||
return (_rSquareSortDistance > p._rSquareSortDistance);
|
||||
}
|
||||
|
||||
protected:
|
||||
float _rRadius;
|
||||
float _rTransparency;
|
||||
Vec3f _vecPosition;
|
||||
Vec4f _vecBaseColor;
|
||||
std::vector<Vec4f> _vecLitColors;
|
||||
Vec3f _vecEye;
|
||||
|
||||
// for sorting particles during shading
|
||||
float _rSquareSortDistance;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloudParticle::SkyCloudParticle
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloudParticle::SkyCloudParticle()
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
inline SkyCloudParticle::SkyCloudParticle()
|
||||
: _rRadius(0),
|
||||
_rTransparency(0),
|
||||
_vecPosition(0, 0, 0),
|
||||
_vecBaseColor(0, 0, 0, 1),
|
||||
_vecEye(0, 0, 0),
|
||||
_rSquareSortDistance(0)
|
||||
{
|
||||
_vecLitColors.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloudParticle::SkyCloudParticle
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloudParticle::SkyCloudParticle(const Vec3f& pos, float rRadius, const Vec4f& baseColor, float rTransparency)
|
||||
* @brief Constructor.
|
||||
*/
|
||||
inline SkyCloudParticle::SkyCloudParticle(const Vec3f& pos,
|
||||
float rRadius,
|
||||
const Vec4f& baseColor,
|
||||
float rTransparency /* = 0 */)
|
||||
: _rRadius(rRadius),
|
||||
_rTransparency(rTransparency),
|
||||
_vecPosition(pos),
|
||||
_vecBaseColor(baseColor),
|
||||
_vecEye(0, 0, 0),
|
||||
_rSquareSortDistance(0)
|
||||
{
|
||||
_vecLitColors.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloudParticle::~SkyCloudParticle
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloudParticle::~SkyCloudParticle()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
inline SkyCloudParticle::~SkyCloudParticle()
|
||||
{
|
||||
_vecLitColors.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Vec4f& SkyCloudParticle::GetLitColor
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Vec4f& SkyCloudParticle::GetLitColor(unsigned int index) const
|
||||
* @brief Returns the lit color specified by index.
|
||||
*
|
||||
* If the index is out of range, returns a zero vector.
|
||||
*/
|
||||
inline const Vec4f& SkyCloudParticle::GetLitColor(unsigned int index) const
|
||||
{
|
||||
if (index <= _vecLitColors.size())
|
||||
return _vecLitColors[index];
|
||||
else
|
||||
return Vec4f::ZERO;
|
||||
}
|
||||
|
||||
#endif //__SKYCLOUDPARTICLE_HPP__
|
||||
283
simgear/scene/sky/clouds3d/SkyContext.cpp
Normal file
283
simgear/scene/sky/clouds3d/SkyContext.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyContext.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyContext.cpp
|
||||
*
|
||||
* Graphics Context Interface. Initializes GL extensions, etc.
|
||||
*/
|
||||
#include <GL/glut.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
//#include "extgl.h"
|
||||
|
||||
#include "SkyContext.hpp"
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkyMaterial.hpp"
|
||||
#include "SkyTextureState.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::SkyContext
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::SkyContext()
|
||||
* @brief Constructor.
|
||||
*
|
||||
*/
|
||||
SkyContext::SkyContext()
|
||||
{
|
||||
_iWidth = glutGet(GLUT_WINDOW_WIDTH);
|
||||
_iHeight = glutGet(GLUT_WINDOW_HEIGHT);
|
||||
|
||||
// materials and structure classes
|
||||
AddCurrentGLContext();
|
||||
// Initialize all the extensions and load the functions - JW (file is extgl.c)
|
||||
#ifdef _WIN32
|
||||
glInitialize();
|
||||
InitializeExtension("GL_ARB_multitexture");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::~SkyContext
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::~SkyContext()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkyContext::~SkyContext()
|
||||
{
|
||||
// delete map of materials
|
||||
for (ContextMaterialIterator cmi = _currentMaterials.begin(); cmi != _currentMaterials.end(); ++cmi)
|
||||
{
|
||||
SAFE_DELETE(cmi->second);
|
||||
}
|
||||
_currentMaterials.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::ProcessReshapeEvent
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::ProcessReshapeEvent(int iWidth, int iHeight)
|
||||
* @brief Handles window resize events, and notifies all context listeners of the event.
|
||||
*/
|
||||
SKYRESULT SkyContext::ProcessReshapeEvent(int iWidth, int iHeight)
|
||||
{
|
||||
_iWidth = iWidth;
|
||||
_iHeight = iHeight;
|
||||
return _SendMessage(SKYCONTEXT_MESSAGE_RESHAPE);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::InitializeExtensions
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::InitializeExtensions(const char *pExtensionNames)
|
||||
* @brief Initializes GL extension specified by @a pExtensionNames.
|
||||
*/
|
||||
SKYRESULT SkyContext::InitializeExtension(const char *pExtensionName)
|
||||
{ /***
|
||||
if (!QueryExtension(pExtensionName)) // see query search function defined in extgl.c
|
||||
{
|
||||
SkyTrace(
|
||||
"ERROR: SkyContext::InitializeExtenstions: The following extensions are unsupported: %s\n",
|
||||
pExtensionName);
|
||||
return SKYRESULT_FAIL;
|
||||
} **/
|
||||
//set this false to catch all the extensions until we come up with a linux version
|
||||
return SKYRESULT_FAIL;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::GetCurrentMaterial
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::GetCurrentMaterial()
|
||||
* @brief Returns the current cached material state that is active in this OpenGL context.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyContext::GetCurrentMaterial FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SkyMaterial* SkyContext::GetCurrentMaterial()
|
||||
{
|
||||
ContextMaterialIterator cmi = _currentMaterials.find(glXGetCurrentContext());
|
||||
if (_currentMaterials.end() != cmi)
|
||||
return cmi->second;
|
||||
else
|
||||
{
|
||||
SkyTrace("SkyContext::GetCurrentMaterial(): Invalid context.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::GetCurrentTextureState
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::GetCurrentTextureState()
|
||||
* @brief Returns the current cached texture state that is active in this OpenGL context.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyContext::GetCurrentTextureState FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SkyTextureState* SkyContext::GetCurrentTextureState()
|
||||
{
|
||||
ContextTextureStateIterator ctsi = _currentTextureState.find(glXGetCurrentContext());
|
||||
if (_currentTextureState.end() != ctsi)
|
||||
return ctsi->second;
|
||||
else
|
||||
{
|
||||
SkyTrace("SkyContext::GetCurrentTextureState(): Invalid context.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::AddCurrentGLContext
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::AddCurrentGLContext()
|
||||
* @brief @todo <WRITE BRIEF SkyContext::AddCurrentGLContext DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyContext::AddCurrentGLContext FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyContext::AddCurrentGLContext()
|
||||
{
|
||||
SkyMaterial *pCurrentMaterial = new SkyMaterial;
|
||||
_currentMaterials.insert(std::make_pair(glXGetCurrentContext(), pCurrentMaterial));
|
||||
|
||||
SkyTextureState *pCurrentTS = new SkyTextureState;
|
||||
_currentTextureState.insert(std::make_pair(glXGetCurrentContext() , pCurrentTS));
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::Register
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::Register(Listener* pListener, int priority)
|
||||
* @brief Register with the messaging system to handle notification of mode changes
|
||||
*/
|
||||
SKYRESULT SkyContext::Register(Listener* pListener, int priority)
|
||||
{
|
||||
std::list<ListenerPair>::iterator iter =
|
||||
std::find_if(_listeners.begin(), _listeners.end(), _ListenerPred(pListener));
|
||||
if (iter == _listeners.end())
|
||||
{
|
||||
// insert the listener, sorted by priority
|
||||
for (iter=_listeners.begin(); iter != _listeners.end(); ++iter)
|
||||
{
|
||||
if (priority <= iter->first)
|
||||
{
|
||||
_listeners.insert(iter, ListenerPair(priority, pListener));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iter == _listeners.end())
|
||||
{
|
||||
_listeners.push_back(ListenerPair(priority, pListener));
|
||||
}
|
||||
// Send a message to the pListener if we are already active so it
|
||||
// can intialize itself
|
||||
//FAIL_RETURN(pListener->GraphicsReshapeEvent());
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyContext: Listener is already registered");
|
||||
}
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyContext::UnRegister
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyContext::UnRegister(Listener *pListener)
|
||||
* @brief UnRegister with the messaging system.
|
||||
*/
|
||||
SKYRESULT SkyContext::UnRegister(Listener *pListener)
|
||||
{
|
||||
std::list<ListenerPair>::iterator iter =
|
||||
std::find_if(_listeners.begin(), _listeners.end(), _ListenerPred(pListener));
|
||||
if (iter == _listeners.end())
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyContext: Listener is not registered");
|
||||
}
|
||||
else
|
||||
{
|
||||
_listeners.erase(iter);
|
||||
}
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn SkyContext::_SendMessage(SkyMessageType msg)
|
||||
* @brief Messaging system to handle notification of mode changes
|
||||
*/
|
||||
SKYRESULT SkyContext::_SendMessage(SkyMessageType msg)
|
||||
{
|
||||
if (_listeners.size() == 0) return SKYRESULT_OK;
|
||||
|
||||
bool failure = false;
|
||||
SKYRESULT res, failureCode = SKYRESULT_OK;
|
||||
std::list<ListenerPair>::iterator iter;
|
||||
SKYRESULT (Listener::*fnPtr)() = NULL;
|
||||
|
||||
// Make a pointer to the appropriate method
|
||||
switch (msg)
|
||||
{
|
||||
case SKYCONTEXT_MESSAGE_RESHAPE: fnPtr = &Listener::GraphicsReshapeEvent; break;
|
||||
}
|
||||
|
||||
// Notify all listeners of the messag. catch failures, but still call everyone else.
|
||||
// !!! WRH HORRIBLE HACK must cache the current "end" because these functions could register new listeners
|
||||
std::list<ListenerPair>::iterator endIter = _listeners.end();
|
||||
endIter--;
|
||||
|
||||
iter = _listeners.begin();
|
||||
do
|
||||
{
|
||||
if ( SKYFAILED( res = (iter->second->*fnPtr)() ) )
|
||||
{
|
||||
failureCode = res;
|
||||
SkyTrace("SkyContext: SendMessage failed");
|
||||
}
|
||||
if (iter == endIter) break;
|
||||
iter++;
|
||||
} while (true);
|
||||
|
||||
FAIL_RETURN(failureCode);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
141
simgear/scene/sky/clouds3d/SkyContext.hpp
Normal file
141
simgear/scene/sky/clouds3d/SkyContext.hpp
Normal file
@@ -0,0 +1,141 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyContext.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 SkyContext.hpp
|
||||
*
|
||||
* Graphics Context Interface. Initializes GL extensions, etc.
|
||||
*/
|
||||
#ifndef __SKYCONTEXT_HPP__
|
||||
#define __SKYCONTEXT_HPP__
|
||||
|
||||
// warning for truncation of template name for browse info
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "SkySingleton.hpp"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "extgl.h"
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
// ifdef to replace windows stuff for handles-JW
|
||||
typedef void *HANDLE;
|
||||
typedef HANDLE *PHANDLE;
|
||||
#define DECLARE_HANDLE(n) typedef HANDLE n
|
||||
|
||||
DECLARE_HANDLE(HGLRC);
|
||||
// end of ifdef
|
||||
|
||||
class SkyContext;
|
||||
class SkyMaterial;
|
||||
class SkyTextureState;
|
||||
|
||||
//! Graphics Context Singleton declaration.
|
||||
/*! The Context must be created by calling GraphicsContext::Instantiate(). */
|
||||
typedef SkySingleton<SkyContext> GraphicsContext;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyContext
|
||||
* @brief A manager / proxy for the state of OpenGL contexts.
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyContext
|
||||
{
|
||||
public: // datatypes
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class Listener
|
||||
* @brief Inherit this class and overide its methods to be notified of context events.
|
||||
*/
|
||||
class Listener
|
||||
{
|
||||
public:
|
||||
|
||||
//! Handle a change in the dimensions of the graphics window.
|
||||
virtual SKYRESULT GraphicsReshapeEvent() { return SKYRESULT_OK; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum SkyMessageType messages that the context can generate for it's listeners.
|
||||
*/
|
||||
enum SkyMessageType
|
||||
{
|
||||
SKYCONTEXT_MESSAGE_RESHAPE,
|
||||
SKYCONTEXT_MESSAGE_COUNT
|
||||
};
|
||||
|
||||
public: // methods
|
||||
|
||||
SKYRESULT ProcessReshapeEvent(int iWidth, int iHeight);
|
||||
SKYRESULT InitializeExtension(const char *pExtensionName);
|
||||
|
||||
//! Returns the current dimensions of the window.
|
||||
void GetWindowSize(int &iWidth, int &iHeight) { iWidth = _iWidth; iHeight = _iHeight; }
|
||||
|
||||
SkyMaterial* GetCurrentMaterial();
|
||||
SkyTextureState* GetCurrentTextureState();
|
||||
|
||||
SKYRESULT AddCurrentGLContext();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Register with the messaging system to handle notification of mode changes
|
||||
//------------------------------------------------------------------------------
|
||||
SKYRESULT Register(Listener *pListener, int priority = 0);
|
||||
SKYRESULT UnRegister(Listener *pLlistener);
|
||||
|
||||
protected: // methods
|
||||
SkyContext();
|
||||
~SkyContext();
|
||||
|
||||
protected: // data
|
||||
int _iWidth;
|
||||
int _iHeight;
|
||||
|
||||
typedef std::map<HGLRC, SkyMaterial*> ContextMaterialMap;
|
||||
typedef ContextMaterialMap::iterator ContextMaterialIterator;
|
||||
typedef std::map<HGLRC, SkyTextureState*> ContextTextureStateMap;
|
||||
typedef ContextTextureStateMap::iterator ContextTextureStateIterator;
|
||||
|
||||
ContextMaterialMap _currentMaterials;
|
||||
ContextTextureStateMap _currentTextureState;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Messaging system to handle notification of mode changes
|
||||
//------------------------------------------------------------------------------
|
||||
typedef std::pair<int, Listener*> ListenerPair;
|
||||
class _ListenerPred
|
||||
{
|
||||
public:
|
||||
_ListenerPred(const Listener* l) { _l = l; }
|
||||
bool operator()(const ListenerPair& pair) { return pair.second == _l; }
|
||||
protected:
|
||||
const Listener *_l;
|
||||
};
|
||||
|
||||
SKYRESULT _SendMessage(SkyMessageType msg);
|
||||
std::list<ListenerPair> _listeners;
|
||||
|
||||
};
|
||||
|
||||
#endif //__SKYCONTEXT_HPP__
|
||||
65
simgear/scene/sky/clouds3d/SkyControlled.hpp
Normal file
65
simgear/scene/sky/clouds3d/SkyControlled.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyControlled.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 SkyControlled.hpp
|
||||
*
|
||||
* Interface definition for controlled objects.
|
||||
*/
|
||||
#ifndef __SKYCONTROLLED_HPP__
|
||||
#define __SKYCONTROLLED_HPP__
|
||||
|
||||
//#include "BHXController.hpp"
|
||||
|
||||
template<typename ControlStateType> class SkyController;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyControlled
|
||||
* @brief A base class defining an interface for controlled objects.
|
||||
*
|
||||
* This class abstracts the control of objects into a simple interface that a
|
||||
* class may inherit that allows it to be controlled by SkyController objects.
|
||||
* A class simply inherits from SkyControlled, which forces the class to implement
|
||||
* the method UpdateStateFromControls(). This method usually uses the SkyController
|
||||
* object passed to SetController() to query the input state via
|
||||
* SkyController::GetControlState().
|
||||
*
|
||||
* @see SkyController
|
||||
*/
|
||||
template<typename ControlStateType>
|
||||
class SkyControlled
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
SkyControlled() { _pController = NULL; }
|
||||
//! Destructor
|
||||
virtual ~SkyControlled() { _pController = NULL; }
|
||||
|
||||
//! Sets the controller which will control this controlled object.
|
||||
void SetController(SkyController<ControlStateType> *pController) { _pController = pController; }
|
||||
|
||||
//! Updates the state of the controlled object based on the controls (received from the controller).
|
||||
virtual SKYRESULT UpdateStateFromControls(SKYTIME timeStep) = 0;
|
||||
|
||||
protected:
|
||||
SkyController<ControlStateType> *_pController;
|
||||
ControlStateType _controlState;
|
||||
};
|
||||
|
||||
#endif //__SKYCONTROLLED_HPP__
|
||||
56
simgear/scene/sky/clouds3d/SkyController.hpp
Normal file
56
simgear/scene/sky/clouds3d/SkyController.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyController.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 SkyController.hpp
|
||||
*
|
||||
* Abstract base class for game object controllers.
|
||||
*/
|
||||
#ifndef __SKYCONTROLLER_HPP__
|
||||
#define __SKYCONTROLLER_HPP__
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyController
|
||||
* @brief A class that defines an interface for translating general control input into game object control.
|
||||
*
|
||||
* This class abstracts game object control from specific control input, such
|
||||
* as via user interface devices or via artificial intelligence. Subclasses of
|
||||
* this class implement the method GetControlState() so that objects controlled
|
||||
* by an instance of a SkyController can query the control state that determines
|
||||
* their actions. The object need not know whether it is controlled by a human
|
||||
* or the computer since either controller provides it the same interface.
|
||||
*
|
||||
* @see SkyControlled
|
||||
*/
|
||||
template <typename ControlStateType>
|
||||
class SkyController
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
SkyController() {}
|
||||
//! Destructor.
|
||||
virtual ~SkyController() {}
|
||||
|
||||
//! Fills out the control state structure passed in with the current state of controls.
|
||||
virtual SKYRESULT GetControlState(ControlStateType &controlState) = 0;
|
||||
};
|
||||
|
||||
#endif //__SKYCONTROLLER_HPP__
|
||||
278
simgear/scene/sky/clouds3d/SkyDynamicTextureManager.cpp
Normal file
278
simgear/scene/sky/clouds3d/SkyDynamicTextureManager.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyDynamicTextureManager.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyDynamicTextureManager.cpp
|
||||
*
|
||||
* Implementation of a repository for check out and check in of dynamic textures.
|
||||
*/
|
||||
|
||||
#pragma warning( disable : 4786 )
|
||||
|
||||
#include "SkyDynamicTextureManager.hpp"
|
||||
#include "SkyTexture.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
|
||||
#pragma warning( disable : 4786 )
|
||||
|
||||
//! Set this to 1 to print lots of dynamic texture usage messages.
|
||||
#define SKYDYNTEXTURE_VERBOSE 0
|
||||
//! The maximum number of textures of each resolution to allow in the checked in pool.
|
||||
#define SKYDYNTEXTURE_TEXCACHE_LIMIT 32
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::SkyDynamicTextureManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::SkyDynamicTextureManager()
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyDynamicTextureManager::SkyDynamicTextureManager()
|
||||
#ifdef SKYDYNTEXTURE_VERBOSE
|
||||
: _iNumTextureBytesUsed(0),
|
||||
_iNumTextureBytesCheckedIn(0),
|
||||
_iNumTextureBytesCheckedOut(0)
|
||||
#endif
|
||||
{
|
||||
for (int i = 0; i < 11; ++i)
|
||||
for (int j = 0; j < 11; ++j)
|
||||
_iAvailableSizeCounts[i][j] = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::~SkyDynamicTextureManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::~SkyDynamicTextureManager()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkyDynamicTextureManager::~SkyDynamicTextureManager()
|
||||
{
|
||||
for ( TextureSet::iterator subset = _availableTexturePool.begin();
|
||||
subset != _availableTexturePool.end();
|
||||
++subset )
|
||||
{ // iterate over texture subsets.
|
||||
for ( TextureSubset::iterator texture = (*subset).second->begin();
|
||||
texture != (*subset).second->end();
|
||||
++texture )
|
||||
{
|
||||
texture->second->Destroy();
|
||||
delete texture->second;
|
||||
}
|
||||
subset->second->clear();
|
||||
}
|
||||
_availableTexturePool.clear();
|
||||
|
||||
for ( TextureSubset::iterator texture = _checkedOutTexturePool.begin();
|
||||
texture != _checkedOutTexturePool.end();
|
||||
++texture )
|
||||
{
|
||||
texture->second->Destroy();
|
||||
delete texture->second;
|
||||
}
|
||||
_checkedOutTexturePool.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::CheckOutTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::CheckOutTexture(unsigned int iWidth, unsigned int iHeight)
|
||||
* @brief Returns a texture from the available pool, creating a new one if necessary.
|
||||
*
|
||||
* Thi texture returned by this method is checked out: it will be maintained in a
|
||||
* checked out pool until it is checked in with CheckInTexture(). The texture is owned
|
||||
* by the SkyDynamicTextureManager -- it should not be deleted by another object. Checked out
|
||||
* textures can be modified (copied, or rendered to, etc.), but should not be reallocated
|
||||
* or resized. All checked out textures will be deleted when the SkyDynamicTextureManager
|
||||
* is destroyed, so this manager should be destroyed only after rendering ceases.
|
||||
*/
|
||||
SkyTexture* SkyDynamicTextureManager::CheckOutTexture(unsigned int iWidth,
|
||||
unsigned int iHeight)
|
||||
{
|
||||
int iWidthLog, iHeightLog;
|
||||
iWidthLog = SkyGetLogBaseTwo(iWidth);
|
||||
iHeightLog = SkyGetLogBaseTwo(iHeight);
|
||||
|
||||
// first see if a texture of this resolution is available:
|
||||
// find the subset of textures with width = iWidth, if it exists.
|
||||
TextureSet::iterator subset = _availableTexturePool.find(iWidth);
|
||||
if (subset != _availableTexturePool.end())
|
||||
{ // found the iWidth subset
|
||||
// now find a texture with height = iHeight:
|
||||
TextureSubset::iterator texture = (*subset).second->find(iHeight);
|
||||
if (texture != (*subset).second->end())
|
||||
{ // found one!
|
||||
// extract the texture
|
||||
SkyTexture *pTexture = (*texture).second;
|
||||
(*texture).second = NULL;
|
||||
// first remove it from this set.
|
||||
(*subset).second->erase(texture);
|
||||
// now add it to the checked out texture set.
|
||||
_checkedOutTexturePool.insert(TextureSubset::value_type(pTexture->GetID(), pTexture));
|
||||
|
||||
// update checked out/in amount.
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesCheckedIn -= iWidth * iHeight * 4;
|
||||
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
|
||||
printf("CHECKOUT: %d x %d\n", iWidth, iHeight);
|
||||
#endif
|
||||
_iAvailableSizeCounts[iWidthLog][iHeightLog]--;
|
||||
// we're now free to give this texture to the user
|
||||
return pTexture;
|
||||
}
|
||||
else
|
||||
{ // we didn't find an iWidth x iHeight texture, although the iWidth subset exists
|
||||
// create a new texture of the appropriate dimensions and return it.
|
||||
SkyTexture *pNewTexture = CreateDynamicTexture(iWidth, iHeight);
|
||||
_checkedOutTexturePool.insert(TextureSubset::value_type(pNewTexture->GetID(),
|
||||
pNewTexture));
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
|
||||
#endif
|
||||
|
||||
return pNewTexture;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // we don't yet have a subset for iWidth textures. Create one.
|
||||
TextureSubset *pSubset = new TextureSubset;
|
||||
_availableTexturePool.insert(TextureSet::value_type(iWidth, pSubset));
|
||||
// now create a new texture of the appropriate dimensions and return it.
|
||||
SkyTexture *pNewTexture = CreateDynamicTexture(iWidth, iHeight);
|
||||
_checkedOutTexturePool.insert(TextureSubset::value_type(pNewTexture->GetID(), pNewTexture));
|
||||
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
|
||||
#endif
|
||||
return pNewTexture;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::CheckInTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::CheckInTexture(SkyTexture *pTexture)
|
||||
* @brief Returns a checked-out texture to the available pool.
|
||||
*
|
||||
* This method removes the checked out texture from the checked out pool if it is
|
||||
* checked out, and then checks it in to the available pool.
|
||||
*/
|
||||
void SkyDynamicTextureManager::CheckInTexture(SkyTexture *pTexture)
|
||||
{
|
||||
// first see if the texture is in the checked out pool.
|
||||
TextureSubset::iterator coTexture = _checkedOutTexturePool.find(pTexture->GetID());
|
||||
if (coTexture != _checkedOutTexturePool.end())
|
||||
{ // if it is there, remove it.
|
||||
_checkedOutTexturePool.erase(coTexture);
|
||||
_iNumTextureBytesCheckedOut -= pTexture->GetWidth() * pTexture->GetHeight() * 4;
|
||||
}
|
||||
|
||||
// Don't cache too many unused textures.
|
||||
int iWidthLog, iHeightLog;
|
||||
iWidthLog = SkyGetLogBaseTwo(pTexture->GetWidth());
|
||||
iHeightLog = SkyGetLogBaseTwo(pTexture->GetHeight());
|
||||
if (_iAvailableSizeCounts[iWidthLog][iHeightLog] >= SKYDYNTEXTURE_TEXCACHE_LIMIT)
|
||||
{
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesUsed -= pTexture->GetWidth() * pTexture->GetHeight() * 4;
|
||||
printf("%dx%d texture DESTROYED.\n\t Total memory used: %d bytes.\n",
|
||||
pTexture->GetWidth(), pTexture->GetHeight(), _iNumTextureBytesUsed);
|
||||
#endif
|
||||
|
||||
pTexture->Destroy();
|
||||
SAFE_DELETE(pTexture);
|
||||
return;
|
||||
}
|
||||
|
||||
// now check the texture into the available pool.
|
||||
// find the width subset:
|
||||
TextureSet::iterator subset = _availableTexturePool.find(pTexture->GetWidth());
|
||||
if (subset != _availableTexturePool.end())
|
||||
{ // the subset exists. Add the texture to it
|
||||
(*subset).second->insert(TextureSubset::value_type(pTexture->GetHeight(), pTexture));
|
||||
_iNumTextureBytesCheckedIn += pTexture->GetWidth() * pTexture->GetHeight() * 4;
|
||||
|
||||
_iAvailableSizeCounts[iWidthLog][iHeightLog]++;
|
||||
}
|
||||
else
|
||||
{ // subset not found. Create it.
|
||||
TextureSubset *pSubset = new TextureSubset;
|
||||
// insert the texture.
|
||||
pSubset->insert(TextureSubset::value_type(pTexture->GetHeight(), pTexture));
|
||||
// insert the subset into the available pool
|
||||
_availableTexturePool.insert(TextureSet::value_type(pTexture->GetWidth(), pSubset));
|
||||
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesCheckedIn += pTexture->GetWidth() * pTexture->GetHeight() * 4;
|
||||
_iAvailableSizeCounts[iWidthLog][iHeightLog]++;
|
||||
#endif
|
||||
}
|
||||
|
||||
pTexture = NULL;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::CreateDynamicTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight)
|
||||
* @brief Allocate a new dynamic texture object of the given resolution.
|
||||
*
|
||||
* This method is used by CheckOutTexture() when it can't find an available texture of
|
||||
* the requested resolution. It can also be called externally, but will result in an
|
||||
* unmanaged texture unless the new texture is subsequently checked in using CheckInTexture().
|
||||
*/
|
||||
SkyTexture* SkyDynamicTextureManager::CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight)
|
||||
{
|
||||
unsigned int iID;
|
||||
glGenTextures(1, &iID);
|
||||
SkyTexture *pNewTexture = new SkyTexture(iWidth, iHeight, iID);
|
||||
glBindTexture(GL_TEXTURE_2D, pNewTexture->GetID());
|
||||
// set default filtering.
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
// create an empty buffer
|
||||
unsigned char *pData = new unsigned char[iWidth * iHeight * 4];
|
||||
|
||||
// allocate the texture
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, iWidth, iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData );
|
||||
|
||||
delete [] pData;
|
||||
|
||||
// update the used texture bytes...
|
||||
_iNumTextureBytesUsed += iWidth * iHeight * 4;
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
printf("New %dx%d texture created.\n\t Total memory used: %d bytes\n", iWidth, iHeight, _iNumTextureBytesUsed);
|
||||
printf("\tTotal memory checked in: %d\n", _iNumTextureBytesCheckedIn);
|
||||
printf("\tTotal memory checked out: %d\n", _iNumTextureBytesCheckedOut);
|
||||
#endif
|
||||
|
||||
return pNewTexture;
|
||||
}
|
||||
80
simgear/scene/sky/clouds3d/SkyDynamicTextureManager.hpp
Normal file
80
simgear/scene/sky/clouds3d/SkyDynamicTextureManager.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyDynamicTextureManager.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 SkyDynamicTextureManager.hpp
|
||||
*
|
||||
* Interface definition of a repository for check out and check in of dynamic textures.
|
||||
*/
|
||||
#ifndef __SKYDYNAMICTEXTUREMANAGER_HPP__
|
||||
#define __SKYDYNAMICTEXTUREMANAGER_HPP__
|
||||
|
||||
// warning for truncation of template name for browse info
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <map>
|
||||
#include <GL/glut.h>
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkySingleton.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SkyTexture;
|
||||
class SkyDynamicTextureManager;
|
||||
|
||||
//! Dynamic Texture Manager Singleton declaration.
|
||||
/*! The DynamicTextureManager must be created by calling DynamicTextureManager::Instantiate(). */
|
||||
typedef SkySingleton<SkyDynamicTextureManager> DynamicTextureManager;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyDynamicTextureManager
|
||||
* @brief A repository that allows check-out and check-in from a pool of dynamic textures.
|
||||
*
|
||||
* When an object needs a dynamic texture, it checks it out using CheckOutTexture(), passing
|
||||
* the resolution of the texture it needs. When the object is done with the texture, it
|
||||
* calls CheckInTexture(). New dynamic textures can be allocated by calling CreateDynamicTexture,
|
||||
* but these textures will be unmanaged.
|
||||
*/
|
||||
class SkyDynamicTextureManager
|
||||
{
|
||||
public:
|
||||
SkyTexture* CheckOutTexture(unsigned int iWidth, unsigned int iHeight);
|
||||
void CheckInTexture(SkyTexture* pTexture);
|
||||
|
||||
SkyTexture* CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight);
|
||||
|
||||
protected: // methods
|
||||
SkyDynamicTextureManager(); // these are protected because it is a singleton.
|
||||
~SkyDynamicTextureManager();
|
||||
|
||||
protected: // datatypes
|
||||
typedef multimap<unsigned int, SkyTexture*> TextureSubset;
|
||||
typedef multimap<unsigned int, TextureSubset*> TextureSet;
|
||||
|
||||
protected: // data
|
||||
TextureSet _availableTexturePool;
|
||||
TextureSubset _checkedOutTexturePool;
|
||||
|
||||
unsigned int _iAvailableSizeCounts[11][11];
|
||||
|
||||
unsigned int _iNumTextureBytesUsed;
|
||||
unsigned int _iNumTextureBytesCheckedOut;
|
||||
unsigned int _iNumTextureBytesCheckedIn;
|
||||
};
|
||||
|
||||
#endif //__SKYDYNAMICTEXTUREMANAGER_HPP__
|
||||
221
simgear/scene/sky/clouds3d/SkyLight.cpp
Normal file
221
simgear/scene/sky/clouds3d/SkyLight.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyLight.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyLight.cpp
|
||||
*
|
||||
* Implementation of a class that maintains the state and operation of a light.
|
||||
*/
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "SkyLight.hpp"
|
||||
#include "SkyMaterial.hpp"
|
||||
#include "mat44.hpp"
|
||||
#include <GL/glut.h>
|
||||
|
||||
SkyMaterial* SkyLight::s_pMaterial = NULL;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyLight::SkyLight
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyLight::SkyLight(SkyLightType eType)
|
||||
* @brief @todo <WRITE BRIEF SkyLight::SkyLight DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyLight::SkyLight FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SkyLight::SkyLight(SkyLightType eType)
|
||||
: _bEnabled(true),
|
||||
_bDirty(true),
|
||||
_iLastGLID(-1),
|
||||
_eType(eType),
|
||||
_vecPosition(0, 0, 1, 1),
|
||||
_vecDirection(0, 0, -1, 0),
|
||||
_vecDiffuse(1, 1, 1, 1),
|
||||
_vecAmbient(0, 0, 0, 0),
|
||||
_vecSpecular(1, 1, 1, 1),
|
||||
_vecAttenuation(1, 0, 0),
|
||||
_rSpotExponent(0),
|
||||
_rSpotCutoff(180)
|
||||
{
|
||||
if (!s_pMaterial)
|
||||
{
|
||||
s_pMaterial = new SkyMaterial;
|
||||
s_pMaterial->SetColorMaterialMode(GL_DIFFUSE);
|
||||
s_pMaterial->EnableColorMaterial(true);
|
||||
s_pMaterial->EnableLighting(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyLight::~SkyLight
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyLight::~SkyLight()
|
||||
* @brief @todo <WRITE BRIEF SkyLight::~SkyLight DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyLight::~SkyLight FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SkyLight::~SkyLight()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyLight::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyLight::Display() const
|
||||
* @brief Displays a wireframe representation of the light.
|
||||
*
|
||||
* This is useful for debugging.
|
||||
*/
|
||||
void SkyLight::Display() const
|
||||
{
|
||||
s_pMaterial->Activate();
|
||||
//if (_bEnabled)
|
||||
//glColor3fv(&(_vecDiffuse.x));
|
||||
//else
|
||||
glColor3f(0, 0, 0);
|
||||
|
||||
switch(_eType)
|
||||
{
|
||||
case SKY_LIGHT_POINT:
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
{
|
||||
glTranslatef(_vecPosition.x, _vecPosition.y, _vecPosition.z);
|
||||
glutWireSphere(4, 8, 8);
|
||||
}
|
||||
glPopMatrix();
|
||||
break;
|
||||
case SKY_LIGHT_DIRECTIONAL:
|
||||
{
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
{
|
||||
Mat44f mat;
|
||||
Vec3f vecPos(_vecPosition.x, _vecPosition.y, _vecPosition.z);
|
||||
Vec3f vecDir(_vecDirection.x, _vecDirection.y, _vecDirection.z);
|
||||
Vec3f vecUp(0, 1, 0);
|
||||
if (fabs(vecDir * vecUp) - 1 < 1e-6) // check that the view and up directions are not parallel.
|
||||
vecUp.Set(1, 0, 0);
|
||||
|
||||
mat.invLookAt(vecPos, vecPos + 10 * vecDir, vecUp);
|
||||
|
||||
glPushMatrix();
|
||||
{
|
||||
glTranslatef(-50 * vecDir.x, -50 * vecDir.y, -50 * vecDir.z);
|
||||
glMultMatrixf(mat);
|
||||
glutWireCone(10, 10, 4, 1);
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
glMultMatrixf(mat);
|
||||
GLUquadric *pQuadric = gluNewQuadric();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
gluCylinder(pQuadric, 4, 4, 50, 4, 4);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
break;
|
||||
case SKY_LIGHT_SPOT:
|
||||
{
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
{
|
||||
Mat44f mat;
|
||||
Vec3f vecUp = Vec3f(0, 1, 0);
|
||||
Vec3f vecPos(_vecPosition.x, _vecPosition.y, _vecPosition.z);
|
||||
Vec3f vecDir(_vecDirection.x, _vecDirection.y, _vecDirection.z);
|
||||
if (_vecDirection == vecUp)
|
||||
vecUp.Set(1, 0, 0);
|
||||
mat.invLookAt(vecPos + 50 * vecDir, vecPos + 51 * vecDir, vecUp);
|
||||
|
||||
glMultMatrixf(mat);
|
||||
float rAlpha= acos(pow(10, (-12 / _rSpotExponent)));
|
||||
//glutWireCone(50 * tan(SKYDEGREESTORADS * rAlpha), 50, 16, 8);
|
||||
glutWireCone(50 * tan(SKYDEGREESTORADS * _rSpotCutoff), 50, 16, 8);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyLight::Activate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyLight::Activate(int iLightID)
|
||||
* @brief @todo <WRITE BRIEF SkyLight::Activate DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyLight::Activate FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyLight::Activate(int iLightID)
|
||||
{
|
||||
glPushMatrix();
|
||||
// set the position every frame
|
||||
if (SKY_LIGHT_DIRECTIONAL != _eType)
|
||||
glLightfv(GL_LIGHT0 + iLightID, GL_POSITION, &(_vecPosition.x));
|
||||
else
|
||||
glLightfv(GL_LIGHT0 + iLightID, GL_POSITION, &(_vecDirection.x));
|
||||
|
||||
if (SKY_LIGHT_SPOT == _eType)
|
||||
glLightfv(GL_LIGHT0 + iLightID, GL_SPOT_DIRECTION, &(_vecDirection.x));
|
||||
|
||||
// set other light properties only when they change.
|
||||
if (_bDirty || iLightID != _iLastGLID)
|
||||
{
|
||||
glLightfv(GL_LIGHT0 + iLightID, GL_DIFFUSE, &(_vecDiffuse.x));
|
||||
glLightfv(GL_LIGHT0 + iLightID, GL_AMBIENT, &(_vecAmbient.x));
|
||||
glLightfv(GL_LIGHT0 + iLightID, GL_SPECULAR, &(_vecSpecular.x));
|
||||
glLightf(GL_LIGHT0 + iLightID, GL_CONSTANT_ATTENUATION, _vecAttenuation.x);
|
||||
glLightf(GL_LIGHT0 + iLightID, GL_LINEAR_ATTENUATION, _vecAttenuation.y);
|
||||
glLightf(GL_LIGHT0 + iLightID, GL_QUADRATIC_ATTENUATION, _vecAttenuation.z);
|
||||
|
||||
if (SKY_LIGHT_SPOT == _eType)
|
||||
{
|
||||
glLightf(GL_LIGHT0 + iLightID, GL_SPOT_CUTOFF, _rSpotCutoff);
|
||||
glLightf(GL_LIGHT0 + iLightID, GL_SPOT_EXPONENT, _rSpotExponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
glLightf(GL_LIGHT0 + iLightID, GL_SPOT_CUTOFF, 180);
|
||||
glLightf(GL_LIGHT0 + iLightID, GL_SPOT_EXPONENT, 0);
|
||||
}
|
||||
|
||||
if (_bEnabled)
|
||||
glEnable(GL_LIGHT0 + iLightID);
|
||||
else
|
||||
{
|
||||
glDisable(GL_LIGHT0 + iLightID);
|
||||
}
|
||||
|
||||
_iLastGLID = iLightID;
|
||||
_bDirty = false;
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
97
simgear/scene/sky/clouds3d/SkyLight.hpp
Normal file
97
simgear/scene/sky/clouds3d/SkyLight.hpp
Normal file
@@ -0,0 +1,97 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyLight.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 SkyLight.hpp
|
||||
*
|
||||
* Definition of a class that maintains the state and operation of a light.
|
||||
*/
|
||||
#ifndef __SKYLIGHT_HPP__
|
||||
#define __SKYLIGHT_HPP__
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include "vec4f.hpp"
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
class SkyMaterial;
|
||||
|
||||
class SkyLight
|
||||
{
|
||||
public: // types
|
||||
enum SkyLightType
|
||||
{
|
||||
SKY_LIGHT_POINT,
|
||||
SKY_LIGHT_DIRECTIONAL,
|
||||
SKY_LIGHT_SPOT,
|
||||
SKY_LIGHT_NUM_TYPES
|
||||
};
|
||||
|
||||
public: // methods
|
||||
SkyLight(SkyLightType eType);
|
||||
virtual ~SkyLight();
|
||||
|
||||
// for visualization of light positions / directions.
|
||||
void Display() const;
|
||||
|
||||
bool GetEnabled() const { return _bEnabled; }
|
||||
SkyLightType GetType() const { return _eType; }
|
||||
const float* GetPosition() const { return _vecPosition; }
|
||||
const float* GetDirection() const { return _vecDirection; }
|
||||
const float* GetDiffuse() const { return _vecDiffuse; }
|
||||
const float* GetAmbient() const { return _vecAmbient; }
|
||||
const float* GetSpecular() const { return _vecSpecular; }
|
||||
const float* GetAttenuation() const { return _vecAttenuation; }
|
||||
float GetSpotExponent() const { return _rSpotExponent; }
|
||||
float GetSpotCutoff() const { return _rSpotCutoff; }
|
||||
|
||||
void Enable(bool bEnable) { _bEnabled = bEnable; _bDirty = true; }
|
||||
void SetType(const SkyLightType& t) { _eType = t; _bDirty = true; }
|
||||
void SetPosition(const float pos[3])
|
||||
{ _vecPosition.Set(pos[0], pos[1], pos[2], (_eType != SKY_LIGHT_DIRECTIONAL)); _bDirty = true; }
|
||||
|
||||
void SetDirection(const float dir[3]) { _vecDirection.Set(dir[0], dir[1], dir[2], 0); _bDirty = true; }
|
||||
void SetDiffuse(const float color[4]) { _vecDiffuse.Set(color); _bDirty = true; }
|
||||
void SetAmbient(const float color[4]) { _vecAmbient.Set(color); _bDirty = true; }
|
||||
void SetSpecular(const float color[4]){ _vecSpecular.Set(color); _bDirty = true; }
|
||||
void SetAttenuation(float rConstant, float rLinear, float rQuadratic)
|
||||
{ _vecAttenuation.Set(rConstant, rLinear, rQuadratic); _bDirty = true; }
|
||||
|
||||
void SetSpotExponent(float rExp) { _rSpotExponent = rExp; _bDirty = true; }
|
||||
void SetSpotCutoff(float rCutoff) { _rSpotCutoff = rCutoff; _bDirty = true; }
|
||||
|
||||
SKYRESULT Activate(int iLightID);
|
||||
|
||||
protected: // data
|
||||
bool _bEnabled;
|
||||
bool _bDirty;
|
||||
|
||||
int _iLastGLID;
|
||||
|
||||
SkyLightType _eType;
|
||||
|
||||
Vec4f _vecPosition;
|
||||
Vec4f _vecDirection;
|
||||
Vec4f _vecDiffuse;
|
||||
Vec4f _vecAmbient;
|
||||
Vec4f _vecSpecular;
|
||||
Vec3f _vecAttenuation; // constant, linear, and quadratic attenuation factors.
|
||||
float _rSpotExponent;
|
||||
float _rSpotCutoff;
|
||||
|
||||
static SkyMaterial *s_pMaterial; // used for rendering the lights during debugging
|
||||
};
|
||||
|
||||
#endif //__SKYLIGHT_HPP__
|
||||
322
simgear/scene/sky/clouds3d/SkyMaterial.cpp
Normal file
322
simgear/scene/sky/clouds3d/SkyMaterial.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyMaterial.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyMaterial.cpp
|
||||
*
|
||||
* Implementation of class SkyMaterial, a meterial property object.
|
||||
*/
|
||||
#include "SkyMaterial.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMaterial::SkyMaterial
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMaterial::SkyMaterial()
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyMaterial::SkyMaterial()
|
||||
: _iMaterialID(-1),
|
||||
_vecDiffuse(Vec4f::ZERO),
|
||||
_vecSpecular(Vec4f::ZERO),
|
||||
_vecAmbient(Vec4f::ZERO),
|
||||
_vecEmissive(Vec4f::ZERO),
|
||||
_rSpecularPower(0),
|
||||
_bLighting(true),
|
||||
_eColorMaterialFace(GL_FRONT_AND_BACK),
|
||||
_eColorMaterialMode(GL_AMBIENT_AND_DIFFUSE),
|
||||
_bColorMaterial(false),
|
||||
_vecFogColor(Vec4f::ZERO),
|
||||
_eFogMode(GL_EXP),
|
||||
_bFog(false),
|
||||
_eDepthFunc(GL_LESS),
|
||||
_bDepthMask(true),
|
||||
_bDepthTest(true),
|
||||
_eAlphaFunc(GL_ALWAYS),
|
||||
_rAlphaRef(0),
|
||||
_bAlphaTest(false),
|
||||
_eBlendSrcFactor(GL_ONE),
|
||||
_eBlendDstFactor(GL_ZERO),
|
||||
_bBlending(false),
|
||||
_bFaceCulling(false),
|
||||
_eFaceCullingMode(GL_BACK),
|
||||
_eTextureEnvMode(GL_MODULATE)
|
||||
{
|
||||
_rFogParams[SKY_FOG_DENSITY] = 1;
|
||||
_rFogParams[SKY_FOG_START] = 0;
|
||||
_rFogParams[SKY_FOG_END] = 1;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMaterial::~SkyMaterial
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMaterial::~SkyMaterial()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkyMaterial::~SkyMaterial()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMaterial::SetFogParameter
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMaterial::SetFogParameter(GLenum eParameter, float rValue)
|
||||
*/
|
||||
SKYRESULT SkyMaterial::SetFogParameter(GLenum eParameter, float rValue)
|
||||
{
|
||||
switch (eParameter)
|
||||
{
|
||||
case GL_FOG_DENSITY:
|
||||
_rFogParams[SKY_FOG_DENSITY] = rValue;
|
||||
break;
|
||||
case GL_FOG_START:
|
||||
_rFogParams[SKY_FOG_START] = rValue;
|
||||
break;
|
||||
case GL_FOG_END:
|
||||
_rFogParams[SKY_FOG_END] = rValue;
|
||||
break;
|
||||
default:
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyMaterial::SetFogParameter(): Invalid parameter.");
|
||||
break;
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMaterial::GetFogParameter
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMaterial::GetFogParameter(GLenum eParameter) const
|
||||
*/
|
||||
float SkyMaterial::GetFogParameter(GLenum eParameter) const
|
||||
{
|
||||
switch (eParameter)
|
||||
{
|
||||
case GL_FOG_DENSITY:
|
||||
return _rFogParams[SKY_FOG_DENSITY];
|
||||
break;
|
||||
case GL_FOG_START:
|
||||
return _rFogParams[SKY_FOG_START];
|
||||
break;
|
||||
case GL_FOG_END:
|
||||
return _rFogParams[SKY_FOG_END];
|
||||
break;
|
||||
default:
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyMaterial::GetFogParameter(): Invalid parameter.");
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMaterial::Activate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMaterial::Activate()
|
||||
* @brief @todo <WRITE BRIEF SkyMaterial::SetMaterialPropertiesForDisplay DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyMaterial::SetMaterialPropertiesForDisplay FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyMaterial::Activate()
|
||||
{
|
||||
// Update the cached current material, and only pass values that have changed to the GL.
|
||||
|
||||
SkyMaterial *pCurrentMaterial = GraphicsContext::InstancePtr()->GetCurrentMaterial();
|
||||
assert(NULL != pCurrentMaterial);
|
||||
|
||||
// basic material properties
|
||||
if (pCurrentMaterial->GetDiffuse() != GetDiffuse())
|
||||
{
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &(GetDiffuse().x));
|
||||
pCurrentMaterial->SetDiffuse(GetDiffuse());
|
||||
}
|
||||
if (pCurrentMaterial->GetSpecular() != GetSpecular())
|
||||
{
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &(GetSpecular().x));
|
||||
pCurrentMaterial->SetSpecular(GetSpecular());
|
||||
}
|
||||
if (pCurrentMaterial->GetAmbient() != GetAmbient())
|
||||
{
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &(GetAmbient().x));
|
||||
pCurrentMaterial->SetAmbient(GetAmbient());
|
||||
}
|
||||
if (pCurrentMaterial->GetEmissive() != GetEmissive())
|
||||
{
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &(GetEmissive().x));
|
||||
pCurrentMaterial->SetEmissive(GetEmissive());
|
||||
}
|
||||
if (pCurrentMaterial->GetSpecularPower() != GetSpecularPower())
|
||||
{
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GetSpecularPower());
|
||||
pCurrentMaterial->SetSpecularPower(GetSpecularPower());
|
||||
}
|
||||
|
||||
// lighting
|
||||
if (pCurrentMaterial->IsLightingEnabled() != IsLightingEnabled())
|
||||
{
|
||||
if (IsLightingEnabled())
|
||||
glEnable(GL_LIGHTING);
|
||||
else
|
||||
glDisable(GL_LIGHTING);
|
||||
pCurrentMaterial->EnableLighting(IsLightingEnabled());
|
||||
}
|
||||
|
||||
// color material (which material property tracks color calls)
|
||||
if (pCurrentMaterial->GetColorMaterialFace() != GetColorMaterialFace() ||
|
||||
pCurrentMaterial->GetColorMaterialMode() != GetColorMaterialMode())
|
||||
{
|
||||
glColorMaterial(GetColorMaterialFace(), GetColorMaterialMode());
|
||||
pCurrentMaterial->SetColorMaterialFace(GetColorMaterialFace());
|
||||
pCurrentMaterial->SetColorMaterialMode(GetColorMaterialMode());
|
||||
}
|
||||
if (pCurrentMaterial->IsColorMaterialEnabled() != IsColorMaterialEnabled())
|
||||
{
|
||||
if (IsColorMaterialEnabled())
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
else
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
pCurrentMaterial->EnableColorMaterial(IsColorMaterialEnabled());
|
||||
}
|
||||
|
||||
// fog
|
||||
if (pCurrentMaterial->GetFogMode() != GetFogMode())
|
||||
{
|
||||
glFogf(GL_FOG_MODE, GetFogMode());
|
||||
pCurrentMaterial->SetFogMode(GetFogMode());
|
||||
}
|
||||
if (pCurrentMaterial->GetFogColor() != GetFogColor())
|
||||
{
|
||||
glFogfv(GL_FOG_COLOR, GetFogColor());
|
||||
pCurrentMaterial->SetFogColor(GetFogColor());
|
||||
}
|
||||
if (pCurrentMaterial->GetFogParameter(GL_FOG_DENSITY) != GetFogParameter(GL_FOG_DENSITY))
|
||||
{
|
||||
glFogf(GL_FOG_DENSITY, GetFogParameter(GL_FOG_DENSITY));
|
||||
pCurrentMaterial->SetFogParameter(GL_FOG_DENSITY, GetFogParameter(GL_FOG_DENSITY));
|
||||
}
|
||||
if (pCurrentMaterial->GetFogParameter(GL_FOG_START) != GetFogParameter(GL_FOG_START))
|
||||
{
|
||||
glFogf(GL_FOG_START, GetFogParameter(GL_FOG_START));
|
||||
pCurrentMaterial->SetFogParameter(GL_FOG_START, GetFogParameter(GL_FOG_START));
|
||||
}
|
||||
if (pCurrentMaterial->GetFogParameter(GL_FOG_END) != GetFogParameter(GL_FOG_END))
|
||||
{
|
||||
glFogf(GL_FOG_END, GetFogParameter(GL_FOG_END));
|
||||
pCurrentMaterial->SetFogParameter(GL_FOG_END, GetFogParameter(GL_FOG_END));
|
||||
}
|
||||
if (pCurrentMaterial->IsFogEnabled() != IsFogEnabled())
|
||||
{
|
||||
if (IsFogEnabled())
|
||||
glEnable(GL_FOG);
|
||||
else
|
||||
glDisable(GL_FOG);
|
||||
pCurrentMaterial->EnableFog(IsFogEnabled());
|
||||
}
|
||||
|
||||
// depth test
|
||||
if (pCurrentMaterial->GetDepthFunc() != GetDepthFunc())
|
||||
{
|
||||
glDepthFunc(GetDepthFunc());
|
||||
pCurrentMaterial->SetDepthFunc(GetDepthFunc());
|
||||
}
|
||||
if (pCurrentMaterial->GetDepthMask() != GetDepthMask())
|
||||
{
|
||||
glDepthMask(GetDepthMask());
|
||||
pCurrentMaterial->SetDepthMask(GetDepthMask());
|
||||
}
|
||||
if (pCurrentMaterial->IsDepthTestEnabled() != IsDepthTestEnabled())
|
||||
{
|
||||
if (IsDepthTestEnabled())
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
else
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
pCurrentMaterial->EnableDepthTest(IsDepthTestEnabled());
|
||||
}
|
||||
|
||||
// alpha test
|
||||
if (pCurrentMaterial->GetAlphaFunc() != GetAlphaFunc() ||
|
||||
pCurrentMaterial->GetAlphaRef() != GetAlphaRef())
|
||||
{
|
||||
glAlphaFunc(GetAlphaFunc(), GetAlphaRef());
|
||||
pCurrentMaterial->SetAlphaFunc(GetAlphaFunc());
|
||||
pCurrentMaterial->SetAlphaRef(GetAlphaRef());
|
||||
}
|
||||
if (pCurrentMaterial->IsAlphaTestEnabled() != IsAlphaTestEnabled())
|
||||
{
|
||||
if (IsAlphaTestEnabled())
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
else
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
pCurrentMaterial->EnableAlphaTest(IsAlphaTestEnabled());
|
||||
}
|
||||
|
||||
// blending
|
||||
if (pCurrentMaterial->GetBlendingSourceFactor() != GetBlendingSourceFactor() ||
|
||||
pCurrentMaterial->GetBlendingDestFactor() != GetBlendingDestFactor())
|
||||
{
|
||||
glBlendFunc(GetBlendingSourceFactor(), GetBlendingDestFactor());
|
||||
pCurrentMaterial->SetBlendFunc(GetBlendingSourceFactor(), GetBlendingDestFactor());
|
||||
}
|
||||
if (pCurrentMaterial->IsBlendingEnabled() != IsBlendingEnabled())
|
||||
{
|
||||
if (IsBlendingEnabled())
|
||||
glEnable(GL_BLEND);
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
pCurrentMaterial->EnableBlending(IsBlendingEnabled());
|
||||
}
|
||||
|
||||
if (pCurrentMaterial->GetFaceCullingMode() != GetFaceCullingMode())
|
||||
{
|
||||
glCullFace(GetFaceCullingMode());
|
||||
pCurrentMaterial->SetFaceCullingMode(GetFaceCullingMode());
|
||||
}
|
||||
if (pCurrentMaterial->IsFaceCullingEnabled() != IsFaceCullingEnabled())
|
||||
{
|
||||
if (IsFaceCullingEnabled())
|
||||
glEnable(GL_CULL_FACE);
|
||||
else
|
||||
glDisable(GL_CULL_FACE);
|
||||
pCurrentMaterial->EnableFaceCulling(IsFaceCullingEnabled());
|
||||
}
|
||||
|
||||
// texturing
|
||||
FAIL_RETURN(_textureState.Activate());
|
||||
if (pCurrentMaterial->GetTextureApplicationMode() != GetTextureApplicationMode())
|
||||
{
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GetTextureApplicationMode());
|
||||
pCurrentMaterial->SetTextureApplicationMode(GetTextureApplicationMode());
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
268
simgear/scene/sky/clouds3d/SkyMaterial.hpp
Normal file
268
simgear/scene/sky/clouds3d/SkyMaterial.hpp
Normal file
@@ -0,0 +1,268 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyMaterial.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 SkyMaterial.hpp
|
||||
*
|
||||
* Interface definition for class SkyMaterial, a meterial property object.
|
||||
*/
|
||||
#ifndef __SKYMATERIAL_HPP__
|
||||
#define __SKYMATERIAL_HPP__
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "vec4f.hpp"
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkyTextureManager.hpp"
|
||||
#include "SkyTextureState.hpp"
|
||||
#include <GL/glut.h>
|
||||
|
||||
// forward
|
||||
class SkyRenderable;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyMaterial
|
||||
* @brief A class for organizing and caching material state.
|
||||
*
|
||||
* This class handles setting and querying material state. By calling the Activate()
|
||||
* method, the material's state can be made current in OpenGL. The material will not
|
||||
* set states that are currently active in the current OpenGL context.
|
||||
*/
|
||||
class SkyMaterial
|
||||
{
|
||||
public:
|
||||
SkyMaterial();
|
||||
~SkyMaterial();
|
||||
|
||||
SKYRESULT Activate();
|
||||
|
||||
// Getters for basic material properties
|
||||
|
||||
//! Returns the material identifier.
|
||||
int GetMaterialID() const { return _iMaterialID; }
|
||||
//! Returns the material diffuse color.
|
||||
const Vec4f& GetDiffuse() const { return _vecDiffuse; }
|
||||
//! Returns the material specular color.
|
||||
const Vec4f& GetSpecular() const { return _vecSpecular; }
|
||||
//! Returns the material ambient color.
|
||||
const Vec4f& GetAmbient() const { return _vecAmbient; }
|
||||
//! Returns the material emissive color.
|
||||
const Vec4f& GetEmissive() const { return _vecEmissive; }
|
||||
//! Returns the material specular power (shininess).
|
||||
const float GetSpecularPower() const { return _rSpecularPower; }
|
||||
|
||||
// lighting
|
||||
//! Returns true if lighting is enabled for this material.
|
||||
bool IsLightingEnabled() const { return _bLighting; }
|
||||
|
||||
// color material (which material property tracks color calls)
|
||||
//! Returns the face for which color material tracking is enabled.
|
||||
GLenum GetColorMaterialFace() const { return _eColorMaterialFace; }
|
||||
//! Returns the color material tracking mode.
|
||||
GLenum GetColorMaterialMode() const { return _eColorMaterialMode; }
|
||||
//! Returns true if color material tracking is enabled.
|
||||
bool IsColorMaterialEnabled() const { return _bColorMaterial; }
|
||||
|
||||
//! Returns the fog density or start / end distance.
|
||||
float GetFogParameter(GLenum eParameter) const;
|
||||
//! Returns the fog mode (exponential, linear, etc.)
|
||||
GLenum GetFogMode() const { return _eFogMode; }
|
||||
//! Returns the fog color.
|
||||
const Vec4f& GetFogColor() const { return _vecFogColor; }
|
||||
//! Returns true if fog is enabled for this material.
|
||||
bool IsFogEnabled() const { return _bFog; }
|
||||
|
||||
// texturing
|
||||
//! Returns the active texture target for texture unit @a iTextureUnit.
|
||||
GLenum GetActiveTarget(unsigned int iTextureUnit) const
|
||||
{ return _textureState.GetActiveTarget(iTextureUnit); }
|
||||
//! Returns the bound texture ID for texture unit @a iTextureUnit.
|
||||
unsigned int GetTextureID(unsigned int iTextureUnit) const
|
||||
{ return _textureState.GetTextureID(iTextureUnit); }
|
||||
//! Returns true if texturing is enabled for texture unit @a iTextureUnit.
|
||||
bool IsTextureEnabled(unsigned int iTextureUnit) const
|
||||
{ return _textureState.IsTextureEnabled(iTextureUnit); }
|
||||
//! Returns the value of the texture parameter @a eParameter for texture unit @a iTextureUnit.
|
||||
GLenum GetTextureParameter(unsigned int iTextureUnit, GLenum eParameter) const
|
||||
{ return _textureState.GetTextureParameter(iTextureUnit, eParameter); }
|
||||
//! Returns the texture application mode of the texture environment.
|
||||
GLenum GetTextureApplicationMode() const { return _eTextureEnvMode; }
|
||||
|
||||
//! Returns a reference to the texture state object owned by this materal.
|
||||
SkyTextureState& GetTextureState() { return _textureState; }
|
||||
|
||||
// depth test
|
||||
//! Returns true if depth testing is enabled for this material.
|
||||
bool IsDepthTestEnabled() const { return _bDepthTest; }
|
||||
//! Returns the depth test function for this material.
|
||||
GLenum GetDepthFunc() const { return _eDepthFunc; }
|
||||
//! Returns true if depth writes are enabled for this material, false if not.
|
||||
bool GetDepthMask() const { return _bDepthMask; }
|
||||
|
||||
// alpha test
|
||||
//! Returns true if alpha testing is enabled for this material.
|
||||
bool IsAlphaTestEnabled() const { return _bAlphaTest; }
|
||||
//! Returns the alpha test function for this material.
|
||||
GLenum GetAlphaFunc() const { return _eAlphaFunc; }
|
||||
//! Returns the reference value for alpha comparison.
|
||||
float GetAlphaRef() const { return _rAlphaRef; }
|
||||
|
||||
// blending
|
||||
//! Returns true if blending is enabled for this material.
|
||||
bool IsBlendingEnabled() const { return _bBlending; }
|
||||
//! Returns the source blending factor for this material.
|
||||
GLenum GetBlendingSourceFactor() const { return _eBlendSrcFactor; }
|
||||
//! Returns the destination blending factor for this material.
|
||||
GLenum GetBlendingDestFactor() const { return _eBlendDstFactor; }
|
||||
|
||||
//! Returns true if face culling enabled for this material.
|
||||
bool IsFaceCullingEnabled() const { return _bFaceCulling; }
|
||||
//! Returns which faces are culled -- front-facing or back-facing.
|
||||
GLenum GetFaceCullingMode() const { return _eFaceCullingMode; }
|
||||
|
||||
// Setters for basic material properties
|
||||
|
||||
//! Sets the material identifier.
|
||||
void SetMaterialID(int ID) { _iMaterialID = ID; }
|
||||
//! Sets the diffuse material color.
|
||||
void SetDiffuse( const Vec4f& d) { _vecDiffuse = d; }
|
||||
//! Sets the specular material color.
|
||||
void SetSpecular(const Vec4f& d) { _vecSpecular = d; }
|
||||
//! Sets the ambient material color.
|
||||
void SetAmbient( const Vec4f& d) { _vecAmbient = d; }
|
||||
//! Sets the emissive material color.
|
||||
void SetEmissive(const Vec4f& d) { _vecEmissive = d; }
|
||||
//! Sets the material specular power (shininess).
|
||||
void SetSpecularPower(float power) { _rSpecularPower = power; }
|
||||
|
||||
// lighting
|
||||
//! Enables / Disables lighting for this material.
|
||||
void EnableLighting(bool bEnable) { _bLighting = bEnable; }
|
||||
|
||||
// color material (which material property tracks color calls)
|
||||
//! Sets which faces (front or back) track color calls.
|
||||
void SetColorMaterialFace(GLenum eFace) { _eColorMaterialFace = eFace; }
|
||||
//! Sets which material property tracks color calls.
|
||||
void SetColorMaterialMode(GLenum eMode) { _eColorMaterialMode = eMode; }
|
||||
//! Enables / Disables material color tracking for this material.
|
||||
void EnableColorMaterial(bool bEnable) { _bColorMaterial = bEnable; }
|
||||
|
||||
//! Sets the fog density or start / end distance.
|
||||
SKYRESULT SetFogParameter(GLenum eParameter, float rValue);
|
||||
//! Sets the fog mode (exponential, linear, etc.)
|
||||
void SetFogMode(GLenum eMode) { _eFogMode = eMode; }
|
||||
//! Sets the fog color.
|
||||
void SetFogColor(const Vec4f& color) { _vecFogColor = color; }
|
||||
//! Enables / Disables fog for this material.
|
||||
void EnableFog(bool bEnable) { _bFog = bEnable; }
|
||||
|
||||
// texturing
|
||||
//! Sets the bound texture and texture target for texture unit @a iTextureUnit.
|
||||
SKYRESULT SetTexture(unsigned int iTextureUnit, GLenum eTarget, SkyTexture& texture)
|
||||
{ return _textureState.SetTexture(iTextureUnit, eTarget, texture); }
|
||||
//! Sets the bound texture and texture target for texture unit @a iTextureUnit.
|
||||
SKYRESULT SetTexture(unsigned int iTextureUnit, GLenum eTarget, unsigned int iTextureID)
|
||||
{ return _textureState.SetTexture(iTextureUnit, eTarget, iTextureID); }
|
||||
//! Enables / Disables texture unit @a iTextureUnit for this material.
|
||||
SKYRESULT EnableTexture(unsigned int iTextureUnit, bool bEnable)
|
||||
{ return _textureState.EnableTexture(iTextureUnit, bEnable); }
|
||||
//! Sets the value of the texture parameter @a eParameter for texture unit @a iTextureUnit.
|
||||
SKYRESULT SetTextureParameter(unsigned int iTextureUnit, GLenum eParameter, GLenum eMode)
|
||||
{ return _textureState.SetTextureParameter(iTextureUnit, eParameter, eMode); }
|
||||
|
||||
//! Sets the texture application mode of the texture environment.
|
||||
void SetTextureApplicationMode(GLenum eMode){ _eTextureEnvMode = eMode;}
|
||||
|
||||
// depth test
|
||||
//! Enables / Disables depth test for this material.
|
||||
void EnableDepthTest(bool bEnable) { _bDepthTest = bEnable; }
|
||||
//! Sets the depth test function (greater, less than, equal, etc.).
|
||||
void SetDepthFunc(GLenum eDepthFunc) { _eDepthFunc = eDepthFunc;}
|
||||
//! If @a bDepthMask is true, then depth writes are enabled, otherwise they are not.
|
||||
void SetDepthMask(bool bDepthMask) { _bDepthMask = bDepthMask;}
|
||||
|
||||
// alpha test
|
||||
//! Enables / Disables alpha test for this material.
|
||||
void EnableAlphaTest(bool bEnable) { _bAlphaTest = bEnable; }
|
||||
//! Sets the alpha test function (greater, less than, equal, etc.).
|
||||
void SetAlphaFunc(GLenum eAlphaFunc) { _eAlphaFunc = eAlphaFunc;}
|
||||
//! Sets the reference value against which fragment alpha values are compared.
|
||||
void SetAlphaRef(float rAlphaRef) { _rAlphaRef = rAlphaRef; }
|
||||
|
||||
// blending
|
||||
//! Enables / Disables blending for this material.
|
||||
void EnableBlending(bool bEnable) { _bBlending = bEnable; }
|
||||
//! Sets the source and destination blending factors for this material.
|
||||
void SetBlendFunc(GLenum eSrcFactor, GLenum eDstFactor)
|
||||
{ _eBlendSrcFactor = eSrcFactor; _eBlendDstFactor = eDstFactor; }
|
||||
|
||||
//! Enables / Disables face culling for this material.
|
||||
void EnableFaceCulling(bool bEnable) { _bFaceCulling = bEnable; }
|
||||
//! Sets which faces will be culled -- front facing or back facing.
|
||||
void SetFaceCullingMode(GLenum eMode) { _eFaceCullingMode = eMode; }
|
||||
|
||||
protected:
|
||||
int _iMaterialID;
|
||||
|
||||
Vec4f _vecDiffuse;
|
||||
Vec4f _vecSpecular;
|
||||
Vec4f _vecAmbient;
|
||||
Vec4f _vecEmissive;
|
||||
|
||||
float _rSpecularPower;
|
||||
|
||||
bool _bLighting;
|
||||
|
||||
GLenum _eColorMaterialFace;
|
||||
GLenum _eColorMaterialMode;
|
||||
bool _bColorMaterial;
|
||||
|
||||
enum SkyFogParams
|
||||
{
|
||||
SKY_FOG_DENSITY,
|
||||
SKY_FOG_START,
|
||||
SKY_FOG_END,
|
||||
SKY_FOG_NUM_PARAMS
|
||||
};
|
||||
|
||||
Vec4f _vecFogColor;
|
||||
GLenum _eFogMode;
|
||||
float _rFogParams[SKY_FOG_NUM_PARAMS];
|
||||
bool _bFog;
|
||||
|
||||
GLenum _eDepthFunc;
|
||||
bool _bDepthMask;
|
||||
bool _bDepthTest;
|
||||
|
||||
GLenum _eAlphaFunc;
|
||||
float _rAlphaRef;
|
||||
bool _bAlphaTest;
|
||||
|
||||
GLenum _eBlendSrcFactor;
|
||||
GLenum _eBlendDstFactor;
|
||||
bool _bBlending;
|
||||
|
||||
bool _bFaceCulling;
|
||||
GLenum _eFaceCullingMode;
|
||||
|
||||
SkyTextureState _textureState;
|
||||
GLenum _eTextureEnvMode;
|
||||
};
|
||||
|
||||
#endif //__SKYMATERIAL_HPP__
|
||||
322
simgear/scene/sky/clouds3d/SkyMinMaxBox.cpp
Normal file
322
simgear/scene/sky/clouds3d/SkyMinMaxBox.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyMinMaxBox.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyMinMaxBox.cpp
|
||||
*
|
||||
* Implementation of a bounding box class. Modified from Wes Hunt's BoundingBox.
|
||||
*/
|
||||
#include "SkyMinMaxBox.hpp"
|
||||
#include "camutils.hpp"
|
||||
#include <GL/glut.h>
|
||||
#include <float.h>
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::SkyMinMaxBox
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::SkyMinMaxBox()
|
||||
* @brief Constructor
|
||||
*/
|
||||
SkyMinMaxBox::SkyMinMaxBox()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::Clear
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::Clear()
|
||||
* @brief Reset the min and max to floating point extremes.
|
||||
*
|
||||
*/
|
||||
void SkyMinMaxBox::Clear()
|
||||
{
|
||||
_min.x = FLT_MAX;
|
||||
_min.y = FLT_MAX;
|
||||
_min.z = FLT_MAX;
|
||||
_max.x = -FLT_MAX;
|
||||
_max.y = -FLT_MAX;
|
||||
_max.z = -FLT_MAX;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::PointInBBox
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::PointInBBox( const Vec3f &pt ) const
|
||||
* @brief Queries pt to see if it is inside the SkyMinMaxBox.
|
||||
*
|
||||
*/
|
||||
bool SkyMinMaxBox::PointInBBox( const Vec3f &pt ) const
|
||||
{
|
||||
if( (pt.x >= _min.x) && ( pt.x <= _max.x ) )
|
||||
{
|
||||
if( (pt.y >= _min.y) && ( pt.y <= _max.y ) )
|
||||
{
|
||||
if( (pt.z >= _min.z) && ( pt.z <= _max.z ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::AddPoint
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::AddPoint( float x , float y , float z )
|
||||
* @brief Adds a point and adjusts bounds if necessary.
|
||||
*/
|
||||
void SkyMinMaxBox::AddPoint( float x , float y , float z )
|
||||
{
|
||||
if( x > _max.x )
|
||||
_max.x = x;
|
||||
if( x < _min.x )
|
||||
_min.x = x;
|
||||
|
||||
if( y > _max.y )
|
||||
_max.y = y;
|
||||
if( y < _min.y )
|
||||
_min.y = y;
|
||||
|
||||
if( z > _max.z )
|
||||
_max.z = z;
|
||||
if( z < _min.z )
|
||||
_min.z = z;
|
||||
|
||||
// update the center and radius
|
||||
_UpdateSphere();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::AddPoint
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::AddPoint( const Vec3f &pt )
|
||||
* @brief Adds a point and adjusts bounds if necessary.
|
||||
*/
|
||||
void SkyMinMaxBox::AddPoint( const Vec3f &pt )
|
||||
{
|
||||
if( pt.x > _max.x )
|
||||
_max.x = pt.x;
|
||||
if( pt.x < _min.x )
|
||||
_min.x = pt.x;
|
||||
|
||||
if( pt.y > _max.y )
|
||||
_max.y = pt.y;
|
||||
if( pt.y < _min.y )
|
||||
_min.y = pt.y;
|
||||
|
||||
if( pt.z > _max.z )
|
||||
_max.z = pt.z;
|
||||
if( pt.z < _min.z )
|
||||
_min.z = pt.z;
|
||||
|
||||
// update the center and radius
|
||||
_UpdateSphere();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::ViewFrustumCull
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::ViewFrustumCull( const Camera &cam, const Mat44f &mat )
|
||||
* @brief Returns true if bounding volume culled against cam.
|
||||
*
|
||||
* This function must transform the object space min and max then adjust the new
|
||||
* min and max box by expanding it. Each of the 8 points must be tested. This
|
||||
* is faster then doing an xform of all the geometry points and finding a tight
|
||||
* fitting min max box, however this will be enlarged.
|
||||
*/
|
||||
bool SkyMinMaxBox::ViewFrustumCull( const Camera &cam, const Mat44f &mat )
|
||||
{
|
||||
SkyMinMaxBox xBV; // Xformed Bounding Volume
|
||||
Vec3f xMin = mat * _min; // Xformed _min
|
||||
Vec3f xMax = mat * _max; // Xformed _max
|
||||
Vec3f offset = _max - _min; // Offset for sides of MinMaxBox
|
||||
Vec3f tmp;
|
||||
|
||||
xBV.Clear(); // Clear the values first
|
||||
|
||||
// First find the new minimum x,y,z
|
||||
// Find min + x
|
||||
tmp.Set(mat.M[0], mat.M[4], mat.M[8]);
|
||||
tmp *= offset.x;
|
||||
tmp += xMin;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Find min + y
|
||||
tmp.Set(mat.M[1], mat.M[5], mat.M[9]);
|
||||
tmp *= offset.y;
|
||||
tmp += xMin;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Find min + z
|
||||
tmp.Set(mat.M[3], mat.M[6], mat.M[10]);
|
||||
tmp *= offset.z;
|
||||
tmp += xMin;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Second find the new maximum x,y,z
|
||||
// Find max - x
|
||||
tmp.Set(mat.M[0], mat.M[4], mat.M[8]);
|
||||
tmp *= -offset.x;
|
||||
tmp += xMax;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Find max - y
|
||||
tmp.Set(mat.M[1], mat.M[5], mat.M[9]);
|
||||
tmp *= -offset.y;
|
||||
tmp += xMax;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Find max - z
|
||||
tmp.Set(mat.M[3], mat.M[6], mat.M[10]);
|
||||
tmp *= -offset.z;
|
||||
tmp += xMax;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Use the camera utility function that already exists for minmax boxes
|
||||
return VFC(&cam, xBV.GetMin(), xBV.GetMax());
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::Transform
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::Transform(const Mat44f& mat)
|
||||
* @brief @todo <WRITE BRIEF SkyMinMaxBox::Transform DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyMinMaxBox::Transform FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyMinMaxBox::Transform(const Mat44f& mat)
|
||||
{
|
||||
Vec3f verts[8];
|
||||
_CalcVerts(verts);
|
||||
Clear();
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
AddPoint(mat * verts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::_UpdateSphere
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::_UpdateSphere()
|
||||
* @brief Updates the bounding sphere based on min and max.
|
||||
*/
|
||||
void SkyMinMaxBox::_UpdateSphere()
|
||||
{
|
||||
_vecCenter = _min;
|
||||
_vecCenter += _max;
|
||||
_vecCenter *= 0.5f;
|
||||
|
||||
Vec3f rad = _max;
|
||||
rad -= _vecCenter;
|
||||
_rRadius = rad.Length();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::Display() const
|
||||
* @brief @todo <WRITE BRIEF SkyMinMaxBox::Display DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyMinMaxBox::Display FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyMinMaxBox::Display() const
|
||||
{
|
||||
Vec3f V[8];
|
||||
_CalcVerts(V);
|
||||
|
||||
glPushAttrib(GL_LINE_BIT);
|
||||
glLineWidth(1.0);
|
||||
|
||||
glBegin(GL_LINE_LOOP); // TOP FACE
|
||||
glVertex3fv(V[4]); glVertex3fv(V[5]); glVertex3fv(V[1]); glVertex3fv(V[0]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // BOTTOM FACE
|
||||
glVertex3fv(V[3]); glVertex3fv(V[2]); glVertex3fv(V[6]); glVertex3fv(V[7]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // LEFT FACE
|
||||
glVertex3fv(V[1]); glVertex3fv(V[5]); glVertex3fv(V[6]); glVertex3fv(V[2]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // RIGHT FACE
|
||||
glVertex3fv(V[0]); glVertex3fv(V[3]); glVertex3fv(V[7]); glVertex3fv(V[4]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // NEAR FACE
|
||||
glVertex3fv(V[1]); glVertex3fv(V[2]); glVertex3fv(V[3]); glVertex3fv(V[0]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // FAR FACE
|
||||
glVertex3fv(V[4]); glVertex3fv(V[7]); glVertex3fv(V[6]); glVertex3fv(V[5]);
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Calculates the eight corner vertices of the MinMaxBox.
|
||||
// V must be prealloced.
|
||||
// 5---4
|
||||
// / /|
|
||||
// 1---0 | VERTS : 0=RTN,1=LTN,2=LBN,3=RBN,4=RTF,5=LTF,6=LBF,7=RBF
|
||||
// | | 7 (L,R, B,T, N,F) = (Left,Right, Bottom,Top, Near,Far)
|
||||
// | |/
|
||||
// 2---3
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::_CalcVerts
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::_CalcVerts(Vec3f pVerts[8]) const
|
||||
* @brief @todo <WRITE BRIEF SkyMinMaxBox::_CalcVerts DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyMinMaxBox::_CalcVerts FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyMinMaxBox::_CalcVerts(Vec3f pVerts[8]) const
|
||||
{
|
||||
pVerts[0].Set(_max); pVerts[4].Set(_max.x, _max.y, _min.z);
|
||||
pVerts[1].Set(_min.x, _max.y, _max.z); pVerts[5].Set(_min.x, _max.y, _min.z);
|
||||
pVerts[2].Set(_min.x, _min.y, _max.z); pVerts[6].Set(_min);
|
||||
pVerts[3].Set(_max.x, _min.y, _max.z); pVerts[7].Set(_max.x, _min.y, _min.z);
|
||||
}
|
||||
85
simgear/scene/sky/clouds3d/SkyMinMaxBox.hpp
Normal file
85
simgear/scene/sky/clouds3d/SkyMinMaxBox.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyMinMaxBox.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 SkyMinMaxBox.hpp
|
||||
*
|
||||
* Interface definition for a min-max bounding box class for bounding volume hierarchies.
|
||||
*/
|
||||
#ifndef __SKYMINMAXBOX_HPP__
|
||||
#define __SKYMINMAXBOX_HPP__
|
||||
|
||||
#include "SkyBoundingVolume.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyMinMaxBox
|
||||
* @brief An AABB class that can be used in bounding volume hierarchies.
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyMinMaxBox : public SkyBoundingVolume
|
||||
{
|
||||
public:
|
||||
SkyMinMaxBox();
|
||||
//! Destructor
|
||||
virtual ~SkyMinMaxBox() {}
|
||||
|
||||
void AddPoint( const Vec3f &pt );
|
||||
void AddPoint( float x , float y , float z );
|
||||
|
||||
//! Expand this box to contain @a box.
|
||||
void Union(const SkyMinMaxBox& box) { AddPoint(box.GetMin()); AddPoint(box.GetMax()); }
|
||||
|
||||
//! Returns the minimum corner of the bounding box.
|
||||
const Vec3f &GetMin() const { return _min; }
|
||||
//! Returns the maximum corner of the bounding box.
|
||||
const Vec3f &GetMax() const { return _max; }
|
||||
|
||||
//! Sets the minimum corner of the bounding box.
|
||||
void SetMin(const Vec3f &min) { _min = min; _UpdateSphere(); }
|
||||
//! Sets the maximum corner of the bounding box.
|
||||
void SetMax(const Vec3f &max) { _max = max; _UpdateSphere(); }
|
||||
|
||||
//! Returns the X width of the bounding box.
|
||||
float GetWidthInX() const { return _max.x - _min.x;}
|
||||
//! Returns the Y width of the bounding box.
|
||||
float GetWidthInY() const { return _max.y - _min.y;}
|
||||
//! Returns the Z width of the bounding box.
|
||||
float GetWidthInZ() const { return _max.z - _min.z;}
|
||||
|
||||
bool PointInBBox( const Vec3f &pt ) const;
|
||||
|
||||
bool ViewFrustumCull( const Camera &cam, const Mat44f &mat );
|
||||
|
||||
void Transform(const Mat44f& mat);
|
||||
|
||||
// Reset the bounding box
|
||||
void Clear();
|
||||
|
||||
void Display() const;
|
||||
|
||||
protected:
|
||||
void _UpdateSphere();
|
||||
void _CalcVerts(Vec3f pVerts[8]) const;
|
||||
|
||||
private:
|
||||
Vec3f _min; // Original object space BV
|
||||
Vec3f _max;
|
||||
};
|
||||
|
||||
#endif //__SKYMINMAXBOX_HPP__
|
||||
116
simgear/scene/sky/clouds3d/SkyRenderable.hpp
Normal file
116
simgear/scene/sky/clouds3d/SkyRenderable.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderable.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 : SkyRenderable.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// Sky : Copyright 2002 Mark J. Harris and Andrew Zaferakis
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @file SkyRenderable.hpp
|
||||
*
|
||||
* Abstract base class definition for SkyRenderable, a renderable object class.
|
||||
*/
|
||||
#ifndef __SKYRENDERABLE_HPP__
|
||||
#define __SKYRENDERABLE_HPP__
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class SkyMinMaxBox;
|
||||
class SkyRenderableInstance;
|
||||
class Camera;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderable
|
||||
* @brief An base class for renderable objects.
|
||||
*
|
||||
* Each SkyRenderable object should know how to Display itself, however some
|
||||
* objects may not have a bounding volume that is useful (skybox, etc.)
|
||||
*/
|
||||
class SkyRenderable
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
SkyRenderable() {}
|
||||
//! Destructor
|
||||
virtual ~SkyRenderable() { }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SetName
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SetName(const std::string &name)
|
||||
* @brief Set a name for this renderable.
|
||||
*/
|
||||
void SetName(const std::string &name) { _name = name; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : GetName
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn GetName() const
|
||||
* @brief Get the name of this renderable.
|
||||
*/
|
||||
const std::string& GetName() const { return _name; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Update
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Update(const Camera &cam, SkyRenderableInstance *pInstance)
|
||||
* @brief Update the state of the renderable.
|
||||
*
|
||||
* This method is optional, as some renderables will need periodic updates
|
||||
* (i.e. for animation) and others will not.
|
||||
*/
|
||||
virtual SKYRESULT Update(const Camera &cam, SkyRenderableInstance *pInstance = NULL)
|
||||
{ return SKYRESULT_OK; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Display(const Camera &cam, SkyRenderableInstance *pInstance)
|
||||
* @brief Display the object.
|
||||
*/
|
||||
virtual SKYRESULT Display(const Camera &cam, SkyRenderableInstance *pInstance = NULL) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : CopyBoundingVolume
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn CopyBoundingVolume() const
|
||||
* @brief Create a copy of the object's bounding volume, useful for collision, VFC, etc.
|
||||
*/
|
||||
virtual SkyMinMaxBox* CopyBoundingVolume() const = 0;// { return 0; }
|
||||
|
||||
protected:
|
||||
std::string _name; // the name of this renderable.
|
||||
};
|
||||
|
||||
#endif //__SKYRENDERABLE_HPP__
|
||||
202
simgear/scene/sky/clouds3d/SkyRenderableInstance.hpp
Normal file
202
simgear/scene/sky/clouds3d/SkyRenderableInstance.hpp
Normal file
@@ -0,0 +1,202 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstance.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 SkyRenderableInstance.hpp
|
||||
*
|
||||
* Interface definition for SkyRenderableInstance, an instance of a renderable object.
|
||||
*/
|
||||
#ifndef __SKYRENDERABLEINSTANCE_HPP__
|
||||
#define __SKYRENDERABLEINSTANCE_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <mat33.hpp>
|
||||
#include <mat44.hpp>
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class Camera;
|
||||
class SkyMinMaxBox;
|
||||
|
||||
// forward so we can make the following typedefs easily visible in the header.
|
||||
// rather than buried under the class definition.
|
||||
class SkyRenderableInstance;
|
||||
|
||||
//! A dynamic array of SkyRenderableInstance pointers.
|
||||
typedef std::vector<SkyRenderableInstance*> InstanceArray;
|
||||
//! An instance array iterator.
|
||||
typedef InstanceArray::iterator InstanceIterator;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderableInstance
|
||||
* @brief An instance of a SkyRenderable object.
|
||||
*
|
||||
* An instance contains a pointer to a SkyRenderable object. The
|
||||
* instance contains attributes such as position, orientation,
|
||||
* scale, etc. that vary between instances.
|
||||
*/
|
||||
class SkyRenderableInstance
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
SkyRenderableInstance()
|
||||
: _bCulled(false), _bAlive(true), _vecPosition(0, 0, 0), _rScale(1), _rSquareSortDistance(0)
|
||||
{
|
||||
_matRotation.Identity(); _matInvRotation.Identity();
|
||||
}
|
||||
|
||||
//! Constructor.
|
||||
SkyRenderableInstance(const Vec3f &position,
|
||||
const Mat33f &rotation,
|
||||
const float scale)
|
||||
: _bCulled(false), _bAlive(true), _vecPosition(position),
|
||||
_matRotation(rotation), _rScale(scale), _rSquareSortDistance(0)
|
||||
{
|
||||
_matInvRotation = _matRotation;
|
||||
_matInvRotation.Transpose();
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
virtual ~SkyRenderableInstance() {}
|
||||
|
||||
// Setters / Getters
|
||||
//! Set the world space position of the instance.
|
||||
virtual void SetPosition(const Vec3f &position) { _vecPosition = position; }
|
||||
//! Set the world space rotation of the instance.
|
||||
virtual void SetRotation(const Mat33f &rotation) { _matRotation = rotation;
|
||||
_matInvRotation = rotation;
|
||||
_matInvRotation.Transpose(); }
|
||||
//! Set the world space scale of the instance.
|
||||
virtual void SetScale( const float &scale) { _rScale = scale; }
|
||||
|
||||
//! Returns the world space position of the instance.
|
||||
virtual const Vec3f& GetPosition() const { return _vecPosition; }
|
||||
//! Returns the world space rotation matrix of the instance.
|
||||
virtual const Mat33f& GetRotation() const { return _matRotation; }
|
||||
//! Returns the inverse of the world space rotation matrix of the instance.
|
||||
virtual const Mat33f& GetInverseRotation() const { return _matInvRotation; }
|
||||
//! Returns the world space scale of the instance.
|
||||
virtual float GetScale() const { return _rScale; }
|
||||
|
||||
//! Update the instance based on the given camera, @a cam.
|
||||
virtual SKYRESULT Update(const Camera &cam) { return SKYRESULT_OK; }
|
||||
//! Render the instance.
|
||||
virtual SKYRESULT Display() { return SKYRESULT_OK; }
|
||||
|
||||
//! Returns the transform matrix from model space to world space.
|
||||
inline virtual void GetModelToWorldTransform(Mat44f &mat) const;
|
||||
|
||||
//! Returns the transform matrix from world space to model space.
|
||||
|
||||
inline virtual void GetWorldToModelTransform(Mat44f &mat) const;
|
||||
|
||||
//! Returns the object-space bounding volume for this instance, or NULL if none is available.
|
||||
virtual SkyMinMaxBox* GetBoundingVolume() const { return NULL; }
|
||||
|
||||
//! Returns true if and only if the bounding volume of this instance lies entirely outside @a cam.
|
||||
virtual bool ViewFrustumCull(const Camera &cam) { return false; }
|
||||
//! Returns true if the instance was culled.
|
||||
virtual bool IsCulled() { return _bCulled; }
|
||||
//! Sets the culled state of the instance.
|
||||
virtual void SetCulled(bool bCulled) { _bCulled = bCulled; }
|
||||
|
||||
//! Returns true if the instance is currently active.
|
||||
virtual bool IsAlive() { return _bAlive; }
|
||||
//! Activates or deactivates the instance.
|
||||
virtual void SetIsAlive(bool bAlive) { _bAlive = bAlive; }
|
||||
|
||||
//! Sets the distance of this object from the sort position. Used to sort instances.
|
||||
virtual void SetSquareSortDistance(float rSqrDist) { _rSquareSortDistance = rSqrDist; }
|
||||
//! Returns the distance of this object from the sort position. (Set with SetSquareSortDistance())
|
||||
virtual float GetSquareSortDistace() const { return _rSquareSortDistance; }
|
||||
|
||||
//! This operator is used to sort instance arrays.
|
||||
bool operator<(const SkyRenderableInstance& instance) const
|
||||
{
|
||||
return (_rSquareSortDistance > instance._rSquareSortDistance);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _bCulled; // Culled flag
|
||||
bool _bAlive; // Alive object flag
|
||||
|
||||
Vec3f _vecPosition; // Position
|
||||
Mat33f _matRotation; // Rotation
|
||||
Mat33f _matInvRotation; // inverse rotation
|
||||
float _rScale; // Scale
|
||||
|
||||
// for sorting particles during shading
|
||||
float _rSquareSortDistance;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstance::GetModelToWorldTransform
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstance::GetModelToWorldTransform(Mat44f &mat) const
|
||||
* @brief Returns the 4x4 transformation matrix from world to model space.
|
||||
*/
|
||||
inline void SkyRenderableInstance::GetModelToWorldTransform(Mat44f &mat) const
|
||||
{
|
||||
mat[0] = _matRotation.M[0]; mat[4] = _matRotation.M[3];
|
||||
mat[8] = _matRotation.M[6]; mat[12] = 0;
|
||||
mat[1] = _matRotation.M[1]; mat[5] = _matRotation.M[4];
|
||||
mat[9] = _matRotation.M[7]; mat[13] = 0;
|
||||
mat[2] = _matRotation.M[2]; mat[6] = _matRotation.M[5];
|
||||
mat[10] = _matRotation.M[8]; mat[14] = 0;
|
||||
mat[3] = 0; mat[7] = 0; mat[11] = 0; mat[15] = 0;
|
||||
|
||||
// Scale the matrix (we don't want to scale translation or mat[15] which is 1)
|
||||
if (_rScale != 1)
|
||||
mat *= _rScale;
|
||||
|
||||
// Set the translation and w coordinate after the potential scaling
|
||||
mat[12] = _vecPosition.x; mat[13] = _vecPosition.y; mat[14] = _vecPosition.z;
|
||||
mat[15] = 1;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Mat44f& SkyRenderableInstance::GetWorldToModelTransform
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstance::GetWorldToModelTransform(Mat44f &mat) const
|
||||
* @brief Returns the 4x4 transformation matrix from world to model space.
|
||||
*/
|
||||
inline void SkyRenderableInstance::GetWorldToModelTransform(Mat44f &mat) const
|
||||
{
|
||||
mat[0] = _matRotation.M[0]; mat[4] = _matRotation.M[1];
|
||||
mat[8] = _matRotation.M[2]; mat[12] = 0;
|
||||
mat[1] = _matRotation.M[3]; mat[5] = _matRotation.M[4];
|
||||
mat[9] = _matRotation.M[5]; mat[13] = 0;
|
||||
mat[2] = _matRotation.M[6]; mat[6] = _matRotation.M[7];
|
||||
mat[10] = _matRotation.M[8]; mat[14] = 0;
|
||||
mat[3] = 0; mat[7] = 0; mat[11] = 0; mat[15] = 0;
|
||||
|
||||
// Scale the matrix (we don't want to scale translation or mat[15] which is 1)
|
||||
if (_rScale != 1)
|
||||
mat *= (1 / _rScale);
|
||||
|
||||
// Set the translation and w coordinate after the potential scaling
|
||||
mat[12] = -_vecPosition.x; mat[13] = -_vecPosition.y; mat[14] = -_vecPosition.z;
|
||||
mat[15] = 1;
|
||||
}
|
||||
|
||||
#endif //__SKYRENDERABLEINSTANCE_HPP__
|
||||
705
simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.cpp
Normal file
705
simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.cpp
Normal file
@@ -0,0 +1,705 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceCloud.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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.cpp
|
||||
*
|
||||
* Implementation of class SkyRenderableInstanceCloud.
|
||||
*/
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkyCloud.hpp"
|
||||
#include "SkyMaterial.hpp"
|
||||
#include "SkyBoundingVolume.hpp"
|
||||
#include "SkyRenderableInstanceCloud.hpp"
|
||||
#include "SkyDynamicTextureManager.hpp"
|
||||
|
||||
//! Set this to 1 to see verbose messages about impostor updates.
|
||||
#define SKYCLOUD_VERBOSE 0
|
||||
|
||||
//! Set this to control the number of frames a cloud has to be culled before its textures are released.
|
||||
#define SKYCLOUD_CULL_RELEASE_COUNT 100
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Static declarations.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int SkyRenderableInstanceCloud::s_iCount = 0;
|
||||
float SkyRenderableInstanceCloud::s_rErrorToleranceAngle = SKYDEGREESTORADS * 0.125f;
|
||||
SkyMaterial* SkyRenderableInstanceCloud::s_pMaterial = NULL;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::SkyRenderableInstanceCloud
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::SkyRenderableInstanceCloud(SkyCloud *pCloud, bool bUseOffScreenBuffer)
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyRenderableInstanceCloud::SkyRenderableInstanceCloud(SkyCloud *pCloud,
|
||||
bool bUseOffScreenBuffer /* = true */)
|
||||
: SkyRenderableInstance(),
|
||||
_iCloudID(-1),
|
||||
_pCloud(pCloud),
|
||||
_pWorldSpaceBV(NULL),
|
||||
_rRadius(0),
|
||||
_bScreenImpostor(false),
|
||||
_bImageExists(false),
|
||||
_bEnabled(true),
|
||||
_bUseOffScreenBuffer(bUseOffScreenBuffer),
|
||||
_bSplit(false),
|
||||
_vecSplit(0, 0, 0),
|
||||
_vecNearPoint(0, 0, 0),
|
||||
_vecFarPoint(0, 0, 0),
|
||||
_iLogResolution(0),
|
||||
_pBackTexture(NULL),
|
||||
_pFrontTexture(NULL),
|
||||
_iCulledCount(0)
|
||||
{
|
||||
_Initialize();
|
||||
cout << "Cloud Instance created" << endl;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::SkyRenderableInstanceCloud
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::SkyRenderableInstanceCloud(SkyCloud *pCloud, const Vec3f &position, const Mat33f &rotation, const float scale, bool bUseOffScreenBuffer)
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyRenderableInstanceCloud::SkyRenderableInstanceCloud(SkyCloud *pCloud,
|
||||
const Vec3f &position,
|
||||
const Mat33f &rotation,
|
||||
const float scale,
|
||||
bool bUseOffScreenBuffer /* = true */)
|
||||
: SkyRenderableInstance(position, rotation, scale),
|
||||
_iCloudID(-1),
|
||||
_pCloud(pCloud),
|
||||
_pWorldSpaceBV(NULL),
|
||||
_rRadius(0),
|
||||
_bScreenImpostor(false),
|
||||
_bImageExists(false),
|
||||
_bEnabled(true),
|
||||
_bUseOffScreenBuffer(false),
|
||||
_bSplit(false),
|
||||
_vecSplit(0, 0, 0),
|
||||
_vecNearPoint(0, 0, 0),
|
||||
_vecFarPoint(0, 0, 0),
|
||||
_iLogResolution(0),
|
||||
_pBackTexture(NULL),
|
||||
_pFrontTexture(NULL)
|
||||
{
|
||||
_Initialize();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::~SkyRenderableInstanceCloud
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::~SkyRenderableInstanceCloud()
|
||||
* @brief Destructor
|
||||
*/
|
||||
SkyRenderableInstanceCloud::~SkyRenderableInstanceCloud()
|
||||
{
|
||||
_pCloud = NULL;
|
||||
SAFE_DELETE(_pWorldSpaceBV);
|
||||
|
||||
s_iCount--;
|
||||
// delete the offscreen buffer when no one else is using it.
|
||||
if (0 == s_iCount)
|
||||
{
|
||||
//JW?? SAFE_DELETE(s_pRenderBuffer);
|
||||
SAFE_DELETE(s_pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::SetPosition
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::SetPosition(const Vec3f &position)
|
||||
* @brief Set the world space position of the instance.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyRenderableInstanceCloud::SetPosition FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyRenderableInstanceCloud::SetPosition(const Vec3f &position)
|
||||
{
|
||||
if (_pCloud)
|
||||
{
|
||||
_pCloud->Translate(position - _vecPosition);
|
||||
}
|
||||
_vecPosition = position;
|
||||
|
||||
_UpdateWorldSpaceBounds();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::SetRotation
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::SetRotation(const Mat33f &rotation)
|
||||
* @brief Set the world space rotation of the instance.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyRenderableInstanceCloud::SetRotation FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyRenderableInstanceCloud::SetRotation(const Mat33f &rotation)
|
||||
{
|
||||
if (_pCloud)
|
||||
{
|
||||
_pCloud->Translate(-_vecPosition);
|
||||
_pCloud->Rotate(_matInvRotation * rotation);
|
||||
_pCloud->Translate(_vecPosition);
|
||||
}
|
||||
_matRotation = rotation;
|
||||
_matInvRotation = rotation;
|
||||
_matInvRotation.Transpose();
|
||||
_UpdateWorldSpaceBounds();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::SetScale
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::SetScale(const float &scale)
|
||||
* @brief Set the world space scale of the instance.
|
||||
*/
|
||||
void SkyRenderableInstanceCloud::SetScale(const float &scale)
|
||||
{
|
||||
if (_pCloud)
|
||||
{
|
||||
_pCloud->Translate(-_vecPosition);
|
||||
_pCloud->Scale(scale);
|
||||
_pCloud->Translate(_vecPosition);
|
||||
}
|
||||
_rScale = scale;
|
||||
_UpdateWorldSpaceBounds();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : DrawQuad
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* DrawQuad(Vec3f pos, Vec3f x, Vec3f y, Vec4f color)
|
||||
* @brief Simply draws an OpenGL quad at @a pos.
|
||||
*
|
||||
* The quad's size and orientation are determined by the (non-unit) vectors @a x
|
||||
* and @a y. Its color is given by @a color.
|
||||
*/
|
||||
inline void DrawQuad(Vec3f pos, Vec3f x, Vec3f y, Vec4f color)
|
||||
{
|
||||
glColor4fv(&(color.x));
|
||||
Vec3f left = pos; left -= y;
|
||||
Vec3f right = left; right += x;
|
||||
left -= x;
|
||||
glTexCoord2f(0, 0); glVertex3fv(&(left.x));
|
||||
glTexCoord2f(1, 0); glVertex3fv(&(right.x));
|
||||
left += y; left += y;
|
||||
right += y; right += y;
|
||||
glTexCoord2f(1, 1); glVertex3fv(&(right.x));
|
||||
glTexCoord2f(0, 1); glVertex3fv(&(left.x));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::Display(bool bDisplayFrontOfSplit)
|
||||
* @brief Display the instance of the cloud using the impostor image.
|
||||
*/
|
||||
SKYRESULT SkyRenderableInstanceCloud::Display(bool bDisplayFrontOfSplit /* = false */)
|
||||
{
|
||||
|
||||
if (!_bImageExists || !_bEnabled)
|
||||
{
|
||||
//FAIL_RETURN(DisplayWithoutImpostor(*(GLVU::GetCurrent()->GetCurrentCam())));
|
||||
FAIL_RETURN(DisplayWithoutImpostor(Camera::Camera()));
|
||||
}
|
||||
else
|
||||
{
|
||||
//cout << "Using impostor image\n";
|
||||
if (!_pBackTexture || (bDisplayFrontOfSplit && !_pFrontTexture))
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyRenderableInstanceCloud::Display(): missing texture!");
|
||||
|
||||
s_pMaterial->SetTexture(0, GL_TEXTURE_2D, bDisplayFrontOfSplit ? *_pFrontTexture : *_pBackTexture);
|
||||
if (_bScreenImpostor)
|
||||
{
|
||||
s_pMaterial->EnableDepthTest(false);
|
||||
}
|
||||
else if (_bSplit)
|
||||
{
|
||||
if (!bDisplayFrontOfSplit)
|
||||
{
|
||||
s_pMaterial->EnableDepthTest(true);
|
||||
s_pMaterial->SetDepthMask(false);
|
||||
}
|
||||
else
|
||||
s_pMaterial->EnableDepthTest(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_pMaterial->EnableDepthTest(true);
|
||||
s_pMaterial->SetDepthMask(true);
|
||||
}
|
||||
|
||||
s_pMaterial->Activate();
|
||||
|
||||
Vec3f x, y, z;
|
||||
|
||||
if (!_bScreenImpostor)
|
||||
{
|
||||
//cout << "Outside the cloud\n";
|
||||
z = _vecPosition;
|
||||
z -= _impostorCam.Orig;
|
||||
z.Normalize();
|
||||
x = (z ^ _impostorCam.Y);
|
||||
x.Normalize();
|
||||
x *= _rRadius;
|
||||
y = (x ^ z);
|
||||
y.Normalize();
|
||||
y *= _rRadius;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
DrawQuad(_vecPosition, x, y, Vec4f(1, 1, 1, 1));
|
||||
glEnd();
|
||||
}
|
||||
else
|
||||
{ //cout << "Drawing a polygon - must be inside a cloud\n";
|
||||
x = _impostorCam.X;
|
||||
x *= 0.5f * (_impostorCam.wR - _impostorCam.wL);
|
||||
y = _impostorCam.Y;
|
||||
y *= 0.5f * (_impostorCam.wT - _impostorCam.wB);
|
||||
z = -_impostorCam.Z;
|
||||
z *= _impostorCam.Near;
|
||||
|
||||
// draw a polygon with this texture...
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(-1, 1, -1, 1);
|
||||
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0); glVertex2f(-1, -1);
|
||||
glTexCoord2f(1, 0); glVertex2f(1, -1);
|
||||
glTexCoord2f(1, 1); glVertex2f(1, 1);
|
||||
glTexCoord2f(0, 1); glVertex2f(-1, 1);
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::DisplayWithoutImpostor
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::DisplayWithoutImpostor(const Camera &cam)
|
||||
* @brief Displays the cloud directly -- without an impotor.
|
||||
*
|
||||
* This is used both when the impostor is disabled and to create the impostor image
|
||||
* when it needs to be updated.
|
||||
*/
|
||||
SKYRESULT SkyRenderableInstanceCloud::DisplayWithoutImpostor(const Camera &cam)
|
||||
{
|
||||
// Get and set the world space transformation
|
||||
/*Mat44f mat;
|
||||
GetModelToWorldTransform(mat);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat.M);*/
|
||||
|
||||
FAIL_RETURN_MSG(_pCloud->Display(cam, this), "SkyRenderableInstanceCloud:Display(): Cloud's display failed.");
|
||||
|
||||
//glMatrixMode(GL_MODELVIEW);
|
||||
//glPopMatrix();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::ViewFrustumCull
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::ViewFrustumCull(const Camera &cam)
|
||||
* @brief View frustum cull the object given its world position
|
||||
*/
|
||||
bool SkyRenderableInstanceCloud::ViewFrustumCull(const Camera &cam)
|
||||
{
|
||||
Mat44f xform;
|
||||
//GetModelToWorldTransform(xform);
|
||||
xform.Identity();
|
||||
_bCulled = (_pWorldSpaceBV == NULL) ? false : _pWorldSpaceBV->ViewFrustumCull(cam, xform);
|
||||
return _bCulled;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::ReleaseImpostorTextures
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::ReleaseImpostorTextures()
|
||||
* @brief Causes the instance to release its impostor textures for use by other impostors.
|
||||
*
|
||||
* This method is called when the cloud is view frustum culled.
|
||||
*/
|
||||
void SkyRenderableInstanceCloud::ReleaseImpostorTextures()
|
||||
{
|
||||
_iCulledCount++;
|
||||
|
||||
if (_iCulledCount > SKYCLOUD_CULL_RELEASE_COUNT)
|
||||
{
|
||||
_iCulledCount = 0;
|
||||
|
||||
if (_pBackTexture)
|
||||
{
|
||||
DynamicTextureManager::InstancePtr()->CheckInTexture(_pBackTexture);
|
||||
_pBackTexture = NULL;
|
||||
}
|
||||
|
||||
if (_pFrontTexture)
|
||||
{
|
||||
DynamicTextureManager::InstancePtr()->CheckInTexture(_pFrontTexture);
|
||||
_pFrontTexture = NULL;
|
||||
}
|
||||
_bImageExists = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::Update
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::Update(const Camera &cam)
|
||||
* @brief Updates the impostor image to be valid for the current viewpoint.
|
||||
*
|
||||
* If the image is already valid, exits early.
|
||||
*
|
||||
* @see SetErrorToleranceAngle, IsValid
|
||||
*/
|
||||
SKYRESULT SkyRenderableInstanceCloud::Update(const Camera &cam)
|
||||
{
|
||||
if (!_bEnabled || IsImpostorValid(cam))
|
||||
return SKYRESULT_OK;
|
||||
|
||||
// since we are going to update it anyway, let's make sure we don't try to use it if something
|
||||
// goes wrong. This will be set to true on the successful completion of this Update() method.
|
||||
_bImageExists = false;
|
||||
//cout << "updating impostor\n";
|
||||
Mat44f M;
|
||||
|
||||
_impostorCam = cam;
|
||||
float rDistance = (_vecPosition - cam.Orig).Length();
|
||||
|
||||
float rRadius = _pWorldSpaceBV->GetRadius();
|
||||
float rCamRadius = sqrt(cam.wR*cam.wR + cam.Near*cam.Near);
|
||||
|
||||
float rWidth = cam.wR - cam.wL;
|
||||
float rHeight = cam.wT - cam.wB;
|
||||
float rMaxdim = (rWidth > rHeight) ? rWidth : rHeight;
|
||||
|
||||
if (rRadius * cam.Near / rDistance < 0.5 * rMaxdim && (rDistance - rRadius > rCamRadius))
|
||||
{ // outside cloud
|
||||
_impostorCam.TightlyFitToSphere(cam.Orig, cam.Y, _vecPosition, rRadius);
|
||||
_rRadius = 0.5f * (_impostorCam.wR - _impostorCam.wL) * rDistance / _impostorCam.Near;
|
||||
_rRadius *= GetScale();
|
||||
_bScreenImpostor = false;
|
||||
// store points used in later error estimation
|
||||
_vecNearPoint = -_impostorCam.Z;
|
||||
_vecNearPoint *= _impostorCam.Near;
|
||||
_vecNearPoint += _impostorCam.Orig;
|
||||
_vecFarPoint = -_impostorCam.Z;
|
||||
_vecFarPoint *= _impostorCam.Far;
|
||||
_vecFarPoint += _impostorCam.Orig;
|
||||
}
|
||||
else // inside cloud
|
||||
{
|
||||
_impostorCam.Far = _impostorCam.Near + 3 * rRadius;
|
||||
_bScreenImpostor = true;
|
||||
}
|
||||
|
||||
// resolution based on screensize, distance, and object size.
|
||||
// Cam radius is used to heuristically reduce resolution for clouds very close to the camera.
|
||||
_iLogResolution = _GetRequiredLogResolution(rDistance, rRadius, rCamRadius);
|
||||
|
||||
int iRes = 1 << _iLogResolution;
|
||||
|
||||
int iOldVP[4];
|
||||
|
||||
glGetIntegerv(GL_VIEWPORT, iOldVP);
|
||||
|
||||
_impostorCam.GetProjectionMatrix(M);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadMatrixf(M);
|
||||
|
||||
_impostorCam.GetModelviewMatrix(M);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadMatrixf(M);
|
||||
|
||||
glViewport(0, 0, iRes, iRes);
|
||||
|
||||
s_pMaterial->SetDepthMask(true); // so that the depth buffer gets cleared!
|
||||
s_pMaterial->Activate();
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
if (!_bSplit)
|
||||
{
|
||||
FAIL_RETURN(DisplayWithoutImpostor(_impostorCam));
|
||||
|
||||
if (_pBackTexture && _pBackTexture->GetWidth() != iRes)
|
||||
{
|
||||
DynamicTextureManager::InstancePtr()->CheckInTexture(_pBackTexture);
|
||||
_pBackTexture = NULL;
|
||||
}
|
||||
|
||||
if (!_pBackTexture)
|
||||
{
|
||||
_pBackTexture = DynamicTextureManager::InstancePtr()->CheckOutTexture(iRes, iRes);
|
||||
}
|
||||
|
||||
s_pMaterial->SetTexture(0, GL_TEXTURE_2D, *_pBackTexture); // shared material for clouds.
|
||||
s_pMaterial->Activate();
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, iRes, iRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL_RETURN_MSG(_pCloud->DisplaySplit(cam, _vecSplit, true, this),
|
||||
"SkyRenderableInstanceCloud:Display(): Cloud's display failed.");
|
||||
|
||||
if (_pBackTexture && _pBackTexture->GetWidth() != iRes)
|
||||
{
|
||||
DynamicTextureManager::InstancePtr()->CheckInTexture(_pBackTexture);
|
||||
_pBackTexture = NULL;
|
||||
}
|
||||
if (_pFrontTexture && _pFrontTexture->GetWidth() != iRes)
|
||||
{
|
||||
DynamicTextureManager::InstancePtr()->CheckInTexture(_pFrontTexture);
|
||||
_pFrontTexture = NULL;
|
||||
}
|
||||
|
||||
if (!_pBackTexture)
|
||||
{
|
||||
_pBackTexture = DynamicTextureManager::InstancePtr()->CheckOutTexture(iRes, iRes);
|
||||
}
|
||||
|
||||
s_pMaterial->SetTexture(0, GL_TEXTURE_2D, *_pBackTexture); // shared material for clouds.
|
||||
FAIL_RETURN(s_pMaterial->Activate());
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, iRes, iRes);
|
||||
|
||||
// now clear and draw the front.
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
FAIL_RETURN_MSG(_pCloud->DisplaySplit(cam, _vecSplit, false, this),
|
||||
"SkyRenderableInstanceCloud:Display(): Cloud's display failed.");
|
||||
|
||||
if (!_pFrontTexture)
|
||||
{
|
||||
_pFrontTexture = DynamicTextureManager::InstancePtr()->CheckOutTexture(iRes, iRes);
|
||||
}
|
||||
|
||||
s_pMaterial->GetTextureState().SetTexture(0, GL_TEXTURE_2D, *_pFrontTexture);
|
||||
FAIL_RETURN(s_pMaterial->GetTextureState().Activate());
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, iRes, iRes);
|
||||
}
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
||||
//GLVU::CheckForGLError("Cloud Impostor Update");
|
||||
|
||||
glViewport(iOldVP[0], iOldVP[1], iOldVP[2], iOldVP[3]);
|
||||
|
||||
_bImageExists = true;
|
||||
|
||||
// the textures should now exist.
|
||||
assert(_pBackTexture);
|
||||
assert(!_bSplit || (_bSplit && _pFrontTexture));
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::IsImpostorValid
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::IsImpostorValid(const Camera& cam)
|
||||
* @brief Returns true if the impostor image is valid for the given camera.
|
||||
*
|
||||
* Will return false if this is a screen impostor, or if there is error in either
|
||||
* the translation of the camera from the capture point or the impostor image resolution.
|
||||
*
|
||||
* @see SetErrorToleranceAngle
|
||||
*/
|
||||
bool SkyRenderableInstanceCloud::IsImpostorValid(const Camera& cam)
|
||||
{
|
||||
// first make sure there is a current image.
|
||||
if (!_bImageExists)
|
||||
return false;
|
||||
|
||||
// screen impostors should always be updated
|
||||
if (_bScreenImpostor)
|
||||
{
|
||||
_vecFarPoint = Vec3f::ZERO;
|
||||
_vecNearPoint = Vec3f::ZERO;
|
||||
#if SKYCLOUD_VERBOSE
|
||||
SkyTrace("Screen Impostor Update");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
// impostors are valid from the viewpoint from which they were captured
|
||||
if (cam.Orig == _impostorCam.Orig)
|
||||
return true;
|
||||
|
||||
if (_bSplit)
|
||||
{
|
||||
#if SKYCLOUD_VERBOSE
|
||||
SkyTrace("Split Impostor Update");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
Vec3f vecX = _vecNearPoint - cam.Orig;
|
||||
Vec3f vecY = _vecFarPoint - cam.Orig;
|
||||
float rXLength = vecX.Length();
|
||||
float rYLength = vecY.Length();
|
||||
if (rXLength > rYLength)
|
||||
{
|
||||
#if SKYCLOUD_VERBOSE
|
||||
SkyTrace("Backwards Impostor Update");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
vecX /= rXLength;
|
||||
vecY /= rYLength;
|
||||
float rCosAlpha = vecX * vecY; // dot product of normalized vectors = cosine
|
||||
|
||||
if (fabs(rCosAlpha) < 1.0)
|
||||
{
|
||||
float rAlpha = acos(rCosAlpha);
|
||||
if (rAlpha >= s_rErrorToleranceAngle)
|
||||
{
|
||||
#if SKYCLOUD_VERBOSE
|
||||
SkyTrace("Angle Error Update %f", SKYRADSTODEGREES * rAlpha);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
float rDistance = (_vecPosition - cam.Orig).Length();
|
||||
float rCamRadius = sqrt(cam.wR*cam.wR + cam.Near*cam.Near);
|
||||
|
||||
int iRes = _GetRequiredLogResolution(rDistance, _pWorldSpaceBV->GetRadius(), rCamRadius);
|
||||
|
||||
if (iRes > _iLogResolution)
|
||||
{
|
||||
#if SKYCLOUD_VERBOSE
|
||||
SkyTrace("Resolution Error Update: Required: %d Actual: %d", iRes, _iLogResolution);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SetErrorToleranceAngle
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::SetErrorToleranceAngle(float rDegrees)
|
||||
* @brief Set the global error tolerance angle for all impostors.
|
||||
*/
|
||||
void SkyRenderableInstanceCloud::SetErrorToleranceAngle(float rDegrees)
|
||||
{
|
||||
s_rErrorToleranceAngle = SKYDEGREESTORADS * rDegrees;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::_Initialize
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::_Initialize()
|
||||
* @brief Initializer used by the constructors.
|
||||
*/
|
||||
void SkyRenderableInstanceCloud::_Initialize()
|
||||
{
|
||||
_UpdateWorldSpaceBounds();
|
||||
|
||||
// if (!s_pRenderBuffer && _bUseOffScreenBuffer)
|
||||
// {
|
||||
//JW?? s_pRenderBuffer = new SkyOffScreenBuffer(GLUT_SINGLE | GLUT_DEPTH | GLUT_STENCIL);
|
||||
//JW?? s_pRenderBuffer->Initialize(true);
|
||||
|
||||
//JW?? s_pRenderBuffer->MakeCurrent();
|
||||
// set some GL state:
|
||||
// glClearColor(0, 0, 0, 0);
|
||||
//JW?? GLVU::GetCurrent()->MakeCurrent();
|
||||
// }
|
||||
if (!s_pMaterial)
|
||||
{
|
||||
s_pMaterial = new SkyMaterial;
|
||||
s_pMaterial->EnableBlending(true);
|
||||
s_pMaterial->SetBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
s_pMaterial->SetAlphaFunc(GL_GREATER);
|
||||
s_pMaterial->EnableDepthTest(false);
|
||||
s_pMaterial->SetDepthMask(true);
|
||||
s_pMaterial->EnableAlphaTest(true);
|
||||
s_pMaterial->EnableLighting(false);
|
||||
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
s_pMaterial->EnableTexture(0, true);
|
||||
}
|
||||
273
simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.hpp
Normal file
273
simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.hpp
Normal file
@@ -0,0 +1,273 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 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__
|
||||
136
simgear/scene/sky/clouds3d/SkyRenderableInstanceGeneric.cpp
Normal file
136
simgear/scene/sky/clouds3d/SkyRenderableInstanceGeneric.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceGeneric.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyRenderableInstanceGeneric.cpp
|
||||
*
|
||||
* A basic implementation of SkyRenderableInstance
|
||||
*/
|
||||
|
||||
#include "glvu.hpp"
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkyRenderable.hpp"
|
||||
#include "SkyMinMaxBox.hpp"
|
||||
#include "SkyRenderableInstanceGeneric.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGeneric::SkyRenderableInstanceGeneric
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGeneric::SkyRenderableInstanceGeneric(SkyRenderable *object)
|
||||
* @brief Constructor, store the renderable and set the position to identity
|
||||
*/
|
||||
SkyRenderableInstanceGeneric::SkyRenderableInstanceGeneric(SkyRenderable *pObject)
|
||||
: SkyRenderableInstance(),
|
||||
_pObj(pObject)
|
||||
{
|
||||
_pBV = pObject->CopyBoundingVolume();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGeneric::SkyRenderableInstanceGeneric
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGeneric::SkyRenderableInstanceGeneric(SkyRenderable *object, const Vec3f &position, const Mat33f &rotation, const float scale)
|
||||
* @brief Constructor, stores the instance information given
|
||||
*/
|
||||
SkyRenderableInstanceGeneric::SkyRenderableInstanceGeneric(SkyRenderable *pObject,
|
||||
const Vec3f &position,
|
||||
const Mat33f &rotation,
|
||||
const float scale)
|
||||
: SkyRenderableInstance(position, rotation, scale),
|
||||
_pObj(pObject)
|
||||
{
|
||||
_pBV = pObject->CopyBoundingVolume();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGeneric::~SkyRenderableInstanceGeneric
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGeneric::~SkyRenderableInstanceGeneric()
|
||||
* @brief Destructor
|
||||
*/
|
||||
SkyRenderableInstanceGeneric::~SkyRenderableInstanceGeneric()
|
||||
{
|
||||
_pObj = NULL;
|
||||
SAFE_DELETE(_pBV);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGeneric::SetRenderable
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGeneric::SetRenderable(SkyRenderable *pRenderable)
|
||||
* @brief Set the renderable for this instance.
|
||||
*/
|
||||
void SkyRenderableInstanceGeneric::SetRenderable(SkyRenderable *pRenderable)
|
||||
{
|
||||
_pObj = pRenderable;
|
||||
SAFE_DELETE(_pBV);
|
||||
_pBV = pRenderable->CopyBoundingVolume();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGeneric::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGeneric::Display()
|
||||
* @brief Displays the instance by calling the renderable's display function
|
||||
*/
|
||||
SKYRESULT SkyRenderableInstanceGeneric::Display()
|
||||
{
|
||||
// Get and set the world space transformation
|
||||
Mat44f mat;
|
||||
GetModelToWorldTransform(mat);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat.M);
|
||||
|
||||
//FAIL_RETURN_MSG(_pObj->Display(*(GLVU::GetCurrent()->GetCurrentCam()), this),
|
||||
// "SkyRenderableInstanceGeneric:Display(), error returned from object's display");
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGeneric::ViewFrustumCull
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGeneric::ViewFrustumCull(const Camera &cam)
|
||||
* @brief View frustum cull the object given its world position
|
||||
*/
|
||||
bool SkyRenderableInstanceGeneric::ViewFrustumCull(const Camera &cam)
|
||||
{
|
||||
Mat44f xform;
|
||||
GetModelToWorldTransform(xform);
|
||||
_bCulled = (_pBV == NULL) ? false : _pBV->ViewFrustumCull(cam, xform);
|
||||
return _bCulled;
|
||||
}
|
||||
76
simgear/scene/sky/clouds3d/SkyRenderableInstanceGeneric.hpp
Normal file
76
simgear/scene/sky/clouds3d/SkyRenderableInstanceGeneric.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceGeneric.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 SkyRenderableInstanceGeneric.hpp
|
||||
*
|
||||
* Interface for a basic implementation of SkyRenderableInstance
|
||||
*/
|
||||
#ifndef __SKYRENDERABLEINSTANCEGENERIC_HPP__
|
||||
#define __SKYRENDERABLEINSTANCEGENERIC_HPP__
|
||||
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class SkyRenderable;
|
||||
class SkyMinMaxBox;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderableInstanceGeneric
|
||||
* @brief A generic renderable instance
|
||||
*
|
||||
* The SkyRenderableInstanceGeneric is a basic implementation of the base class.
|
||||
* For view frustum culling, the function ViewFrustumCull should be called once
|
||||
* per frame, at which point a flag is set if the object is culled or not. It
|
||||
* is possible that the object is then queried multiple times if it is culled or
|
||||
* not by various other objects before being displayed, that is why the flag is
|
||||
* stored.
|
||||
*/
|
||||
class SkyRenderableInstanceGeneric : public SkyRenderableInstance
|
||||
{
|
||||
public:
|
||||
SkyRenderableInstanceGeneric(SkyRenderable *pObject);
|
||||
SkyRenderableInstanceGeneric(SkyRenderable *pObject,
|
||||
const Vec3f &position,
|
||||
const Mat33f &rotation,
|
||||
const float scale);
|
||||
virtual ~SkyRenderableInstanceGeneric();
|
||||
|
||||
// Setters / Getters
|
||||
|
||||
virtual void SetRenderable(SkyRenderable *pRenderable );
|
||||
|
||||
//! Returns a pointer to the renderable that this instance represents.
|
||||
virtual SkyRenderable* GetRenderable() const { return _pObj; }
|
||||
|
||||
virtual SKYRESULT Display();
|
||||
|
||||
// Test / Set / Get
|
||||
virtual bool ViewFrustumCull( const Camera &cam );
|
||||
|
||||
|
||||
virtual SkyMinMaxBox* GetBoundingVolume() const { return _pBV; }
|
||||
|
||||
protected:
|
||||
|
||||
protected:
|
||||
SkyRenderable *_pObj; // Pointer to the renderable object
|
||||
SkyMinMaxBox *_pBV; // Pointer to bounding volume
|
||||
};
|
||||
|
||||
#endif //__SKYRENDERABLEINSTANCEGENERIC_HPP__
|
||||
178
simgear/scene/sky/clouds3d/SkyRenderableInstanceGroup.cpp
Normal file
178
simgear/scene/sky/clouds3d/SkyRenderableInstanceGroup.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceGroup.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyRenderableInstanceGroup.cpp
|
||||
*
|
||||
* Implementation of class SkyRenderableInstanceGroup, an instance that groups
|
||||
* other instances.
|
||||
*/
|
||||
|
||||
#include <GL/glut.h>
|
||||
#include "SkyRenderableInstanceGroup.hpp"
|
||||
#include "SkySceneManager.hpp"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::SkyRenderableInstanceGroup
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::SkyRenderableInstanceGroup()
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyRenderableInstanceGroup::SkyRenderableInstanceGroup()
|
||||
: SkyRenderableInstance(),
|
||||
_pObjectSpaceBV(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::Update
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::Update(const Camera &cam)
|
||||
* @brief Processes any per frame updates the instance requires.
|
||||
*
|
||||
* This method simply calls the SkyRenderableInstance::Update() method of each of
|
||||
* its sub-instances.
|
||||
*/
|
||||
SKYRESULT SkyRenderableInstanceGroup::Update(const Camera &cam)
|
||||
{
|
||||
InstanceIterator ii;
|
||||
for (ii = _opaqueSubInstances.begin(); ii != _opaqueSubInstances.end(); ++ii)
|
||||
{
|
||||
FAIL_RETURN((*ii)->Update(cam));
|
||||
}
|
||||
for (ii = _transparentSubInstances.begin(); ii != _transparentSubInstances.end(); ++ii)
|
||||
{
|
||||
FAIL_RETURN((*ii)->Update(cam));
|
||||
}
|
||||
|
||||
SkySceneManager::SortInstances(_transparentSubInstances, cam.Orig);
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::Display()
|
||||
* @brief Displays all sub-instances of this instance.
|
||||
*
|
||||
* The object-to-world transform of this instance group will be applied to all sub-instances before
|
||||
* their own object-to-world transforms are applied.
|
||||
*/
|
||||
SKYRESULT SkyRenderableInstanceGroup::Display()
|
||||
{
|
||||
// Get and set the world space transformation
|
||||
Mat44f mat;
|
||||
GetModelToWorldTransform(mat);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat.M);
|
||||
|
||||
InstanceIterator ii;
|
||||
/***
|
||||
for (ii = _opaqueSubInstances.begin(); ii != _opaqueSubInstances.end(); ++ii)
|
||||
{
|
||||
FAIL_RETURN((*ii)->Display());
|
||||
}
|
||||
|
||||
for (ii = _transparentSubInstances.begin(); ii != _transparentSubInstances.end(); ++ii)
|
||||
{
|
||||
FAIL_RETURN((*ii)->Display());
|
||||
}
|
||||
|
||||
***/
|
||||
_pObjectSpaceBV->Display();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::ViewFrustumCull
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::ViewFrustumCull(const Camera& cam)
|
||||
* @brief @todo <WRITE BRIEF SkyRenderableInstanceGroup::ViewFrustumCull DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyRenderableInstanceGroup::ViewFrustumCull FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
bool SkyRenderableInstanceGroup::ViewFrustumCull(const Camera& cam)
|
||||
{
|
||||
Mat44f xform;
|
||||
GetModelToWorldTransform(xform);
|
||||
_bCulled = (_pObjectSpaceBV == NULL) ? false : _pObjectSpaceBV->ViewFrustumCull(cam, xform);
|
||||
return _bCulled;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::AddSubInstance
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent)
|
||||
* @brief Adds a sub-instance to the group.
|
||||
*/
|
||||
void SkyRenderableInstanceGroup::AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent)
|
||||
{
|
||||
if (!bTransparent)
|
||||
_opaqueSubInstances.push_back(pInstance);
|
||||
else
|
||||
_transparentSubInstances.push_back(pInstance);
|
||||
|
||||
// update the bounds...
|
||||
Mat44f xform;
|
||||
pInstance->GetModelToWorldTransform(xform);
|
||||
|
||||
SkyMinMaxBox *pBV = pInstance->GetBoundingVolume();
|
||||
if (pBV)
|
||||
{
|
||||
Vec3f min = pInstance->GetBoundingVolume()->GetMin();
|
||||
Vec3f max = pInstance->GetBoundingVolume()->GetMax();
|
||||
|
||||
if (!_pObjectSpaceBV)
|
||||
_pObjectSpaceBV = new SkyMinMaxBox;
|
||||
|
||||
_pObjectSpaceBV->AddPoint(xform * min);
|
||||
_pObjectSpaceBV->AddPoint(xform * max);
|
||||
}
|
||||
63
simgear/scene/sky/clouds3d/SkyRenderableInstanceGroup.hpp
Normal file
63
simgear/scene/sky/clouds3d/SkyRenderableInstanceGroup.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceGroup.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 SkyRenderableInstanceGroup.hpp
|
||||
*
|
||||
* Interface definition for class SkyRenderableInstanceGroup, an instance that groups
|
||||
* other instances.
|
||||
*/
|
||||
#ifndef __SKYRENDERABLEINSTANCEGROUP_HPP__
|
||||
#define __SKYRENDERABLEINSTANCEGROUP_HPP__
|
||||
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
#include "SkyMinMaxBox.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderableInstanceGroup
|
||||
* @brief A renderable instance that groups other instances.
|
||||
*
|
||||
* This class provides a very basic way to implement static hierarchies of objects.
|
||||
* It is not meant to be a full scene graph --
|
||||
*/
|
||||
class SkyRenderableInstanceGroup : public SkyRenderableInstance
|
||||
{
|
||||
public:
|
||||
SkyRenderableInstanceGroup();
|
||||
virtual ~SkyRenderableInstanceGroup();
|
||||
|
||||
//! Update all sub-instances.
|
||||
virtual SKYRESULT Update(const Camera &cam);
|
||||
//! Render all sub-instances.
|
||||
virtual SKYRESULT Display();
|
||||
|
||||
//! Returns true if and only if the bounding volume of this instance lies entirely outside @a cam.
|
||||
virtual bool ViewFrustumCull(const Camera &cam);
|
||||
|
||||
//! Adds an instance to the group that this instance represents.
|
||||
void AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent);
|
||||
|
||||
protected:
|
||||
InstanceArray _opaqueSubInstances;
|
||||
InstanceArray _transparentSubInstances;
|
||||
|
||||
SkyMinMaxBox *_pObjectSpaceBV; // Pointer to bounding volume in object space
|
||||
};
|
||||
|
||||
|
||||
#endif //__SKYRENDERABLEINSTANCEGROUP_HPP__
|
||||
232
simgear/scene/sky/clouds3d/SkySceneLoader.cpp
Normal file
232
simgear/scene/sky/clouds3d/SkySceneLoader.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkySceneLoader.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// Adapted from SkyWorks for FlightGear by J. Wojnaroski -- castle@mminternet.com
|
||||
// Copywrite July 2002
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
/**
|
||||
* @file SkySceneLoader.cpp
|
||||
*
|
||||
* Implementation of class SkySceneLoader.
|
||||
*/
|
||||
|
||||
#include <plib/ssg.h>
|
||||
#include <simgear/math/point3d.hxx>
|
||||
|
||||
#include "SkySceneLoader.hpp"
|
||||
#include "SkySceneManager.hpp"
|
||||
#include "SkyTextureManager.hpp"
|
||||
#include "SkySceneManager.hpp"
|
||||
#include "SkyDynamicTextureManager.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
//#include "SkyViewManager.hpp"
|
||||
//#include "SkyRenderableInstanceGroup.hpp"
|
||||
#include "SkyLight.hpp"
|
||||
#include "camera.hpp"
|
||||
|
||||
ssgLight _sky_ssgLights [ 8 ] ;
|
||||
static Point3D origin;
|
||||
Point3D offset;
|
||||
//int _ssgFrameCounter = 0 ;
|
||||
Camera *pCam = new Camera();
|
||||
// Need to add a light here until we figure out how to use the sun position and color
|
||||
SkyLight::SkyLightType eType = SkyLight::SKY_LIGHT_DIRECTIONAL;
|
||||
SkyLight *pLight = new SkyLight(eType);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneLoader::SkySceneLoader
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneLoader::SkySceneLoader()
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkySceneLoader::SkySceneLoader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneLoader::~SkySceneLoader
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneLoader::~SkySceneLoader()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkySceneLoader::~SkySceneLoader()
|
||||
{
|
||||
SceneManager::Destroy();
|
||||
DynamicTextureManager::Destroy();
|
||||
TextureManager::Destroy();
|
||||
GraphicsContext::Destroy();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneLoader::Load
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneLoader::Load(std::string filename)
|
||||
* @brief Loads a SkyWorks scene.
|
||||
*
|
||||
* This is a temporary fix, as it loads only limited scenes
|
||||
* It can however, load any number of Cloud
|
||||
+
|
||||
*/
|
||||
bool SkySceneLoader::Load(std::string filename)
|
||||
{
|
||||
SkyArchive archive;
|
||||
if (SKYFAILED(archive.Load(filename.c_str()))) {
|
||||
cout << "Archive file not found\n";
|
||||
return false; }
|
||||
char *pFilename;
|
||||
|
||||
// Need to create the managers
|
||||
GraphicsContext::Instantiate();
|
||||
TextureManager::Instantiate();
|
||||
DynamicTextureManager::Instantiate();
|
||||
SceneManager::Instantiate();
|
||||
|
||||
unsigned int iNumFiles;
|
||||
if (!SKYFAILED(archive.GetInfo("CloudFile", STRING_TYPE, &iNumFiles)))
|
||||
{
|
||||
for (unsigned int i = 0; i < iNumFiles; ++i)
|
||||
{
|
||||
FAIL_RETURN(archive.FindString("CloudFile", &pFilename, i));
|
||||
|
||||
float rScale = 1.0;
|
||||
FAIL_RETURN(archive.FindFloat32("CloudScale", &rScale, i));
|
||||
rScale = 5.0;
|
||||
SkyArchive cloudArchive;
|
||||
FAIL_RETURN(cloudArchive.Load(pFilename));
|
||||
FAIL_RETURN(SceneManager::InstancePtr()->LoadClouds(cloudArchive, rScale));
|
||||
}
|
||||
}
|
||||
|
||||
Vec3f dir(0, 0, 1);
|
||||
pLight->SetPosition(Vec3f(0, 0, 7000));
|
||||
pLight->SetDirection(dir);
|
||||
pLight->SetAmbient(Vec4f( 0.0f, 0.0f, 0.0f, 0.0f));
|
||||
pLight->SetDiffuse(Vec4f(1.0f, 1.0f, 1.0f, 0.0f));
|
||||
//pLight->SetDiffuse(Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
//pLight->SetSpecular(Vec4f(1.0f, 1.0f, 1.0f, 0.0f));
|
||||
|
||||
// No attenuation
|
||||
pLight->SetAttenuation(1.0f, 0.0f, 0.0f);
|
||||
SceneManager::InstancePtr()->AddLight(pLight);
|
||||
|
||||
SceneManager::InstancePtr()->ShadeClouds();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkySceneLoader::Set_Cloud_Orig( Point3D *posit )
|
||||
{ // use this to adjust camera position for a new tile center
|
||||
|
||||
origin = *posit; // set origin to current tile center
|
||||
printf("Cloud marker %f %f %f\n", origin.x(), origin.y(), origin.z() );
|
||||
|
||||
}
|
||||
|
||||
void SkySceneLoader::Update( sgMat4 viewmat, Point3D *posit )
|
||||
//void SkySceneLoader::Update()
|
||||
{
|
||||
offset = *posit - origin;
|
||||
cout << "X: " << offset.x() << "Y: " << offset.y() << "Z: " << offset.z() << endl;
|
||||
|
||||
SceneManager::InstancePtr()->Update(*pCam);
|
||||
|
||||
// need some scheme to reshade selected clouds a few at a time to save frame rate cycles
|
||||
///SceneManager::InstancePtr()->ShadeClouds();
|
||||
|
||||
}
|
||||
|
||||
void SkySceneLoader::Resize( double w, double h )
|
||||
{
|
||||
|
||||
pCam->Perspective( (float) h, (float) (w / h), 0.5, 120000.0 );
|
||||
|
||||
}
|
||||
|
||||
void SkySceneLoader::Draw()
|
||||
{ // this is a clone of the plib ssgCullAndDraw except there is no scene graph
|
||||
if ( _ssgCurrentContext == NULL )
|
||||
{
|
||||
cout<< "ssg: No Current Context: Did you forgot to call ssgInit()?" ; char x; cin >> x;
|
||||
}
|
||||
|
||||
//ssgForceBasicState () ;
|
||||
|
||||
sgMat4 test;
|
||||
|
||||
//glMatrixMode ( GL_PROJECTION );
|
||||
//glLoadIdentity();
|
||||
//_ssgCurrentContext->loadProjectionMatrix ();
|
||||
// test/debug section
|
||||
|
||||
//_ssgCurrentContext->getProjectionMatrix( test );
|
||||
/*
|
||||
printf( "\nFG Projection matrix\n" );
|
||||
cout << test[0][0] << " " << test[1][0] << " " << test[2][0] << " " << test[3][0] << endl;
|
||||
cout << test[0][1] << " " << test[1][1] << " " << test[2][1] << " " << test[3][1] << endl;
|
||||
cout << test[0][2] << " " << test[1][2] << " " << test[2][2] << " " << test[3][2] << endl;
|
||||
cout << test[0][3] << " " << test[1][3] << " " << test[2][3] << " " << test[3][3] << endl;
|
||||
*/
|
||||
sgMat4 m, *pm;
|
||||
sgVec3 temp;
|
||||
pm = &m;
|
||||
|
||||
// this is the cameraview matrix used by flightgear to render scene
|
||||
// need to play with this to build a new matrix that accounts for tile crossings
|
||||
// for now it resets the clouds when a boundary is crossed
|
||||
_ssgCurrentContext->getModelviewMatrix( m );
|
||||
|
||||
///pCam->GetProjectionMatrix( (float *) pm );
|
||||
//sgCopyMat4( test, m );
|
||||
/*printf( "\nSkyworks Projection matrix\n" );
|
||||
cout << test[0][0] << " " << test[1][0] << " " << test[2][0] << " " << test[3][0] << endl;
|
||||
cout << test[0][1] << " " << test[1][1] << " " << test[2][1] << " " << test[3][1] << endl;
|
||||
cout << test[0][2] << " " << test[1][2] << " " << test[2][2] << " " << test[3][2] << endl;
|
||||
cout << test[0][3] << " " << test[1][3] << " " << test[2][3] << " " << test[3][3] << endl;
|
||||
*/
|
||||
glMatrixMode ( GL_MODELVIEW ) ;
|
||||
glLoadIdentity () ;
|
||||
glLoadMatrixf( (float *) pm );
|
||||
|
||||
//sgCopyMat4( test, m );
|
||||
|
||||
pCam->SetModelviewMatrix( (float *) pm );
|
||||
|
||||
//printf( "\nFG modelview matrix\n" );
|
||||
//cout << test[0][0] << " " << test[1][0] << " " << test[2][0] << " " << test[3][0] << endl;
|
||||
//cout << test[0][1] << " " << test[1][1] << " " << test[2][1] << " " << test[3][1] << endl;
|
||||
//cout << test[0][2] << " " << test[1][2] << " " << test[2][2] << " " << test[3][2] << endl;
|
||||
//cout << test[0][3] << " " << test[1][3] << " " << test[2][3] << " " << test[3][3] << endl;
|
||||
|
||||
//pCam->Print();
|
||||
|
||||
//_ssgCurrentContext->cull(r) ;
|
||||
//_ssgDrawDList () ;
|
||||
|
||||
SceneManager::InstancePtr()->Display(*pCam);
|
||||
|
||||
//pLight->Display(); // draw the light position to debug with sun position
|
||||
|
||||
glMatrixMode ( GL_MODELVIEW ) ;
|
||||
glLoadIdentity () ;
|
||||
|
||||
58
simgear/scene/sky/clouds3d/SkySceneLoader.hpp
Normal file
58
simgear/scene/sky/clouds3d/SkySceneLoader.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkySceneLoader.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 SkySceneLoader.hpp
|
||||
*
|
||||
* Definition of a simple class for loading scenes into SkyWorks.
|
||||
*/
|
||||
#ifndef __SKYSCENELOADER_HPP__
|
||||
#define __SKYSCENELOADER_HPP__
|
||||
|
||||
#include <string>
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkySceneLoader
|
||||
* @brief A simple scene loader for SkyWorks scenes.
|
||||
*
|
||||
* Loads a scene using the Load() method, which is passed the filename of a
|
||||
* file containing a SkyArchive describing the scene.
|
||||
*/
|
||||
class SkySceneLoader
|
||||
{
|
||||
public:
|
||||
SkySceneLoader();
|
||||
~SkySceneLoader();
|
||||
|
||||
bool Load(std::string filename);
|
||||
|
||||
void Set_Cloud_Orig( Point3D *posit );
|
||||
|
||||
//void Update();
|
||||
void Update( sgMat4 viewmat, Point3D *posit );
|
||||
|
||||
void Resize( double w, double h);
|
||||
|
||||
void Draw();
|
||||
|
||||
};
|
||||
|
||||
#endif //__SKYSCENELOADER_HPP__
|
||||
919
simgear/scene/sky/clouds3d/SkySceneManager.cpp
Normal file
919
simgear/scene/sky/clouds3d/SkySceneManager.cpp
Normal file
@@ -0,0 +1,919 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkySceneManager.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkySceneManager.cpp
|
||||
*
|
||||
* Implementation of the singleton class SkySceneManager, which manages objects,
|
||||
* instances, scene update, visibility, culling, and rendering.
|
||||
*/
|
||||
|
||||
// warning for truncation of template name for browse info
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "SkySceneManager.hpp"
|
||||
#include "SkyMaterial.hpp"
|
||||
#include "SkyLight.hpp"
|
||||
#include "SkyCloud.hpp"
|
||||
#include "SkyRenderable.hpp"
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
#include "SkyRenderableInstanceCloud.hpp"
|
||||
//#include "SkyHeavens.hpp"
|
||||
//#include "SkyHeightField.hpp"
|
||||
|
||||
#include "camutils.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::SkySceneManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::SkySceneManager()
|
||||
* @brief Constructor
|
||||
*/
|
||||
SkySceneManager::SkySceneManager()
|
||||
: /*_pSkyBox(NULL),
|
||||
_pTerrain(NULL),
|
||||
*/
|
||||
_bDrawLights(false),
|
||||
_bDrawTree(false),
|
||||
_bReshadeClouds(true)
|
||||
{
|
||||
_wireframeMaterial.SetColorMaterialMode(GL_DIFFUSE);
|
||||
_wireframeMaterial.EnableColorMaterial(true);
|
||||
_wireframeMaterial.EnableLighting(false);
|
||||
|
||||
// add the default material with ID -1
|
||||
// this should avoid errors caused by models without materials exported from MAX
|
||||
// (because flexporter gives them the ID -1).
|
||||
SkyMaterial *pDefaultMaterial = new SkyMaterial;
|
||||
pDefaultMaterial->SetMaterialID(-1);
|
||||
AddMaterial(pDefaultMaterial);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::~SkySceneManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::~SkySceneManager()
|
||||
* @brief Destructor.
|
||||
*
|
||||
* This destructor deletes all renderables, instances (renderable instances, cloud instances,
|
||||
* and otherwise), materials, and lights that were added to the scene using the Add*() functions.
|
||||
* In other words, the scene manager owns all entities added to the scene. This eases cleanup
|
||||
* and shutdown.
|
||||
*/
|
||||
SkySceneManager::~SkySceneManager()
|
||||
{
|
||||
ObjectIterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi)
|
||||
SAFE_DELETE(*oi);
|
||||
_objects.clear();
|
||||
|
||||
CloudIterator ci;
|
||||
for (ci = _clouds.begin(); ci != _clouds.end(); ++ci)
|
||||
SAFE_DELETE(*ci);
|
||||
_clouds.clear();
|
||||
|
||||
InstanceIterator ii;
|
||||
for (ii = _instances.begin(); ii != _instances.end(); ++ii)
|
||||
SAFE_DELETE(*ii);
|
||||
_instances.clear();
|
||||
|
||||
CloudInstanceIterator cii;
|
||||
for (cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
|
||||
SAFE_DELETE(*cii);
|
||||
_cloudInstances.clear();
|
||||
|
||||
ContainerSetIterator cni;
|
||||
for (cni = _containerClouds.begin(); cni != _containerClouds.end(); ++cni)
|
||||
SAFE_DELETE(cni->second);
|
||||
_containerClouds.clear();
|
||||
|
||||
MaterialIterator mi;
|
||||
for (mi = _materials.begin(); mi != _materials.end(); ++mi)
|
||||
SAFE_DELETE(mi->second);
|
||||
_materials.clear();
|
||||
|
||||
LightIterator li;
|
||||
for (li = _lights.begin(); li!= _lights.end(); ++li)
|
||||
SAFE_DELETE(li->second);
|
||||
_lights.clear();
|
||||
|
||||
//SAFE_DELETE(_pSkyBox);
|
||||
//SAFE_DELETE(_pTerrain);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::AddObject
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::AddObject(SkyRenderable *pObject)
|
||||
* @brief Add a new SkyRenderable object to the manager.
|
||||
*/
|
||||
SKYRESULT SkySceneManager::AddObject(SkyRenderable *pObject)
|
||||
{
|
||||
// Check for null object
|
||||
if (NULL == pObject)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"SkySceneManager::AddObject(): Attempting to add NULL Renderable Object.");
|
||||
}
|
||||
|
||||
_objects.push_back(pObject);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::AddInstance
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::AddInstance(SkyRenderableInstance *pInstance, bool bTransparent)
|
||||
* @brief Add a new SkyRenderableInstance to the manager.
|
||||
*/
|
||||
SKYRESULT SkySceneManager::AddInstance(SkyRenderableInstance *pInstance, bool bTransparent /* = false */)
|
||||
{
|
||||
// Check for null instance
|
||||
if (NULL == pInstance)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"SkySceneManager::AddObject(): Attempting to add NULL Renderable Instance.");
|
||||
}
|
||||
|
||||
if (!bTransparent)
|
||||
_instances.push_back(pInstance);
|
||||
else
|
||||
_transparentInstances.push_back(pInstance);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::AddCloud
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::AddCloud(SkyCloud *pCloud)
|
||||
* @brief Add a new cloud object to the manager.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::AddCloud FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkySceneManager::AddCloud(SkyCloud *pCloud)
|
||||
{
|
||||
if (NULL == pCloud)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"SkySceneManager::AddObject(): Attempting to add NULL SkyCloud Object.");
|
||||
}
|
||||
|
||||
_clouds.push_back(pCloud);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::AddCloudInstance
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::AddCloudInstance(SkyRenderableInstanceCloud *pInstance)
|
||||
* @brief Add a new instance of a cloud to the manager.
|
||||
*
|
||||
* @todo Note that since cloud instances share shading information, if two instances
|
||||
* of a cloud have different orientations, one of the instances will have incorrect
|
||||
* lighting for the scene. For this reason, I recommend that the number of clouds and
|
||||
* cloud instances is equal.
|
||||
*/
|
||||
SKYRESULT SkySceneManager::AddCloudInstance(SkyRenderableInstanceCloud *pInstance)
|
||||
{
|
||||
// Check for null instance
|
||||
if (NULL == pInstance)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"SkySceneManager::AddObject(): Attempting to add NULL SkyCloud Instance.");
|
||||
}
|
||||
|
||||
pInstance->SetID(_cloudInstances.size());
|
||||
|
||||
_cloudInstances.push_back(pInstance);
|
||||
|
||||
SkyContainerCloud *pContainer = new SkyContainerCloud(pInstance);
|
||||
_containerClouds.insert(std::make_pair(pInstance->GetID(), pContainer));
|
||||
|
||||
RebuildCloudBVTree();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::AddMaterial
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::AddMaterial(SkyMaterial *pMaterial)
|
||||
* @brief Adds a material to the scene.
|
||||
*
|
||||
* Materials are kept in a map with their ID as key. A material can be retrieved
|
||||
* from the scene manager by passing its ID to GetMaterial.
|
||||
*
|
||||
* @see GetMaterial, SkyMaterial
|
||||
*/
|
||||
SKYRESULT SkySceneManager::AddMaterial(SkyMaterial *pMaterial)
|
||||
{
|
||||
// Check for null instance
|
||||
if (NULL == pMaterial)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"SkySceneMananger::AddMaterial(): Attempting to add NULL Material to Scene Manager");
|
||||
}
|
||||
|
||||
_materials.insert(std::make_pair(pMaterial->GetMaterialID(), pMaterial));
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::GetMaterial
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::GetMaterial(int iMaterialID)
|
||||
* @brief Returns the material with ID @a iMaterialID.
|
||||
*
|
||||
* If the material is not found, returns NULL.
|
||||
*
|
||||
* @see AddMaterial, SkyMaterial
|
||||
*/
|
||||
SkyMaterial* SkySceneManager::GetMaterial(int iMaterialID)
|
||||
{
|
||||
MaterialIterator mi = _materials.find(iMaterialID);
|
||||
if (_materials.end() == mi)
|
||||
{
|
||||
SkyTrace("SkySceneManager::GetMaterial: Error: invalid material ID");
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return mi->second;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::ActivateMaterial
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::ActivateMaterial(int iMaterialID)
|
||||
* @brief Makes the specified material active, setting the appropriate rendering state.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::ActivateMaterial FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkySceneManager::ActivateMaterial(int iMaterialID)
|
||||
{
|
||||
cout << "Activating material\n"; char mm; cin >> mm;
|
||||
MaterialIterator mi = _materials.find(iMaterialID);
|
||||
if (_materials.end() == mi)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"SkySceneManager::ActivateMaterial: Error: invalid material ID.");
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL_RETURN_MSG(mi->second->Activate(),
|
||||
"SkySceneManager::ActivateMaterial: Error: failed to activate.");
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::AddLight
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::AddLight(SkyLight *pLight)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::AddLight DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::AddLight FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkySceneManager::AddLight(SkyLight *pLight)
|
||||
{
|
||||
// Check for null instance
|
||||
if (NULL == pLight)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"SkySceneMananger::AddLight(): Attempting to add NULL Light to Scene Manager");
|
||||
}
|
||||
|
||||
_lights.insert(std::make_pair(_lights.size(), pLight));
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::GetLight
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::GetLight(int iLightID)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::GetLight DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::GetLight FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SkyLight* SkySceneManager::GetLight(int iLightID)
|
||||
{
|
||||
LightIterator li = _lights.find(iLightID);
|
||||
if (_lights.end() == li)
|
||||
{
|
||||
SkyTrace("SkySceneManager::GetLight: Error: Invalid light ID");
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return li->second;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Alive
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Alive(SkyRenderableInstance* pInstance)
|
||||
* @brief A predicate to determine if an object is dead or not.
|
||||
*/
|
||||
bool Alive(SkyRenderableInstance* pInstance)
|
||||
{
|
||||
return (pInstance->IsAlive());
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::Update
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::Update(const Camera &cam)
|
||||
* @brief Iterate through all SkyRenderableInstances and update them.
|
||||
*/
|
||||
SKYRESULT SkySceneManager::Update(const Camera &cam)
|
||||
{
|
||||
_ResolveVisibility(cam);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::Display(const Camera &cam)
|
||||
* @brief Iterate through all SkyRenderableInstances and display them.
|
||||
*/
|
||||
SKYRESULT SkySceneManager::Display( const Camera &cam )
|
||||
|
||||
{
|
||||
_clearMaterial.Activate();
|
||||
//glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// set lights (only lights that have changed will be passed to GL).
|
||||
for (LightIterator li = _lights.begin(); li != _lights.end(); ++li)
|
||||
{
|
||||
li->second->Activate(li->first);
|
||||
//if (_bDrawLights)
|
||||
//li->second->Display();
|
||||
}
|
||||
|
||||
//if (_bDrawTree)
|
||||
// force the issue and draw
|
||||
_VisualizeCloudBVTree(cam, _cloudBVTree.GetRoot());
|
||||
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
// red is Cartesian y-axis
|
||||
glColor3ub( 255, 0, 0 );
|
||||
glVertex3f( 0.0,0.0,0.0 );
|
||||
glVertex3f( 0.0, -104000.0, 0.0);
|
||||
// yellow is Cartesian z-axis
|
||||
glColor3ub( 255, 255, 0 );
|
||||
glVertex3f( 0.0, 0.0, 0.0);
|
||||
glVertex3f( 0.0, 0.0, 104000.0);
|
||||
// blue is Cartesian x-axis
|
||||
glColor3ub( 0, 0, 255 );
|
||||
glVertex3f( 0.0, 0.0, 0.0);
|
||||
glVertex3f( -104000.0, 0.0, 0.0);
|
||||
glEnd();
|
||||
|
||||
// draw all container clouds and "free" objects not in clouds.
|
||||
int i = 0;
|
||||
for (InstanceIterator iter = _visibleInstances.begin(); iter != _visibleInstances.end(); ++iter)
|
||||
{
|
||||
FAIL_RETURN_MSG((*iter)->Display(),
|
||||
"SkySceneManager::Display(): instance display failed.");
|
||||
i++;
|
||||
}
|
||||
//cout << "There are " << i << " visible clouds\n";
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::RebuildCloudBVTree
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::RebuildCloudBVTree()
|
||||
* @brief Builds an AABB tree of the cloud bounding volumes.
|
||||
*/
|
||||
SKYRESULT SkySceneManager::RebuildCloudBVTree()
|
||||
{
|
||||
CloudInstanceIterator cii;
|
||||
SkyMinMaxBox bbox;
|
||||
|
||||
_cloudBVTree.BeginTree();
|
||||
for (cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
|
||||
{
|
||||
bbox = (*cii)->GetWorldSpaceBounds();
|
||||
_cloudBVTree.AddObject(*cii, bbox);
|
||||
}
|
||||
_cloudBVTree.EndTree();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::ShadeClouds
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::ShadeClouds()
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::ShadeClouds DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::ShadeClouds FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkySceneManager::ShadeClouds()
|
||||
{
|
||||
cout << "SkySceneManager::ShadeClouds()\n";
|
||||
int i=0;
|
||||
|
||||
for (CloudInstanceIterator cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
|
||||
{
|
||||
for (LightIterator li = _lights.begin(); li != _lights.end(); ++li)
|
||||
{
|
||||
|
||||
if (SkyLight::SKY_LIGHT_DIRECTIONAL == li->second->GetType())
|
||||
{
|
||||
(*cii)->GetCloud()->Illuminate(li->second, *cii, li == _lights.begin());
|
||||
printf("Shading Cloud %d of %d with light %d \n", i++, _cloudInstances.size(), *li );
|
||||
}
|
||||
}
|
||||
}
|
||||
_bReshadeClouds = false;
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::LoadClouds
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::LoadClouds(SkyArchive& cloudArchive, float rScale)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::LoadClouds DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::LoadClouds FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkySceneManager::LoadClouds(SkyArchive& cloudArchive, float rScale /* = 1.0f */)
|
||||
{
|
||||
unsigned int iNumClouds = 0;
|
||||
cloudArchive.FindUInt32("CldNumClouds", &iNumClouds);
|
||||
|
||||
SkyArchive subArchive;
|
||||
//iNumClouds = 5; //set this value to reduce cloud field for debugging
|
||||
for (int i = 0; i < iNumClouds; ++i)
|
||||
{
|
||||
printf("Loading # %d of %d clouds\n", i, iNumClouds);
|
||||
cloudArchive.FindArchive("Cloud", &subArchive, i);
|
||||
SkyCloud *pCloud = new SkyCloud();
|
||||
pCloud->Load(subArchive, rScale);
|
||||
SkyRenderableInstanceCloud *pInstance = new SkyRenderableInstanceCloud(pCloud, false);
|
||||
AddCloud(pCloud);
|
||||
AddCloudInstance(pInstance);
|
||||
}
|
||||
RebuildCloudBVTree();
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::_SortClouds
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::_SortClouds(CloudInstanceArray& clouds, const Vec3f& vecSortPoint)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::_SortClouds DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::_SortClouds FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkySceneManager::_SortClouds(CloudInstanceArray& clouds, const Vec3f& vecSortPoint)
|
||||
{
|
||||
static InstanceComparator comparator;
|
||||
|
||||
for (CloudInstanceIterator cii = clouds.begin(); cii != clouds.end(); ++cii)
|
||||
{
|
||||
Vec3f vecPos = (*cii)->GetPosition();
|
||||
vecPos -= vecSortPoint;
|
||||
(*cii)->SetSquareSortDistance(vecPos.LengthSqr());
|
||||
}
|
||||
|
||||
std::sort(clouds.begin(), clouds.end(), comparator);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::_SortInstances
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::_SortInstances DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::_SortInstances FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkySceneManager::SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint)
|
||||
{
|
||||
static InstanceComparator comparator;
|
||||
|
||||
for (InstanceIterator ii = instances.begin(); ii != instances.end(); ++ii)
|
||||
{
|
||||
Vec3f vecPos = (*ii)->GetPosition();
|
||||
vecPos -= vecSortPoint;
|
||||
(*ii)->SetSquareSortDistance(vecPos.LengthSqr());
|
||||
}
|
||||
|
||||
std::sort(instances.begin(), instances.end(), comparator);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::_ViewFrustumCullClouds
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::_ViewFrustumCullClouds(const Camera& cam, const CloudBVTree::Node *pNode)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::_ViewFrustumCullClouds DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::_ViewFrustumCullClouds FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkySceneManager::_ViewFrustumCullClouds(const Camera& cam, const CloudBVTree::Node *pNode)
|
||||
{
|
||||
if (!pNode)
|
||||
return;
|
||||
|
||||
int i;
|
||||
int iResult = CamMinMaxBoxOverlap(&cam, pNode->GetNodeBV().GetMin(), pNode->GetNodeBV().GetMax());
|
||||
|
||||
|
||||
//iResult = COMPLETEIN; // just a hack to force the issue
|
||||
if (COMPLETEIN == iResult)
|
||||
{
|
||||
// trivially add all instances
|
||||
for (i = 0; i < pNode->GetNumObjs(); ++i)
|
||||
{
|
||||
SkyRenderableInstanceCloud* pInstance =
|
||||
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
|
||||
_visibleCloudInstances.push_back(pInstance);
|
||||
}
|
||||
}
|
||||
else if ((PARTIAL == iResult) && pNode->IsLeaf())
|
||||
{
|
||||
SkyMinMaxBox bbox;
|
||||
|
||||
// check each instance in this node against camera
|
||||
for (i = 0; i < pNode->GetNumObjs(); ++i)
|
||||
{
|
||||
SkyRenderableInstanceCloud* pInstance =
|
||||
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
|
||||
bbox = pInstance->GetWorldSpaceBounds();
|
||||
iResult = CamMinMaxBoxOverlap(&cam, bbox.GetMin(), bbox.GetMax());
|
||||
if (COMPLETEOUT != iResult)
|
||||
_visibleCloudInstances.push_back(pInstance);
|
||||
else
|
||||
pInstance->ReleaseImpostorTextures();
|
||||
}
|
||||
}
|
||||
else if (PARTIAL == iResult)
|
||||
{
|
||||
_ViewFrustumCullClouds(cam, pNode->GetLeftChild());
|
||||
_ViewFrustumCullClouds(cam, pNode->GetRightChild());
|
||||
}
|
||||
else // the node is completely out. All of its child clouds should release their textures.
|
||||
{
|
||||
for (i = 0; i < pNode->GetNumObjs(); ++i)
|
||||
{
|
||||
SkyRenderableInstanceCloud* pInstance =
|
||||
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
|
||||
pInstance->ReleaseImpostorTextures();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::_VisualizeCloudBVTree
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::_VisualizeCloudBVTree(const Camera& cam, const CloudBVTree::Node *pNode)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::_VisualizeCloudBVTree DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::_VisualizeCloudBVTree FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkySceneManager::_VisualizeCloudBVTree(const Camera& cam, const CloudBVTree::Node *pNode)
|
||||
{
|
||||
// set display state.
|
||||
_wireframeMaterial.Activate();
|
||||
|
||||
int iResult = CamMinMaxBoxOverlap(&cam, pNode->GetNodeBV().GetMin(), pNode->GetNodeBV().GetMax());
|
||||
|
||||
if (COMPLETEIN == iResult)
|
||||
{
|
||||
// draw this node's bounding box in green.
|
||||
glColor3f(0, 1, 0);
|
||||
pNode->GetNodeBV().Display();
|
||||
}
|
||||
else if (PARTIAL == iResult)
|
||||
{
|
||||
SkyMinMaxBox bbox;
|
||||
|
||||
if (pNode->IsLeaf())
|
||||
{
|
||||
// draw this node's bounding box and the boxes of all of its objects that are visible.
|
||||
// draw this node's bbox in orange.
|
||||
glColor3f(1, 0.5, 0);
|
||||
pNode->GetNodeBV().Display();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < pNode->GetNumObjs(); ++i)
|
||||
{
|
||||
SkyRenderableInstanceCloud* pInstance =
|
||||
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
|
||||
bbox = pInstance->GetWorldSpaceBounds();
|
||||
iResult = CamMinMaxBoxOverlap(&cam, bbox.GetMin(), bbox.GetMax());
|
||||
|
||||
if (COMPLETEIN == iResult)
|
||||
{
|
||||
// draw the box in green
|
||||
glColor3f(0, 1, 0);
|
||||
bbox.Display();
|
||||
}
|
||||
else if (PARTIAL == iResult)
|
||||
{
|
||||
// draw the box in yellow
|
||||
glColor3f(1, 1, 0);
|
||||
bbox.Display();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_VisualizeCloudBVTree(cam, pNode->GetLeftChild());
|
||||
_VisualizeCloudBVTree(cam, pNode->GetRightChild());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw the node's bbox in red.
|
||||
// This should NEVER be visible from the camera from which it was culled!
|
||||
glColor3f(1, 0, 0);
|
||||
pNode->GetNodeBV().Display();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::_ResolveVisibility
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::_ResolveVisibility(const Camera &cam)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::_ResolveRenderingOrder DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::_ResolveRenderingOrder FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkySceneManager::_ResolveVisibility(const Camera &cam)
|
||||
{
|
||||
InstanceIterator ii;
|
||||
|
||||
// clear the free instance array
|
||||
_visibleInstances.clear();
|
||||
|
||||
// clear the contained instance arrays
|
||||
ContainerSetIterator csi;
|
||||
for (csi = _containerClouds.begin(); csi != _containerClouds.end(); ++csi)
|
||||
{
|
||||
csi->second->containedOpaqueInstances.clear();
|
||||
csi->second->containedTransparentInstances.clear();
|
||||
}
|
||||
|
||||
// clear the visible cloud array.
|
||||
_visibleCloudInstances.clear();
|
||||
|
||||
// Test each instance for containment inside a cloud's bounding volume.
|
||||
// If the instance is inside a cloud, it is considered a "contained" instance, and will be
|
||||
// rendered with the cloud in which it is contained for correct visibility. If the instance is
|
||||
// not inside any cloud, then it is a "free" instance, and will be rendered after all contained
|
||||
// instances. Transparent instances of each type are rendered after opaque instances of each
|
||||
// type.
|
||||
|
||||
// opaque instances
|
||||
for (ii = _instances.begin(); ii != _instances.end(); ++ii)
|
||||
{
|
||||
cout << "Opague instance\n"; char zz; cin >> zz;
|
||||
(*ii)->ViewFrustumCull(cam); // First VFC then check if culled, some instances may
|
||||
// manually set the culled flag, instead of using VFC
|
||||
if (!(*ii)->IsCulled())
|
||||
{
|
||||
// first update this instance.
|
||||
FAIL_RETURN_MSG((*ii)->Update(cam), "SkySceneManager::_ResolveVisibility(): instance update failed.");
|
||||
|
||||
if (!_TestInsertInstanceIntoClouds(cam, _cloudBVTree.GetRoot(), *ii, false))
|
||||
_visibleInstances.push_back(*ii);
|
||||
}
|
||||
}
|
||||
|
||||
// transparent instances
|
||||
for (ii = _transparentInstances.begin(); ii != _transparentInstances.end(); ++ii)
|
||||
{
|
||||
cout << "Transparent instance\n"; char tt; cin >> tt;
|
||||
(*ii)->ViewFrustumCull(cam); // First VFC then check if culled, some instances may
|
||||
// manually set the culled flag, instead of using VFC
|
||||
if (!(*ii)->IsCulled())
|
||||
{
|
||||
// first update this instance.
|
||||
FAIL_RETURN_MSG((*ii)->Update(cam), "SkySceneManager::Update(): instance update failed.");
|
||||
|
||||
if (!_TestInsertInstanceIntoClouds(cam, _cloudBVTree.GetRoot(), *ii, true))
|
||||
_visibleInstances.push_back(*ii);
|
||||
}
|
||||
}
|
||||
|
||||
// view frustum cull the clouds
|
||||
_ViewFrustumCullClouds(cam, _cloudBVTree.GetRoot());
|
||||
|
||||
// Clouds must be rendered in sorted order.
|
||||
//_SortClouds(_visibleCloudInstances, cam.Orig);
|
||||
|
||||
// reshade the clouds if necessary.
|
||||
if (_bReshadeClouds)
|
||||
{
|
||||
printf("ReShading clouds\n");
|
||||
FAIL_RETURN(ShadeClouds());
|
||||
}
|
||||
|
||||
// Now process the visible clouds. First, go through the container clouds corresponding to the
|
||||
// clouds, calculate their split points, and update their impostors.
|
||||
for (CloudInstanceIterator cii = _visibleCloudInstances.begin();
|
||||
cii != _visibleCloudInstances.end();
|
||||
++cii)
|
||||
{
|
||||
// get the container corresponding to this cloud
|
||||
ContainerSetIterator csi = _containerClouds.find((*cii)->GetID());
|
||||
|
||||
if (csi == _containerClouds.end())
|
||||
{
|
||||
SkyTrace("Error: SkySceneManager::_ResolveVisibility(): Invalid cloud instance %d.",
|
||||
(*cii)->GetID());
|
||||
return SKYRESULT_FAIL;
|
||||
}
|
||||
|
||||
if (csi->second->containedOpaqueInstances.size() > 0 ||
|
||||
csi->second->containedTransparentInstances.size() > 0)
|
||||
{
|
||||
SortInstances(csi->second->containedOpaqueInstances, cam.Orig);
|
||||
SortInstances(csi->second->containedTransparentInstances, cam.Orig);
|
||||
|
||||
|
||||
SkyRenderableInstance *pOpaque = (csi->second->containedOpaqueInstances.size() > 0) ?
|
||||
csi->second->containedOpaqueInstances.back() : NULL;
|
||||
SkyRenderableInstance *pTransparent = (csi->second->containedTransparentInstances.size() > 0) ?
|
||||
csi->second->containedTransparentInstances.back() : NULL;
|
||||
|
||||
// find the closest contained instance to the camera
|
||||
if (pOpaque && pTransparent)
|
||||
{
|
||||
if (*pOpaque < *pTransparent)
|
||||
(*cii)->SetSplitPoint(pOpaque->GetPosition());
|
||||
else
|
||||
(*cii)->SetSplitPoint(pTransparent->GetPosition());
|
||||
}
|
||||
else if (pOpaque)
|
||||
(*cii)->SetSplitPoint(pOpaque->GetPosition());
|
||||
else if (pTransparent)
|
||||
(*cii)->SetSplitPoint(pTransparent->GetPosition());
|
||||
else
|
||||
(*cii)->SetSplit(false);
|
||||
}
|
||||
else
|
||||
(*cii)->SetSplit(false);
|
||||
|
||||
// add the container to the list of visiblie clouds to be rendered this frame.
|
||||
_visibleInstances.push_back(csi->second);
|
||||
|
||||
// now update the impostors
|
||||
FAIL_RETURN_MSG((*cii)->Update(cam),
|
||||
"SkySceneManager::_ResolveVisibility(): cloud instance update failed.");
|
||||
}
|
||||
|
||||
SortInstances(_visibleInstances, cam.Orig);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySceneManager::_TestInsertInstanceIntoClouds
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySceneManager::_TestInsertInstanceIntoClouds(const Camera &cam, const CloudBVTree::Node *pNode, SkyRenderableInstance *pInstanceToInsert, bool bTransparent)
|
||||
* @brief @todo <WRITE BRIEF SkySceneManager::_TestInsertInstanceIntoClouds DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkySceneManager::_TestInsertInstanceIntoClouds FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
bool SkySceneManager::_TestInsertInstanceIntoClouds(const Camera &cam,
|
||||
const CloudBVTree::Node *pNode,
|
||||
SkyRenderableInstance *pInstanceToInsert,
|
||||
bool bTransparent)
|
||||
{
|
||||
if (_clouds.size() <= 0)
|
||||
return false;
|
||||
|
||||
if (pNode->GetNodeBV().PointInBBox(pInstanceToInsert->GetPosition()))
|
||||
{
|
||||
if (pNode->IsLeaf())
|
||||
{
|
||||
SkyMinMaxBox bbox;
|
||||
int i;
|
||||
|
||||
// check the instance against each cloud in this leaf node.
|
||||
for (i = 0; i < pNode->GetNumObjs(); ++i)
|
||||
{
|
||||
SkyRenderableInstanceCloud* pCloud =
|
||||
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
|
||||
bbox = pCloud->GetWorldSpaceBounds();
|
||||
if (bbox.PointInBBox(pInstanceToInsert->GetPosition()))
|
||||
{
|
||||
// get the container cloud struct for this cloud instance, and add this instance.
|
||||
ContainerSetIterator csi = _containerClouds.find(pCloud->GetID());
|
||||
if (csi == _containerClouds.end())
|
||||
{
|
||||
SkyTrace(
|
||||
"Error: SkySceneManager::_TestInsertInstanceIntoClouds(): Invalid cloud instance %d.",
|
||||
pCloud->GetID());
|
||||
return false;
|
||||
}
|
||||
else // this instance is inside a cloud. Set up for split cloud rendering.
|
||||
{
|
||||
if (!bTransparent)
|
||||
csi->second->containedOpaqueInstances.push_back(pInstanceToInsert);
|
||||
else
|
||||
csi->second->containedTransparentInstances.push_back(pInstanceToInsert);
|
||||
csi->second->pCloud->SetSplit(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_TestInsertInstanceIntoClouds(cam, pNode->GetLeftChild(), pInstanceToInsert, bTransparent))
|
||||
188
simgear/scene/sky/clouds3d/SkySceneManager.hpp
Normal file
188
simgear/scene/sky/clouds3d/SkySceneManager.hpp
Normal file
@@ -0,0 +1,188 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkySceneManager.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 SkySceneManager.hpp
|
||||
*
|
||||
* The SkySceneManager class manages all of the renderable objects and
|
||||
* instances. This class maintains lists of each object and instance.
|
||||
* The scene manager decides what to display, it can make use of various
|
||||
* techniques such as view frustum culling, material grouping, etc.
|
||||
*/
|
||||
#ifndef __SKYSCENEMANAGER_HPP__
|
||||
#define __SKYSCENEMANAGER_HPP__
|
||||
|
||||
// warning for truncation of template name for browse info
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkySingleton.hpp"
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
#include "SkyMaterial.hpp"
|
||||
#include "SkyAABBTree.hpp"
|
||||
#include "SkyRenderableInstanceCloud.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class Camera;
|
||||
class SkyRenderable;
|
||||
class SkyRenderableInstance;
|
||||
class SkyMaterial;
|
||||
class SkyLight;
|
||||
class SkyCloud;
|
||||
//class SkyHeavens;
|
||||
//class SkyHeightField;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkySceneManager
|
||||
* @brief Manages all of the renderable objects and instances.
|
||||
*/
|
||||
class SkySceneManager; // Forward declaration
|
||||
|
||||
//! A singleton of the SkySceneManager. Can only create the SceneManager with SceneManager::Instantiate();
|
||||
typedef SkySingleton<SkySceneManager> SceneManager;
|
||||
|
||||
class SkySceneManager
|
||||
{
|
||||
public:
|
||||
SKYRESULT AddObject( SkyRenderable *pObject);
|
||||
SKYRESULT AddInstance( SkyRenderableInstance *pInstance, bool bTransparent = false);
|
||||
|
||||
SKYRESULT AddCloud( SkyCloud *pCloud);
|
||||
SKYRESULT AddCloudInstance(SkyRenderableInstanceCloud *pInstance);
|
||||
|
||||
SKYRESULT AddMaterial( SkyMaterial *pMaterial);
|
||||
SkyMaterial* GetMaterial( int iMaterialID);
|
||||
SKYRESULT ActivateMaterial(int iMaterialID);
|
||||
|
||||
SKYRESULT AddLight( SkyLight *pLight);
|
||||
SkyLight* GetLight( int iLightID);
|
||||
|
||||
//! Set the sky box for this scene.
|
||||
// void SetSkyBox( SkyHeavens *pSkyBox) { _pSkyBox = pSkyBox; }
|
||||
//! Set the terrain for this scene.
|
||||
//void SetTerrain( SkyHeightField *pTerrain) { _pTerrain = pTerrain; }
|
||||
|
||||
//! Enable wireframe display of lights (for debugging).
|
||||
void EnableDrawLights(bool bEnable) { _bDrawLights = bEnable; }
|
||||
//! Enable wireframe display of bounding volume tree of clouds.
|
||||
void EnableDrawBVTree(bool bEnable) { _bDrawTree = bEnable; }
|
||||
|
||||
//! Returns true if wireframe display of lights is enabled.
|
||||
bool IsDrawLightsEnabled() const { return _bDrawLights; }
|
||||
//! Returns true if wireframe display of the cloud bounding volume tree is enabled.
|
||||
bool IsDrawBVTreeEnabled() const { return _bDrawTree; }
|
||||
|
||||
SKYRESULT Update( const Camera &cam);
|
||||
SKYRESULT Display( const Camera &cam);
|
||||
|
||||
SKYRESULT RebuildCloudBVTree();
|
||||
SKYRESULT ShadeClouds();
|
||||
|
||||
//! Force the illumination of all clouds to be recomputed in the next update.
|
||||
void ForceReshadeClouds() { _bReshadeClouds = true; }
|
||||
|
||||
// sort instances in @a instances from back to front.
|
||||
static void SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint);
|
||||
|
||||
// load a set of clouds from an archive file.
|
||||
SKYRESULT LoadClouds(SkyArchive& cloudArchive, float rScale = 1.0f);
|
||||
|
||||
protected: // datatypes
|
||||
// Typedef the vectors into cleaner names
|
||||
typedef std::vector<SkyRenderable*> ObjectArray;
|
||||
|
||||
typedef std::map<int, SkyMaterial*> MaterialSet;
|
||||
typedef std::map<int, SkyLight*> LightSet;
|
||||
|
||||
typedef std::vector<SkyRenderableInstanceCloud*> CloudInstanceArray;
|
||||
typedef std::vector<SkyCloud*> CloudArray;
|
||||
typedef std::map<int, SkyContainerCloud*> ContainerCloudSet;
|
||||
|
||||
typedef SkyAABBTree<SkyRenderableInstanceCloud*> CloudBVTree;
|
||||
|
||||
typedef ObjectArray::iterator ObjectIterator;
|
||||
typedef CloudArray::iterator CloudIterator;
|
||||
typedef CloudInstanceArray::iterator CloudInstanceIterator;
|
||||
typedef MaterialSet::iterator MaterialIterator;
|
||||
typedef LightSet::iterator LightIterator;
|
||||
typedef ContainerCloudSet::iterator ContainerSetIterator;
|
||||
|
||||
class InstanceComparator
|
||||
{
|
||||
public:
|
||||
bool operator()(SkyRenderableInstance* pA, SkyRenderableInstance *pB)
|
||||
{
|
||||
return ((*pA) < (*pB));
|
||||
}
|
||||
};
|
||||
|
||||
class ContainerComparator
|
||||
{
|
||||
public:
|
||||
bool operator()(SkyContainerCloud* pA, SkyContainerCloud *pB)
|
||||
{
|
||||
return ((*pA) < (*pB));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
protected: // methods
|
||||
SkySceneManager();
|
||||
~SkySceneManager();
|
||||
|
||||
void _SortClouds(CloudInstanceArray& clouds, const Vec3f& vecSortPoint);
|
||||
|
||||
void _ViewFrustumCullClouds(const Camera& cam, const CloudBVTree::Node *pNode);
|
||||
void _VisualizeCloudBVTree(const Camera& cam, const CloudBVTree::Node *pNode);
|
||||
|
||||
SKYRESULT _ResolveVisibility(const Camera &cam);
|
||||
bool _TestInsertInstanceIntoClouds(const Camera &cam,
|
||||
const CloudBVTree::Node *pNode,
|
||||
SkyRenderableInstance *pInstanceToInsert,
|
||||
bool bTransparent);
|
||||
|
||||
private: // data
|
||||
ObjectArray _objects;
|
||||
CloudArray _clouds;
|
||||
InstanceArray _instances;
|
||||
InstanceArray _transparentInstances;
|
||||
InstanceArray _visibleInstances; //! @TODO: change this to "_freeInstances"
|
||||
CloudInstanceArray _cloudInstances;
|
||||
CloudInstanceArray _visibleCloudInstances;
|
||||
ContainerCloudSet _containerClouds;
|
||||
|
||||
MaterialSet _materials;
|
||||
LightSet _lights;
|
||||
|
||||
SkyMaterial _wireframeMaterial; // used for rendering the wireframes for debugging
|
||||
SkyMaterial _clearMaterial; // used to maintain state consistency when clearing.
|
||||
CloudBVTree _cloudBVTree;
|
||||
|
||||
//SkyHeavens *_pSkyBox;
|
||||
//SkyHeightField *_pTerrain;
|
||||
|
||||
bool _bDrawLights;
|
||||
bool _bDrawTree;
|
||||
bool _bReshadeClouds;
|
||||
};
|
||||
|
||||
#endif //__SKYSCENEMANAGER_HPP__
|
||||
292
simgear/scene/sky/clouds3d/SkySingleton.hpp
Normal file
292
simgear/scene/sky/clouds3d/SkySingleton.hpp
Normal file
@@ -0,0 +1,292 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkySingleton.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 SkySingleton.hpp
|
||||
*
|
||||
* A generic singleton template wrapper to make classes into singletons
|
||||
*/
|
||||
#ifndef __SKYSINGLETON_HPP__
|
||||
#define __SKYSINGLETON_HPP__
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkySingleton
|
||||
* @brief A singleton template class.
|
||||
*
|
||||
* Usage : Use this template container class to make any class into a
|
||||
* singleton. I usually do this:
|
||||
*
|
||||
* @code
|
||||
* class MyClass
|
||||
* {
|
||||
* public:
|
||||
* // normal class stuff, but don't put ctor/dtor here.
|
||||
* int GetData() { return _someData; }
|
||||
* protected:
|
||||
* // Make the ctor(s)/dtor protected, so this can only be
|
||||
* // instantiated as a singleton. Note: singleton will still
|
||||
* // work on classes that do not follow this (public ctors)
|
||||
* // but violation of the singleton is possible then, since non-
|
||||
* // singleton versions of the class can be instantiated.
|
||||
* MyClass() : _someData(5) {}
|
||||
* MyClass(int arg) : _someData(arg) {} // etc...
|
||||
* // don't implement the copy constructor, because singletons
|
||||
* // shouldn't be copied!
|
||||
* MyClass(const MyClass& mc) {}
|
||||
* ~MyClass() {}
|
||||
* private:
|
||||
* int _someData;
|
||||
* };
|
||||
*
|
||||
* // now create a singleton of MyClass
|
||||
* typedef SkySingleton<MyClass> MyClassSingleton;
|
||||
*
|
||||
* @endcode
|
||||
* Later, in your program code, you can instantiate the singleton and access
|
||||
* its members like so:
|
||||
*
|
||||
* @code
|
||||
* void somefunc()
|
||||
* {
|
||||
* // instantiate the MyClassSingleton
|
||||
* MyClassSingleton::Instantiate();
|
||||
* // could also call MyClassSingleton::Instantiate(10);
|
||||
* // since we have a constructor of that form in MyClass.
|
||||
*
|
||||
* // access the methods in MyClass:
|
||||
* int data1 = MyClassSingleton::InstancePtr()->GetData();
|
||||
* // or...
|
||||
* int data2 = MyClassSingleton::InstanceRef().GetData();
|
||||
*
|
||||
* // now destroy the singleton
|
||||
* MyClassSingleton::Destroy();
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
template <class T>
|
||||
class SkySingleton : protected T
|
||||
{
|
||||
public:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Instantiate()
|
||||
* @brief Creates the singleton instance for class T.
|
||||
*
|
||||
* Assures (by assertion) that the instance will only be created once.
|
||||
* This works for default constructors.
|
||||
*/
|
||||
static void Instantiate()
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Destroy
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Destroy() { SAFE_DELETE(s_pInstance); }
|
||||
* @brief Destructor, deletes the instance
|
||||
*/
|
||||
static void Destroy() { SAFE_DELETE(s_pInstance); }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : InstancePtr
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn InstancePtr() { assert(s_pInstance); return s_pInstance; }
|
||||
* @brief Returns a pointer to the instance
|
||||
*/
|
||||
static T* InstancePtr() { assert(s_pInstance); return s_pInstance; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : InstanceRef
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn InstanceRef() { assert(s_pInstance); return *s_pInstance; }
|
||||
* @brief Returns a reference to the instance
|
||||
*/
|
||||
static T& InstanceRef() { assert(s_pInstance); return *s_pInstance; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : static void Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn static void Instantiate(const A& a)
|
||||
* @brief Instantiates class of type T that have constructors with an argument
|
||||
*
|
||||
* This might be a source of confusion. These templatized
|
||||
* functions are used to instantiate classes of type T that
|
||||
* have constructors with arguments. For n arguments, you
|
||||
* to add a function below with n arguments. Note, these will
|
||||
* only be created if they are used, since they are templates.
|
||||
* I've added 4 below, for 1-4 arguments. If you get a
|
||||
* compilation error, add one for the number of arguments you
|
||||
* need. Also need a SkySingleton protected constructor with
|
||||
* the same number of arguments.
|
||||
*/
|
||||
template<class A>
|
||||
static void Instantiate(const A& a)
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton(a);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Instantiate(const A& a, const B& b)
|
||||
* @brief Instantiates class of type T that have constructors with 2 args
|
||||
*/
|
||||
template<class A, class B>
|
||||
static void Instantiate(const A& a, const B& b)
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton(a, b);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Instantiate(const A& a, const B& b, const C& c)
|
||||
* @brief Instantiates class of type T that have constructors with 3 args
|
||||
*/
|
||||
template<class A, class B, class C>
|
||||
static void Instantiate(const A& a, const B& b, const C& c)
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton(a, b, c);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Instantiate(const A& a, const B& b, const C& c, const D& d)
|
||||
* @brief Instantiates class of type T that have constructors with 4 args
|
||||
*/
|
||||
template<class A, class B, class C, class D>
|
||||
static void Instantiate(const A& a, const B& b, const C& c, const D& d)
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton(a, b, c, d);
|
||||
}
|
||||
|
||||
protected:
|
||||
// although the instance is of type SkySingleton<T>, the Instance***() funcs
|
||||
// above implicitly cast it to type T.
|
||||
static SkySingleton* s_pInstance;
|
||||
|
||||
private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySingleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySingleton()
|
||||
* @brief Hidden so that the singleton can only be instantiated via public static Instantiate function.
|
||||
*/
|
||||
SkySingleton() : T() {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Singleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Singleton(const A& a)
|
||||
* @brief Used by the templatized public Instantiate() functions.
|
||||
*/
|
||||
template<class A>
|
||||
SkySingleton(const A& a) : T(a) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Singleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Singleton(const A& a, const B& b)
|
||||
* @brief Used by the templatized public Instantiate() functions.
|
||||
*/
|
||||
template<class A, class B>
|
||||
SkySingleton(const A& a, const B& b) : T(a, b) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Singleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Singleton(const A& a, const B& b, const C& c)
|
||||
* @brief Used by the templatized public Instantiate() functions.
|
||||
*/
|
||||
template<class A, class B, class C>
|
||||
SkySingleton(const A& a, const B& b, const C& c) : T(a, b, c) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Singleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Singleton(const A& a, const B& b, const C &c, const D& d)
|
||||
* @brief Used by the templatized public Instantiate() functions.
|
||||
*/
|
||||
template<class A, class B, class C, class D>
|
||||
SkySingleton(const A& a, const B& b, const C &c, const D& d) : T(a, b, c, d) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySingleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySingleton(const SkySingleton&)
|
||||
* @brief Hidden because you can't copy a singleton!
|
||||
*/
|
||||
SkySingleton(const SkySingleton&) {} // hide the copy ctor: singletons can'
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : ~SkySingleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn ~SkySingleton()
|
||||
* @brief Destructor, hidden, destroy via the public static Destroy() method.
|
||||
*/
|
||||
~SkySingleton() {} // hide the dtor:
|
||||
};
|
||||
|
||||
// declare the static instance pointer
|
||||
template<class T> SkySingleton<T>* SkySingleton<T>::s_pInstance = NULL;
|
||||
|
||||
#endif //__SKYSINGLETON_HPP__
|
||||
96
simgear/scene/sky/clouds3d/SkyTexture.hpp
Normal file
96
simgear/scene/sky/clouds3d/SkyTexture.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyTexture.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 SkyTexture.hpp
|
||||
*
|
||||
* Interface definition for class SkyTexture, a texture class.
|
||||
*/
|
||||
#ifndef __SKYTEXTURE_HPP__
|
||||
#define __SKYTEXTURE_HPP__
|
||||
|
||||
#pragma warning( disable : 4786 )
|
||||
|
||||
#include <GL/glut.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyTexture
|
||||
* @brief A basic texture class.
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyTexture
|
||||
{
|
||||
public:
|
||||
//! Default Constructor.
|
||||
SkyTexture() : _iID(0), _iWidth(0), _iHeight(0) {}
|
||||
//! Constructor.
|
||||
SkyTexture(unsigned int iWidth, unsigned int iHeight, unsigned int iTextureID)
|
||||
: _iID(iTextureID), _iWidth(iWidth), _iHeight(iHeight) {}
|
||||
//! Destructor.
|
||||
~SkyTexture() {}
|
||||
|
||||
//! Sets the texture width in texels.
|
||||
void SetWidth(unsigned int iWidth) { _iWidth = iWidth; }
|
||||
//! Sets the texture height in texels.
|
||||
void SetHeight(unsigned int iHeight) { _iHeight = iHeight; }
|
||||
//! Sets the texture ID as created by OpenGL.
|
||||
void SetID(unsigned int iTextureID) { _iID = iTextureID; }
|
||||
|
||||
//! Returns the texture width in texels.
|
||||
unsigned int GetWidth() const { return _iWidth; }
|
||||
//! Returns the texture height in texels.
|
||||
unsigned int GetHeight() const { return _iHeight; }
|
||||
//! Returns the texture ID as created by OpenGL.
|
||||
unsigned int GetID() const { return _iID; }
|
||||
|
||||
inline SKYRESULT Destroy();
|
||||
|
||||
protected:
|
||||
unsigned int _iID;
|
||||
unsigned int _iWidth;
|
||||
unsigned int _iHeight;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTexture::Destroy
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTexture::Destroy()
|
||||
* @brief Destroys the OpenGL texture object represented by this SkyTexture object.
|
||||
*
|
||||
* Fails if the GL texture has not been created (i.e. its ID is zero).
|
||||
*/
|
||||
inline SKYRESULT SkyTexture::Destroy()
|
||||
{
|
||||
if (0 == _iID)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL,
|
||||
"SkyTexture::Destroy(): Error: attempt to destroy unallocated texture.");
|
||||
}
|
||||
else
|
||||
{
|
||||
glDeleteTextures(1, &_iID);
|
||||
_iID = 0;
|
||||
}
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
#endif //__SKYTEXTURE_HPP__
|
||||
883
simgear/scene/sky/clouds3d/SkyTextureManager.cpp
Normal file
883
simgear/scene/sky/clouds3d/SkyTextureManager.cpp
Normal file
@@ -0,0 +1,883 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyTextureManager.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyTextureManager.cpp
|
||||
*
|
||||
* Implementation of a manager that keeps track of texture resource locations and sharing.
|
||||
*/
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "SkyTextureManager.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
//#include "glvu.hpp"
|
||||
//#include "ppm.hpp"
|
||||
//#include "tga.hpp"
|
||||
//#include "fileutils.hpp"
|
||||
|
||||
bool SkyTextureManager::s_bSlice3DTextures = false;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::SkyTextureManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::SkyTextureManager(bool bSlice3DTextures)
|
||||
* @brief Constructor.
|
||||
*
|
||||
*/
|
||||
SkyTextureManager::SkyTextureManager(bool bSlice3DTextures /* = false */)
|
||||
{
|
||||
s_bSlice3DTextures = bSlice3DTextures;
|
||||
|
||||
// this should be put somewhere more safe -- like done once in the functions that actually
|
||||
// use these extensions.
|
||||
/*GraphicsContext::InstancePtr()->InitializeExtensions("GL_ARB_texture_cube_map "
|
||||
"GL_VERSION_1_2");*/
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::~SkyTextureManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::~SkyTextureManager()
|
||||
* @brief destructor.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyTextureManager::~SkyTextureManager FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SkyTextureManager::~SkyTextureManager()
|
||||
{
|
||||
_texturePaths.clear();
|
||||
for ( TextureIterator iter = _textures.begin();
|
||||
iter != _textures.end();
|
||||
++iter)
|
||||
{
|
||||
DestroyTextureObject(iter->second);
|
||||
}
|
||||
_textures.clear();
|
||||
|
||||
for ( TextureList::iterator uncachedIter = _uncachedTextures.begin();
|
||||
uncachedIter != _uncachedTextures.end();
|
||||
++uncachedIter)
|
||||
{
|
||||
DestroyTextureObject(*uncachedIter);
|
||||
}
|
||||
_uncachedTextures.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::AddPath
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::AddPath(const string &path)
|
||||
* @brief Adds a texture path to the list of active search paths.
|
||||
*
|
||||
*/
|
||||
void SkyTextureManager::AddPath(const string &path)
|
||||
{
|
||||
_texturePaths.push_back(path);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Get2DTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Get2DTexture(const string& filename, SkyTexture& texture, bool bMipmap)
|
||||
* @brief Returns a 2D texture object from the texture set.
|
||||
*
|
||||
* If the texture is already loaded, it is returned. If it is not, the texture is loaded from
|
||||
* file, added to the texture set, and returned.
|
||||
*
|
||||
* If the image cannot be loaded, returns an error. Otherwise returns success.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::Get2DTexture(const string& filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap /* = false */)
|
||||
{
|
||||
TextureIterator iter = _textures.find(filename);
|
||||
|
||||
if (iter != _textures.end())
|
||||
{ // the texture is already loaded, just return it.
|
||||
texture = iter->second;
|
||||
}
|
||||
else
|
||||
{ // the texture is being requested for the first time, load and return it
|
||||
FAIL_RETURN(Clone2DTexture(filename, texture, bMipmap));
|
||||
|
||||
_textures.insert(make_pair(filename, texture));
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Get3DTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Get3DTexture(const string& filename, SkyTexture& texture, unsigned int iDepth, bool bMipmap, bool bLoadFromSliceFiles)
|
||||
* @brief Returns a 3D texture object from the texture set.
|
||||
*
|
||||
* If the texture is already loaded, it is returned. If it is not, the texture is loaded from
|
||||
* file, added to the texture set, and returned. If the image cannot be loaded, returns an error.
|
||||
* Otherwise returns success.
|
||||
*
|
||||
* For 3D textures, this simply loads a 2D image file, and duplicates it across each slice. The
|
||||
* parameter iDepth must be set in order to use a 2D texture image for a 3D texture.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::Get3DTexture(const string& filename,
|
||||
SkyTexture& texture,
|
||||
unsigned int iDepth,
|
||||
bool bMipmap /* = false */,
|
||||
bool bLoadFromSliceFiles /* = false */)
|
||||
{
|
||||
TextureIterator iter = _textures.find(filename);
|
||||
|
||||
if (iter != _textures.end())
|
||||
{ // the texture is already loaded, just return it.
|
||||
texture = iter->second;
|
||||
}
|
||||
else
|
||||
{ // the texture is being requested for the first time, load and return it
|
||||
FAIL_RETURN(Clone3DTexture(filename, texture, iDepth, bMipmap, bLoadFromSliceFiles));
|
||||
|
||||
_textures.insert(make_pair(filename, texture));
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : roundPowerOf2
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
static int roundPowerOf2(int n)
|
||||
{
|
||||
int m;
|
||||
for (m = 1; m < n; m *= 2);
|
||||
|
||||
// m >= n
|
||||
if (m - n <= n - m/2)
|
||||
return m;
|
||||
else
|
||||
return m/2;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Clone2DTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Clone2DTexture( const string &filename, SkyTexture& texture, bool bMipmap)
|
||||
* @brief Returns a 2D texture object.
|
||||
*
|
||||
* Ignores texture set. This always loads the file, if it exists, and creates and returns the texture.
|
||||
*
|
||||
* If the image cannot be loaded, returns an error. Otherwise returns success.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::Clone2DTexture(const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap /* = false */)
|
||||
{
|
||||
string pathFilename;
|
||||
unsigned char *pImageData = NULL;
|
||||
int iWidth = 0;
|
||||
int iHeight = 0;
|
||||
int iChannels = 0;
|
||||
|
||||
enum ImageType
|
||||
{
|
||||
IMAGE_PPM,
|
||||
IMAGE_TGA
|
||||
};
|
||||
ImageType eType;
|
||||
|
||||
/****
|
||||
// first get the image type from its extension.
|
||||
if (filename.find(".tga") != string.npos || filename.find(".TGA") != string.npos)
|
||||
eType = IMAGE_TGA;
|
||||
else if (filename.find(".ppm") != string.npos || filename.find(".PPM") != string.npos)
|
||||
eType = IMAGE_PPM;
|
||||
else
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureManager error: invalid image format");
|
||||
|
||||
****/
|
||||
// first try the filename sent in in case it includes a path.
|
||||
//if (FileUtils::FileExists(filename.c_str()))
|
||||
//{
|
||||
// printf("Filename is %s\n", filename.c_str() );
|
||||
//eType = IMAGE_TGA;
|
||||
/* switch (eType)
|
||||
{
|
||||
case IMAGE_PPM:
|
||||
LoadPPM(filename.c_str(), pImageData, iWidth, iHeight);
|
||||
iChannels = 3;
|
||||
break;
|
||||
case IMAGE_TGA:
|
||||
LoadTGA(filename.c_str(), pImageData, iWidth, iHeight, iChannels);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
//}
|
||||
|
||||
if (!pImageData) // image not found in current directory. Check the paths...
|
||||
{
|
||||
|
||||
for ( StringList::iterator iter = _texturePaths.begin();
|
||||
iter != _texturePaths.end();
|
||||
++iter)
|
||||
|
||||
{ // loop over all texture paths, looking for the filename
|
||||
// get just the filename without path.
|
||||
int iPos = filename.find_last_of("/");
|
||||
if (iPos == filename.npos)
|
||||
iPos = filename.find_last_of("/");
|
||||
|
||||
// tack on the paths from the texture path list.
|
||||
if (iPos != filename.npos)
|
||||
pathFilename = (*iter) + "/" + filename.substr(iPos+1);
|
||||
else
|
||||
pathFilename = (*iter) + "/" + filename;
|
||||
|
||||
//if (FileUtils::FileExists(pathFilename.c_str()))
|
||||
//{
|
||||
/* switch (eType)
|
||||
{
|
||||
case IMAGE_PPM:
|
||||
LoadPPM(pathFilename.c_str(), pImageData, iWidth, iHeight);
|
||||
break;
|
||||
case IMAGE_TGA:
|
||||
LoadTGA(pathFilename.c_str(), pImageData, iWidth, iHeight, iChannels);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
//if (pImageData)
|
||||
//break;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pImageData)
|
||||
{
|
||||
char buffer[256];
|
||||
sprintf(buffer, "SkyTextureManager::Clone2DTexture(): Could not load image. %s.\n", filename);
|
||||
FAIL_RETURN_MSG(SKYRESULT_OK, buffer);
|
||||
}
|
||||
|
||||
// make sure it is power of 2 resolution.
|
||||
int iNewWidth = roundPowerOf2(iWidth);
|
||||
int iNewHeight = roundPowerOf2(iHeight);
|
||||
int iMaxsize;
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
|
||||
if (iNewWidth > iMaxsize)
|
||||
{
|
||||
iNewWidth = iMaxsize;
|
||||
}
|
||||
if (iNewHeight> iMaxsize)
|
||||
{
|
||||
iNewHeight = iMaxsize;
|
||||
}
|
||||
|
||||
GLenum eFormat = (4 == iChannels) ? GL_RGBA : GL_RGB;
|
||||
|
||||
if (iNewWidth != iWidth || iNewHeight != iHeight)
|
||||
{
|
||||
unsigned char *pScaledImageData = new unsigned char[iChannels * iNewWidth * iNewHeight];
|
||||
gluScaleImage(eFormat, iWidth, iHeight, GL_UNSIGNED_BYTE, pImageData,
|
||||
iNewWidth, iNewHeight, GL_UNSIGNED_BYTE, pScaledImageData);
|
||||
SAFE_DELETE_ARRAY(pImageData);
|
||||
pImageData = pScaledImageData;
|
||||
}
|
||||
|
||||
_Create2DTextureObject( texture, iNewWidth, iNewHeight, eFormat, pImageData);
|
||||
|
||||
SAFE_DELETE_ARRAY(pImageData);
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Clone3DTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Clone3DTexture( const string &filename, SkyTexture& texture, unsigned int iDepth, bool bMipmap, bool bLoadFromSliceFiles)
|
||||
* @brief Returns a 3D texture object.
|
||||
*
|
||||
* Ignores texture set. This always loads the file, if it exists, and creates and returns the texture.
|
||||
* If the image cannot be loaded, returns an error. Otherwise returns success.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::Clone3DTexture(const string &filename,
|
||||
SkyTexture& texture,
|
||||
unsigned int iDepth,
|
||||
bool bMipmap /* = false */,
|
||||
bool bLoadFromSliceFiles /* = false */)
|
||||
{
|
||||
string pathFilename;
|
||||
/*QImage image;
|
||||
QDir dir;
|
||||
unsigned char *pBits = NULL;
|
||||
|
||||
if (!bLoadFromSliceFiles)
|
||||
{
|
||||
// first try the filename sent in in case it includes a path.
|
||||
if (image.load(filename))
|
||||
{
|
||||
image = QGLWidget::convertToGLFormat(image);
|
||||
}
|
||||
else
|
||||
{
|
||||
image.reset();
|
||||
|
||||
for ( QStringList::Iterator iter = _texturePaths.begin();
|
||||
iter != _texturePaths.end();
|
||||
iter++)
|
||||
{ // loop over all texture paths, looking for the filename
|
||||
pathFilename = (*iter) + "\\" + filename;
|
||||
|
||||
if (image.load(pathFilename))
|
||||
{
|
||||
image = QGLWidget::convertToGLFormat(image);
|
||||
break;
|
||||
}
|
||||
else
|
||||
image.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (image.isNull())
|
||||
{
|
||||
qWarning("SkyTextureManager::GetTexture(): Could not load image "
|
||||
"%s.\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure it is power of 2 resolutions.
|
||||
int iWidth = roundPowerOf2(image.width());
|
||||
int iHeight = roundPowerOf2(image.height());
|
||||
int iMaxsize;
|
||||
if (s_bSlice3DTextures)
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
|
||||
else
|
||||
glGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &iMaxsize );
|
||||
if (iWidth > iMaxsize)
|
||||
{
|
||||
iWidth = iMaxsize;
|
||||
}
|
||||
if (iHeight> iMaxsize)
|
||||
{
|
||||
iHeight = iMaxsize;
|
||||
}
|
||||
|
||||
if (iWidth != image.width() || iHeight != image.height())
|
||||
image = image.smoothScale(iWidth, iHeight);
|
||||
|
||||
// first build an array of repeated 2D textures...
|
||||
QImage inverted(image.mirror());
|
||||
pBits = new unsigned char[image.numBytes() * iDepth];
|
||||
unsigned int iSliceSize = image.numBytes();
|
||||
int bInverted = false;
|
||||
int iInvertedCount = 8;
|
||||
for (unsigned int iSlice = 0; iSlice < iDepth; ++iSlice)
|
||||
{
|
||||
memcpy(&(pBits[iSlice * iSliceSize]),
|
||||
(bInverted) ? inverted.bits() : image.bits(),
|
||||
image.numBytes());
|
||||
if (--iInvertedCount <= 0)
|
||||
{
|
||||
iInvertedCount = 8;
|
||||
bInverted = !bInverted;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /// Load from a set of files matching the file pattern
|
||||
{
|
||||
QFileInfo fi(filename);
|
||||
fi.refresh();
|
||||
|
||||
QString baseFilename = fi.baseName();
|
||||
int truncPos = baseFilename.find(QRegExp("[0-9]"));
|
||||
if (truncPos >= 0)
|
||||
baseFilename.truncate(truncPos);
|
||||
|
||||
dir.setFilter(QDir::Files);
|
||||
dir.setNameFilter(baseFilename + "*." + fi.extension());
|
||||
dir.setSorting(QDir::Name);
|
||||
QStringList files = dir.entryList();
|
||||
|
||||
bool bFound = true;
|
||||
if (files.count() < iDepth)
|
||||
{
|
||||
bFound = false;
|
||||
for ( QStringList::Iterator iter = _texturePaths.begin();
|
||||
iter != _texturePaths.end();
|
||||
iter++)
|
||||
{
|
||||
dir.setCurrent(*iter);
|
||||
files = dir.entryList();
|
||||
if (files.count() >= iDepth)
|
||||
{
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bFound)
|
||||
{
|
||||
qWarning("SkyTextureManager::Clone3DTexture: ERROR: could not find %d files matching "
|
||||
"%s", iDepth, filename.latin1());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int iSlice = 0;
|
||||
unsigned int iSliceSize = 0;
|
||||
for ( QStringList::Iterator iter = files.begin();
|
||||
iter != files.end() && iSlice < iDepth;
|
||||
iter++)
|
||||
{
|
||||
if (image.load(*iter))
|
||||
{
|
||||
image = QGLWidget::convertToGLFormat(image);
|
||||
// make sure it is power of 2 resolution.
|
||||
int iWidth = roundPowerOf2(image.width());
|
||||
int iHeight = roundPowerOf2(image.height());
|
||||
int iMaxsize;
|
||||
if (s_bSlice3DTextures)
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
|
||||
else
|
||||
glGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &iMaxsize );
|
||||
if (iWidth > iMaxsize)
|
||||
{
|
||||
iWidth = iMaxsize;
|
||||
}
|
||||
if (iHeight> iMaxsize)
|
||||
{
|
||||
iHeight = iMaxsize;
|
||||
}
|
||||
|
||||
if (iWidth != image.width() || iHeight != image.height())
|
||||
image = image.smoothScale(iWidth, iHeight);
|
||||
if (0 == iSlice)
|
||||
{
|
||||
pBits = new unsigned char[image.numBytes() * iDepth];
|
||||
iSliceSize = image.numBytes();
|
||||
}
|
||||
memcpy(&(pBits[iSlice * iSliceSize]), image.bits(), image.numBytes());
|
||||
++iSlice;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("SkyTextureManager::Clone3DTexture: ERROR: could not find %d files matching "
|
||||
"%s", iDepth, filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_Create3DTextureObject(texture,
|
||||
image.width(),
|
||||
image.height(),
|
||||
iDepth,
|
||||
GL_RGBA,
|
||||
pBits);
|
||||
*/
|
||||
return SKYRESULT_FAIL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//!
|
||||
/*! */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::GetCubeMapTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::GetCubeMapTexture(const string& filename, SkyTexture& texture, bool bMipmap)
|
||||
* @brief Returns a cube map texture object from the texture set
|
||||
*
|
||||
* If the texture is already loaded, it is returned. If it is not, the texture is loaded from file,
|
||||
* added to the texture set, and returned. If any of the 6 images cannot be loaded, returns an error.
|
||||
* Otherwise returns success.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::GetCubeMapTexture( const string& filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap)
|
||||
{
|
||||
TextureIterator iter = _textures.find(filename);
|
||||
|
||||
if (iter != _textures.end())
|
||||
{ // the texture is already loaded, just return it.
|
||||
texture = iter->second;
|
||||
}
|
||||
else
|
||||
{ // the texture is being requested for the first time, load and return it
|
||||
if (!CloneCubeMapTexture(filename, texture, bMipmap))
|
||||
return false;
|
||||
|
||||
_textures.insert(make_pair(filename, texture));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::CloneCubeMapTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::CloneCubeMapTexture(const string& filename, SkyTexture& texture, bool bMipmap)
|
||||
* @brief Returns a cube map texture object.
|
||||
*
|
||||
* Ignores the texture set. This always loads the cube map texture, if all 6 face images exist,
|
||||
* creates the texture, and returns it. If any of the 6 images cannot be loaded, returns an error.
|
||||
* Otherwise returns success.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::CloneCubeMapTexture( const string& filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap)
|
||||
{
|
||||
string pathFilename;
|
||||
/*QImage images[6];
|
||||
|
||||
GLenum faces [] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB };
|
||||
char* faceNames[] = {"posx", "negx", "posy", "negy", "posz", "negz" };
|
||||
|
||||
for ( QStringList::Iterator iter = _texturePaths.begin();
|
||||
iter != _texturePaths.end();
|
||||
iter++)
|
||||
{ // loop over all texture paths, looking for the filename
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
char buffer[FILENAME_MAX];
|
||||
sprintf(buffer, filename.ascii(), faceNames[i]);
|
||||
pathFilename = (*iter) + "\\" + buffer;
|
||||
|
||||
if (images[i].load(pathFilename))
|
||||
{
|
||||
images[i] = QGLWidget::convertToGLFormat(images[i]);
|
||||
}
|
||||
else
|
||||
images[i].reset();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (images[i].isNull())
|
||||
{
|
||||
char buffer[FILENAME_MAX];
|
||||
sprintf(buffer, filename.ascii(), faceNames[i]);
|
||||
qWarning("SkyTextureManager::GetTexture(): Could not load image "
|
||||
"%s.\n", buffer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
glGenTextures(1, &(texture.iTextureID));
|
||||
texture.iWidth = images[0].width();
|
||||
texture.iHeight = images[0].height();
|
||||
|
||||
// create and bind a cubemap texture object
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texture.iTextureID);
|
||||
|
||||
// enable automipmap generation if needed.
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_GENERATE_MIPMAP_SGIS, bMipmap);
|
||||
if (bMipmap)
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
glTexImage2D(faces[i],
|
||||
0,
|
||||
GL_RGBA8,
|
||||
images[i].width(),
|
||||
images[i].height(),
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
images[i].bits());
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::_Create2DTextureObject
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::_Create2DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iFormat, unsigned char *pData)
|
||||
* @brief Creates a 2D texture.
|
||||
*
|
||||
* Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::_Create2DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData)
|
||||
{
|
||||
bool bNew = false;
|
||||
unsigned int iTextureID;
|
||||
if (!texture.GetID())
|
||||
{
|
||||
glGenTextures(1, &iTextureID);
|
||||
texture.SetID(iTextureID);
|
||||
bNew = true;
|
||||
}
|
||||
texture.SetWidth(iWidth);
|
||||
texture.SetHeight(iHeight);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.GetID());
|
||||
|
||||
if (bNew)
|
||||
{
|
||||
unsigned int iInternalFormat;
|
||||
switch (iFormat)
|
||||
{
|
||||
case GL_LUMINANCE:
|
||||
iInternalFormat = GL_LUMINANCE;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
iInternalFormat = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
default:
|
||||
iInternalFormat = GL_RGBA8;
|
||||
break;
|
||||
}
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D,
|
||||
0,
|
||||
iInternalFormat,
|
||||
iWidth, iHeight,
|
||||
0,
|
||||
iFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
pData);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, 0, 0,
|
||||
iWidth, iHeight,
|
||||
iFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
pData);
|
||||
}
|
||||
// set default filtering.
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::_Create3DTextureObject
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::_Create3DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iDepth, unsigned int iFormat, unsigned char *pData)
|
||||
* @brief Creates a 3D texture
|
||||
*
|
||||
* Creates an OpenGL 3D texture object (or a set of 2D slices) and returns its ID and dimensions
|
||||
* in a SkyTexture structure.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::_Create3DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iDepth,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData)
|
||||
{
|
||||
/* bool bNew = false;
|
||||
if (s_bSlice3DTextures) // create one 2D texture per slice!
|
||||
{
|
||||
if (!texture.pSliceIDs)
|
||||
{
|
||||
texture.pSliceIDs = new unsigned int[iDepth];
|
||||
glGenTextures(iDepth, texture.pSliceIDs);
|
||||
bNew = true;
|
||||
}
|
||||
}
|
||||
else if (!texture.iTextureID)
|
||||
{
|
||||
glGenTextures(1, &(texture.iTextureID));
|
||||
bNew = true;
|
||||
}
|
||||
|
||||
texture.iWidth = iWidth;
|
||||
texture.iHeight = iHeight;
|
||||
texture.iDepth = iDepth;
|
||||
texture.bSliced3D = s_bSlice3DTextures;
|
||||
|
||||
if (!s_bSlice3DTextures)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_3D, texture.iTextureID);
|
||||
|
||||
if (bNew)
|
||||
{
|
||||
unsigned int iInternalFormat;
|
||||
switch (iFormat)
|
||||
{
|
||||
case GL_LUMINANCE:
|
||||
iInternalFormat = GL_LUMINANCE;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
iInternalFormat = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
default:
|
||||
iInternalFormat = GL_RGBA;
|
||||
break;
|
||||
}
|
||||
|
||||
glTexImage3D( GL_TEXTURE_3D,
|
||||
0,
|
||||
iInternalFormat,
|
||||
iWidth, iHeight, iDepth,
|
||||
0,
|
||||
iFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
pData);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexSubImage3D(GL_TEXTURE_3D,
|
||||
0, 0, 0, 0,
|
||||
iWidth, iHeight, iDepth,
|
||||
iFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
pData);
|
||||
}
|
||||
// set default filtering.
|
||||
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int iInternalFormat = 0;
|
||||
unsigned int iBytesPerPixel = 0;
|
||||
switch (iFormat)
|
||||
{
|
||||
case GL_LUMINANCE:
|
||||
iInternalFormat = GL_LUMINANCE;
|
||||
iBytesPerPixel = 1;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
iInternalFormat = GL_LUMINANCE_ALPHA;
|
||||
iBytesPerPixel = 2;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
default:
|
||||
iInternalFormat = GL_RGBA;
|
||||
iBytesPerPixel = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int iSliceSize = iWidth * iHeight * iBytesPerPixel;
|
||||
|
||||
// create iDepth 2D texture slices...
|
||||
for (unsigned int iSlice = 0; iSlice < iDepth; ++iSlice)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture.pSliceIDs[iSlice]);
|
||||
|
||||
if (bNew)
|
||||
{
|
||||
glTexImage2D( GL_TEXTURE_2D,
|
||||
0,
|
||||
iInternalFormat,
|
||||
iWidth, iHeight,
|
||||
0,
|
||||
iFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
(pData + iSlice * iSliceSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, 0, 0,
|
||||
iWidth, iHeight,
|
||||
iFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
(pData + iSlice * iSliceSize));
|
||||
}
|
||||
// set default filtering.
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
}
|
||||
GLVU::CheckForGLError("SkyTextureManager::_Create3DTextureObject()");
|
||||
|
||||
return SKYRESULT_OK;*/
|
||||
return SKYRESULT_FAIL;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::DestroyTextureObject
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::DestroyTextureObject(SkyTexture &texture)
|
||||
* @brief destroys a SkyTexture object.
|
||||
*
|
||||
* Deletes the data as well as the OpenGL texture ID(s).
|
||||
*/
|
||||
void SkyTextureManager::DestroyTextureObject(SkyTexture &texture)
|
||||
{
|
||||
/*if (texture.GetID)
|
||||
glDeleteTextures(1, &(texture.iTextureID));
|
||||
if (texture.bSliced3D && texture.pSliceIDs)
|
||||
{
|
||||
208
simgear/scene/sky/clouds3d/SkyTextureManager.hpp
Normal file
208
simgear/scene/sky/clouds3d/SkyTextureManager.hpp
Normal file
@@ -0,0 +1,208 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyTextureManager.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 SkyTextureManager.hpp
|
||||
*
|
||||
* Definition of a manager that keeps track of texture locations and sharing of texture files. |
|
||||
*/
|
||||
#ifndef SKYTEXTUREMANAGER_HPP
|
||||
#define SKYTEXTUREMANAGER_HPP
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "SkySingleton.hpp"
|
||||
#include "SkyTexture.hpp"
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// forward declaration for singleton
|
||||
class SkyTextureManager;
|
||||
|
||||
//! A singleton of the SkyTextureManager. Can only create the TextureManager with TextureManager::Instantiate();
|
||||
typedef SkySingleton<SkyTextureManager> TextureManager;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyTextureManager
|
||||
* @brief A resource manager for textures.
|
||||
*
|
||||
* This manager allows textures to be shared. It keeps a mapping of
|
||||
* filenames to texture objects, and makes it easy to use the same texture
|
||||
* for multiple objects without the objects having to be aware of the
|
||||
* sharing. Supports cube map textures, and 2D textures. Can also be used
|
||||
* to "clone textures", which creates unmanaged texture objects from files
|
||||
* that are not kept in the mapping, and thus are not shared.
|
||||
*/
|
||||
class SkyTextureManager
|
||||
{
|
||||
public: // types
|
||||
typedef list<string> StringList;
|
||||
|
||||
public: // methods
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Paths to texture directories
|
||||
//.-------------------------------------------------------------------------.
|
||||
void AddPath(const string& path);
|
||||
//! Return the list of texture paths that will be searched by Get2DTexture() and Get3DTexture().
|
||||
const StringList& GetPaths() const { return _texturePaths; }
|
||||
//! Clear the list of texture paths that will be searched by Get2DTexture() and Get3DTexture().
|
||||
void ClearPaths() { _texturePaths.clear(); }
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Texture loading
|
||||
//.-------------------------------------------------------------------------.
|
||||
SKYRESULT Get2DTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap = false);
|
||||
SKYRESULT Get3DTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
unsigned int iDepth,
|
||||
bool bMipmap = false,
|
||||
bool bLoadFromSliceFiles = false);
|
||||
SKYRESULT GetCubeMapTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap = false);
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Texture cloning: create a duplicate texture object: not added to set!
|
||||
//.-------------------------------------------------------------------------.
|
||||
SKYRESULT Clone2DTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap = false);
|
||||
SKYRESULT Clone3DTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
unsigned int iDepth,
|
||||
bool bMipmap = false,
|
||||
bool bLoadFromSliceFiles = false );
|
||||
SKYRESULT CloneCubeMapTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap = false);
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Texture Object Creation: not added to the texture set (no filename!)
|
||||
//.-------------------------------------------------------------------------.
|
||||
inline SKYRESULT Create2DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData);
|
||||
inline SKYRESULT Create3DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iDepth,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData);
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Texture Object Destruction: use this because texture objects are structs
|
||||
//| that use shallow copies!
|
||||
//.-------------------------------------------------------------------------.
|
||||
static void DestroyTextureObject( SkyTexture &texture);
|
||||
|
||||
|
||||
protected:
|
||||
SkyTextureManager(bool bSlice3DTextures = false);
|
||||
~SkyTextureManager();
|
||||
|
||||
SKYRESULT _Create2DTextureObject( SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData);
|
||||
SKYRESULT _Create3DTextureObject( SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iDepth,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData);
|
||||
private:
|
||||
typedef list<SkyTexture> TextureList;
|
||||
typedef map<string, SkyTexture> TextureSet;
|
||||
typedef TextureSet::iterator TextureIterator;
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Data
|
||||
//.-------------------------------------------------------------------------.
|
||||
|
||||
// paths searched for textures specified by filename.
|
||||
StringList _texturePaths;
|
||||
|
||||
// cached textures
|
||||
TextureSet _textures; // loaded textures
|
||||
// textures created directly, not loaded from file and cached.
|
||||
TextureList _uncachedTextures;
|
||||
|
||||
// if this is true, then 3D textures will be represented as a set of 2D slices.
|
||||
static bool s_bSlice3DTextures;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Create2DTextureObject
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Create2DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iFormat, unsigned char *pData)
|
||||
* @brief Creates a 2D texture.
|
||||
*
|
||||
* Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
|
||||
* This texture will be deleted by the texture manager at shutdown.
|
||||
*
|
||||
*/
|
||||
inline SKYRESULT SkyTextureManager::Create2DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData)
|
||||
{
|
||||
SKYRESULT retval = _Create2DTextureObject(texture, iWidth, iHeight, iFormat, pData);
|
||||
if SKYSUCCEEDED(retval)
|
||||
_uncachedTextures.push_back(texture);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Create3DTextureObject
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Create3DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iDepth, unsigned int iFormat, unsigned char *pData)
|
||||
* @brief Creates a 3D texture.
|
||||
*
|
||||
* Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
|
||||
* This texture will be deleted by the texture manager at shutdown, and should not be destroyed
|
||||
* by the user.
|
||||
*
|
||||
*/
|
||||
inline SKYRESULT SkyTextureManager::Create3DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iDepth,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData)
|
||||
{
|
||||
SKYRESULT retval = _Create3DTextureObject(texture, iWidth, iHeight, iDepth, iFormat, pData);
|
||||
if SKYSUCCEEDED(retval)
|
||||
_uncachedTextures.push_back(texture);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif //QGLVUTEXTUREMANAGER_HPP
|
||||
271
simgear/scene/sky/clouds3d/SkyTextureState.cpp
Normal file
271
simgear/scene/sky/clouds3d/SkyTextureState.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyTextureState.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyTextureState.cpp
|
||||
*
|
||||
* Implementation of class SkyTextureState, which encapsulates OpenGL texture state.
|
||||
*/
|
||||
#include "SkyTextureState.hpp"
|
||||
//#include "glvu.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Static initializations.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int SkyTextureState::s_iNumTextureUnits = 0;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::SkyTextureState
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::SkyTextureState()
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyTextureState::SkyTextureState()
|
||||
{
|
||||
if (0 == s_iNumTextureUnits)
|
||||
{
|
||||
int iNumTextureUnits = 0;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &iNumTextureUnits);
|
||||
if (iNumTextureUnits > 0)
|
||||
s_iNumTextureUnits = iNumTextureUnits;
|
||||
else
|
||||
s_iNumTextureUnits = 1;
|
||||
}
|
||||
|
||||
_pTextureUnitState = new TexState[s_iNumTextureUnits];
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::~SkyTextureState
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::~SkyTextureState()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkyTextureState::~SkyTextureState()
|
||||
{
|
||||
SAFE_DELETE(_pTextureUnitState);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::Activate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::Activate()
|
||||
* @brief @todo <WRITE BRIEF SkyTextureState::Activate DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyTextureState::Activate FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyTextureState::Activate()
|
||||
{
|
||||
SkyTextureState *pCurrent = GraphicsContext::InstancePtr()->GetCurrentTextureState();
|
||||
assert(NULL != pCurrent);
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate(8)");
|
||||
for (unsigned int i = 0; i < s_iNumTextureUnits; ++i)
|
||||
{
|
||||
if (s_iNumTextureUnits > 1)
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB + i);
|
||||
bool bEnabled = IsTextureEnabled(i);
|
||||
if (pCurrent->IsTextureEnabled(i) != bEnabled)
|
||||
{
|
||||
FAIL_RETURN(pCurrent->EnableTexture(i, bEnabled));
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate(7)");
|
||||
if (bEnabled)
|
||||
glEnable(GetActiveTarget(i));
|
||||
else
|
||||
glDisable(GetActiveTarget(i));
|
||||
}
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate(6)");
|
||||
if (bEnabled)
|
||||
{
|
||||
GLenum eTarget = GetActiveTarget(i);
|
||||
unsigned int iID = GetTextureID(i);
|
||||
if ((pCurrent->GetActiveTarget(i) != eTarget) ||
|
||||
(pCurrent->GetTextureID(i) != iID))
|
||||
{
|
||||
FAIL_RETURN(pCurrent->SetTexture(i, eTarget, iID));
|
||||
glBindTexture(eTarget, iID);
|
||||
}
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate(5)");
|
||||
GLenum paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_S);
|
||||
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_WRAP_S) != paramValue)
|
||||
{
|
||||
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_S, paramValue));
|
||||
glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, paramValue);
|
||||
}
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate(4)");
|
||||
paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_T);
|
||||
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_WRAP_T) != paramValue)
|
||||
{
|
||||
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_T, paramValue));
|
||||
glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, paramValue);
|
||||
}
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate(3)");
|
||||
paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_R);
|
||||
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_WRAP_R) != paramValue)
|
||||
{
|
||||
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_R, paramValue));
|
||||
//glTexParameteri(eTarget, GL_TEXTURE_WRAP_R, paramValue);
|
||||
}
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate(2)");
|
||||
paramValue = GetTextureParameter(i, GL_TEXTURE_MIN_FILTER);
|
||||
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_MIN_FILTER) != paramValue)
|
||||
{
|
||||
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_MIN_FILTER, paramValue));
|
||||
glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, paramValue);
|
||||
}
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate(1)");
|
||||
paramValue = GetTextureParameter(i, GL_TEXTURE_MAG_FILTER);
|
||||
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_MAG_FILTER) != paramValue)
|
||||
{
|
||||
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_MAG_FILTER, paramValue));
|
||||
glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, paramValue);
|
||||
}
|
||||
//GLVU::CheckForGLError("SkyTextureState::Activate()");
|
||||
}
|
||||
if (s_iNumTextureUnits > 1)
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
}
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::SetTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::SetTexture(unsigned int iTextureUnit, GLenum eTarget, SkyTexture& texture)
|
||||
* @brief @todo <WRITE BRIEF SkyTextureState::BindTexture DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyTextureState::BindTexture FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyTextureState::SetTexture(unsigned int iTextureUnit,
|
||||
GLenum eTarget,
|
||||
SkyTexture& texture)
|
||||
{
|
||||
if (iTextureUnit >= s_iNumTextureUnits)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureState::BindTexture(): Invalid texture unit.");
|
||||
}
|
||||
|
||||
_pTextureUnitState[iTextureUnit].eActiveTarget = eTarget;
|
||||
_pTextureUnitState[iTextureUnit].iBoundTexture = texture.GetID();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::SetTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::SetTexture(unsigned int iTextureUnit, GLenum eTarget, unsigned int iTextureID)
|
||||
* @brief @todo <WRITE BRIEF SkyTextureState::SetTexture DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyTextureState::SetTexture FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyTextureState::SetTexture(unsigned int iTextureUnit,
|
||||
GLenum eTarget,
|
||||
unsigned int iTextureID)
|
||||
{
|
||||
if (iTextureUnit >= s_iNumTextureUnits)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureState::BindTexture(): Invalid texture unit.");
|
||||
}
|
||||
|
||||
_pTextureUnitState[iTextureUnit].eActiveTarget = eTarget;
|
||||
_pTextureUnitState[iTextureUnit].iBoundTexture = iTextureID;
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::EnableTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::EnableTexture(unsigned int iTextureUnit, bool bEnable)
|
||||
* @brief @todo <WRITE BRIEF SkyTextureState::EnableTexture DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyTextureState::EnableTexture FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyTextureState::EnableTexture(unsigned int iTextureUnit, bool bEnable)
|
||||
{
|
||||
if (iTextureUnit >= s_iNumTextureUnits)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureState::EnableTexture(): Invalid texture unit.");
|
||||
}
|
||||
|
||||
_pTextureUnitState[iTextureUnit].bEnabled = bEnable;
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::SetTextureParameter
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::SetTextureParameter(unsigned int iTextureUnit, GLenum eParameter, GLenum eMode)
|
||||
* @brief @todo <WRITE BRIEF SkyTextureState::SetTextureParameter DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyTextureState::SetTextureParameter FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SKYRESULT SkyTextureState::SetTextureParameter(unsigned int iTextureUnit,
|
||||
GLenum eParameter,
|
||||
GLenum eMode)
|
||||
{
|
||||
if (iTextureUnit >= s_iNumTextureUnits)
|
||||
{
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureState::SetTextureParameter(): Invalid texture unit.");
|
||||
}
|
||||
|
||||
switch (eParameter)
|
||||
{
|
||||
case GL_TEXTURE_WRAP_S:
|
||||
_pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_S] = eMode;
|
||||
break;
|
||||
case GL_TEXTURE_WRAP_T:
|
||||
_pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_T] = eMode;
|
||||
break;
|
||||
case GL_TEXTURE_WRAP_R:
|
||||
_pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_R] = eMode;
|
||||
break;
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
_pTextureUnitState[iTextureUnit].eFilterMode[TexState::SKY_FILTER_MIN] = eMode;
|
||||
break;
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
_pTextureUnitState[iTextureUnit].eFilterMode[TexState::SKY_FILTER_MAG] = eMode;
|
||||
break;
|
||||
default:
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTExtureState::SetTextureParameter(): Invalid parameter.");
|
||||
break;
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
205
simgear/scene/sky/clouds3d/SkyTextureState.hpp
Normal file
205
simgear/scene/sky/clouds3d/SkyTextureState.hpp
Normal file
@@ -0,0 +1,205 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyTextureState.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 SkyTextureState.hpp
|
||||
*
|
||||
* Interface Definition for class SkyTextureState, which encapsulates OpenGL texture state.
|
||||
*/
|
||||
#ifndef __SKYTEXTURESTATE_HPP__
|
||||
#define __SKYTEXTURESTATE_HPP__
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkyTexture.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
#include <map>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyTextureState
|
||||
* @brief A wrapper for texture unit state.
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyTextureState
|
||||
{
|
||||
public: // methods
|
||||
SkyTextureState();
|
||||
~SkyTextureState();
|
||||
|
||||
SKYRESULT Activate();
|
||||
|
||||
SKYRESULT SetTexture(unsigned int iTextureUnit, GLenum eTarget, SkyTexture& texture);
|
||||
SKYRESULT SetTexture(unsigned int iTextureUnit, GLenum eTarget, unsigned int iTextureID);
|
||||
SKYRESULT EnableTexture(unsigned int iTextureUnit, bool bEnable);
|
||||
SKYRESULT SetTextureParameter(unsigned int iTextureUnit,
|
||||
GLenum eParameter,
|
||||
GLenum eMode);
|
||||
|
||||
inline GLenum GetActiveTarget(unsigned int iTextureUnit) const;
|
||||
inline unsigned int GetTextureID(unsigned int iTextureUnit) const;
|
||||
inline bool IsTextureEnabled(unsigned int iTextureUnit) const;
|
||||
inline GLenum GetTextureParameter(unsigned int iTextureUnit, GLenum eParameter) const;
|
||||
|
||||
protected: // datatypes
|
||||
struct TexState
|
||||
{
|
||||
TexState() : eActiveTarget(GL_TEXTURE_2D), iBoundTexture(0), bEnabled(false)
|
||||
{
|
||||
// set state to GL defaults.
|
||||
int i;
|
||||
for (i = 0; i < SKY_TEXCOORD_COUNT; ++i) { eWrapMode[i] = GL_REPEAT; }
|
||||
eFilterMode[SKY_FILTER_MIN] = GL_NEAREST_MIPMAP_LINEAR;
|
||||
eFilterMode[SKY_FILTER_MAG] = GL_LINEAR;
|
||||
}
|
||||
|
||||
enum TexCoord
|
||||
{
|
||||
SKY_TEXCOORD_S,
|
||||
SKY_TEXCOORD_T,
|
||||
SKY_TEXCOORD_R,
|
||||
SKY_TEXCOORD_COUNT
|
||||
};
|
||||
|
||||
enum TexFilter
|
||||
{
|
||||
SKY_FILTER_MIN,
|
||||
SKY_FILTER_MAG,
|
||||
SKY_FILTER_COUNT
|
||||
};
|
||||
|
||||
GLenum eActiveTarget;
|
||||
unsigned int iBoundTexture;
|
||||
bool bEnabled;
|
||||
GLenum eWrapMode[SKY_TEXCOORD_COUNT];
|
||||
GLenum eFilterMode[SKY_FILTER_COUNT];
|
||||
};
|
||||
|
||||
protected: // data
|
||||
|
||||
TexState *_pTextureUnitState; // one per texture unit
|
||||
|
||||
static unsigned int s_iNumTextureUnits;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::GetActiveTarget
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::GetActiveTarget(unsigned int iTextureUnit) const
|
||||
* @brief Returns the active texture target for the specified texture unit.
|
||||
*
|
||||
* If an invalid texture unit is specifed, returns GL_NONE.
|
||||
*/
|
||||
inline GLenum SkyTextureState::GetActiveTarget(unsigned int iTextureUnit) const
|
||||
{
|
||||
if (iTextureUnit >= s_iNumTextureUnits)
|
||||
{
|
||||
SkyTrace("SkyTextureState::GetActiveTexture(): Invalid texture unit.");
|
||||
return GL_NONE;
|
||||
}
|
||||
return _pTextureUnitState[iTextureUnit].eActiveTarget;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : int SkyTextureState::GetTextureID
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn int SkyTextureState::GetTextureID(unsigned int iTextureUnit) const
|
||||
* @brief Returns the texture ID associated with the specified texture unit.
|
||||
*
|
||||
* If an invalid texture unit is specifed, returns GL_NONE.
|
||||
*/
|
||||
inline unsigned int SkyTextureState::GetTextureID(unsigned int iTextureUnit) const
|
||||
{
|
||||
if (iTextureUnit >= s_iNumTextureUnits)
|
||||
{
|
||||
SkyTrace("SkyTextureState::GetTextureID(): Invalid texture unit.");
|
||||
return GL_NONE;
|
||||
}
|
||||
return _pTextureUnitState[iTextureUnit].iBoundTexture;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::IsTextureEnabled
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::IsTextureEnabled(unsigned int iTextureUnit) const
|
||||
* @brief Returns the status (enabled or disabled) of the specified texture unit.
|
||||
*
|
||||
* If an invalid texture unit is specifed, returns false.
|
||||
*/
|
||||
inline bool SkyTextureState::IsTextureEnabled(unsigned int iTextureUnit) const
|
||||
{
|
||||
if (iTextureUnit >= s_iNumTextureUnits)
|
||||
{
|
||||
SkyTrace("SkyTextureState::IsTextureEnabled(): Invalid texture unit.");
|
||||
return false;
|
||||
}
|
||||
return _pTextureUnitState[iTextureUnit].bEnabled;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureState::GetTextureParameter
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureState::GetTextureParameter(unsigned int iTextureUnit, GLenum eParamter) const
|
||||
* @brief Returns the current value of @eParameter on the specified texture unit.
|
||||
*
|
||||
* If an invalid texture unit or parameter is specified, returns GL_NONE.
|
||||
*/
|
||||
inline GLenum SkyTextureState::GetTextureParameter(unsigned int iTextureUnit, GLenum eParameter) const
|
||||
{
|
||||
if (iTextureUnit >= s_iNumTextureUnits)
|
||||
{
|
||||
SkyTrace("SkyTextureState::GetTextureParamter(): Invalid texture unit.");
|
||||
return GL_NONE;
|
||||
}
|
||||
|
||||
switch (eParameter)
|
||||
{
|
||||
case GL_TEXTURE_WRAP_S:
|
||||
return _pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_S];
|
||||
break;
|
||||
case GL_TEXTURE_WRAP_T:
|
||||
return _pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_T];
|
||||
break;
|
||||
case GL_TEXTURE_WRAP_R:
|
||||
return _pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_R];
|
||||
break;
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
return _pTextureUnitState[iTextureUnit].eFilterMode[TexState::SKY_FILTER_MIN];
|
||||
break;
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
return _pTextureUnitState[iTextureUnit].eFilterMode[TexState::SKY_FILTER_MAG];
|
||||
break;
|
||||
default:
|
||||
SkyTrace("SkyTExtureState::SetTextureParameter(): Invalid parameter.");
|
||||
break;
|
||||
}
|
||||
return GL_NONE;
|
||||
}
|
||||
|
||||
#endif //__SKYTEXTURESTATE_HPP__
|
||||
50
simgear/scene/sky/clouds3d/SkyUtil.cpp
Normal file
50
simgear/scene/sky/clouds3d/SkyUtil.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyUtil.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 SkyUtil.cpp
|
||||
*
|
||||
* Implemtation of global utility functions.
|
||||
*/
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTrace
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* SkyTrace( char* strMsg, ... )
|
||||
* @brief Prints formatted output, debug only.
|
||||
*
|
||||
* Includes file and line number information automatically.
|
||||
*/
|
||||
void SkyTrace( char* strMsg, ... )
|
||||
{
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
|
||||
char strBuffer[512];
|
||||
|
||||
va_list args;
|
||||
va_start(args, strMsg);
|
||||
_vsnprintf( strBuffer, 512, strMsg, args );
|
||||
va_end(args);
|
||||
|
||||
fprintf(stderr, "[SkyTrace] %s(%d): %s\n",__FILE__, __LINE__, strBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
192
simgear/scene/sky/clouds3d/SkyUtil.hpp
Normal file
192
simgear/scene/sky/clouds3d/SkyUtil.hpp
Normal file
@@ -0,0 +1,192 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyUtil.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 SkyUtil.hpp
|
||||
* @brief Safe deallocation functions, result codes, trace functions, and macros.
|
||||
*/
|
||||
#ifndef __SKYUTIL_HPP__
|
||||
#define __SKYUTIL_HPP__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Useful constants
|
||||
//-----------------------------------------------------------------------------
|
||||
//! Pi.
|
||||
const float SKY_PI = 4.0f * (float) atan(1.0f);
|
||||
//! 1.0 / Pi
|
||||
const float SKY_INV_PI = 1.0f / SKY_PI;
|
||||
//! 1.0 / (4.0 * Pi)
|
||||
const float SKY_INV_4PI = 1.0f / (4.0f * SKY_PI);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Safe deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
//! Delete and set pointer to NULL.
|
||||
#define SAFE_DELETE(p) { delete (p); (p)=NULL; }
|
||||
//! Delete an array and set pointer to NULL.
|
||||
#define SAFE_DELETE_ARRAY(p) { delete[] (p); (p)=NULL; }
|
||||
//#define SAFE_RELEASE(p) { (p) = NULL; }
|
||||
//{ if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Useful Macros
|
||||
//------------------------------------------------------------------------------
|
||||
//! Convert Degrees to Radians
|
||||
#define SKYDEGREESTORADS 0.01745329252f
|
||||
//! Convert Radians to Degrees
|
||||
#define SKYRADSTODEGREES 57.2957795131f
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyGetLogBaseTwo
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyGetLogBaseTwo(int iNum)
|
||||
* @brief Returns the integer base two logarithm of the integer input.
|
||||
*/
|
||||
inline int SkyGetLogBaseTwo(int iNum)
|
||||
{
|
||||
int i, n;
|
||||
for(i = iNum-1, n = 0; i > 0; i >>= 1, n++ );
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTrace
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
void SkyTrace( char* strMsg, ... );
|
||||
|
||||
|
||||
//.----------------------------------------------------------------------------.
|
||||
//| Result Codes |
|
||||
//.----------------------------------------------------------------------------.
|
||||
//! SKYRESULTs are used for returning error information that can be used to trace bugs.
|
||||
typedef int SKYRESULT;
|
||||
|
||||
//! Returns true if the SKYRESULT is a success result.
|
||||
#define SKYSUCCEEDED(Status) ((SKYRESULT)(Status) >= 0)
|
||||
//! Returns true if the SKYRESULT is a failure result.
|
||||
#define SKYFAILED(Status) ((SKYRESULT)(Status) < 0)
|
||||
|
||||
//! SKYRESULTs are used for returning error information that can be used to trace bugs.
|
||||
enum SKYRESULT_CODES
|
||||
{
|
||||
// SUCCESS CODES: non-negative
|
||||
SKYRESULT_OK = 1,
|
||||
// FAILURE CODES: negative
|
||||
SKYRESULT_FAIL = -1
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FAIL_RETURN
|
||||
//-----------------------------------------------------------------------------
|
||||
// Print debug messages to the WIN32 debug window
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : FAIL_RETURN
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn FAIL_RETURN(p)
|
||||
* @brief Prints a trace message if @a p failed, and returns the failure code.
|
||||
*
|
||||
* Outputs in a format that can be double-clicked in DevStudio to open the
|
||||
* appropriate file and location.
|
||||
*/
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
#define FAIL_RETURN(p) \
|
||||
{ \
|
||||
SKYRESULT __SKYUTIL__result__; \
|
||||
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
|
||||
fprintf(stderr, "!!!! FAIL_RETURN TRAP !!!! %s: %d: %d\n",__FILE__, __LINE__, __SKYUTIL__result__); \
|
||||
return __SKYUTIL__result__; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define FAIL_RETURN(p) p
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : FAIL_RETURN_MSG
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn FAIL_RETURN_MSG(p,str)
|
||||
* @brief Similar to FAIL_RETURN, but also appends a user-supplied message.
|
||||
*
|
||||
* @see FAIL_RETURN, FAIL_RETURN_MSG
|
||||
*/
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
#define FAIL_RETURN_MSG(p,str) \
|
||||
{ \
|
||||
SKYRESULT __SKYUTIL__result__; \
|
||||
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
|
||||
fprintf(stderr, "!!!! FAIL_RETURN_MSG TRAP !!!! %s: %d: %d: %s\n",__FILE__,__LINE__,__SKYUTIL__result__,str); \
|
||||
return __SKYUTIL__result__; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define FAIL_RETURN_MSG(p,str) p
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : FAIL_RETURN_MSGBOX
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn FAIL_RETURN_MSGBOX(p,str)
|
||||
* @brief Similar to FAIL_RETURN_MSG, but also displays the error in a message box (in Windows).
|
||||
*
|
||||
* @see FAIL_RETURN_MSG, FAIL_RETURN
|
||||
*/
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
#ifdef USEWINDOWSOUTPUT
|
||||
#define FAIL_RETURN_MSGBOX(p,str) \
|
||||
{ \
|
||||
SKYRESULT __SKYUTIL__result__; \
|
||||
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
|
||||
char msg[512]; \
|
||||
sprintf(msg, "%s: %d: %d: %s\n",__FILE__,__LINE__,__SKYUTIL__result__,str); \
|
||||
MessageBox(NULL, msg, "!!!! FAIL_RETURN_MSG TRAP !!!!", MB_OK); \
|
||||
return __SKYUTIL__result__; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define FAIL_RETURN_MSGBOX(p,str) \
|
||||
{ \
|
||||
SKYRESULT __SKYUTIL__result__; \
|
||||
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
|
||||
fprintf(stderr, "!!!! FAIL_RETURN_MSG TRAP !!!! %s: %d: %d: %s\n",__FILE__,__LINE__,__D3DUTIL__hres__,str); \
|
||||
return __SKYUTIL__result__; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#define FAIL_RETURN_MSGBOX(p,str) p
|
||||
#endif
|
||||
|
||||
#endif //__SKYUTIL_HPP__
|
||||
84
simgear/scene/sky/clouds3d/camdisplay.cpp
Normal file
84
simgear/scene/sky/clouds3d/camdisplay.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : camdisplay.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// camdisplay.cpp
|
||||
//============================================================================
|
||||
|
||||
#include <GL/glut.h>
|
||||
#include "camera.hpp"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OPENGL CAMERA FRUSTUM DRAWING ROUTINES
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::Display() const
|
||||
{
|
||||
// CALC EIGHT CORNERS OF FRUSTUM (NEAR PTS AND FAR PTS)
|
||||
Vec3f V[8];
|
||||
CalcVerts(V);
|
||||
|
||||
|
||||
// DRAW THE FRUSTUM IN WIREFRAME
|
||||
glBegin(GL_LINE_LOOP); // TOP FACE
|
||||
glVertex3fv(&(V[4].x)); glVertex3fv(&(V[5].x));
|
||||
glVertex3fv(&(V[1].x)); glVertex3fv(&(V[0].x));
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // BOTTOM FACE
|
||||
glVertex3fv(&(V[3].x)); glVertex3fv(&(V[2].x));
|
||||
glVertex3fv(&(V[6].x)); glVertex3fv(&(V[7].x));
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // LEFT FACE
|
||||
glVertex3fv(&(V[1].x)); glVertex3fv(&(V[5].x));
|
||||
glVertex3fv(&(V[6].x)); glVertex3fv(&(V[2].x));
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // RIGHT FACE
|
||||
glVertex3fv(&(V[0].x)); glVertex3fv(&(V[3].x));
|
||||
glVertex3fv(&(V[7].x)); glVertex3fv(&(V[4].x));
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // NEAR FACE
|
||||
glVertex3fv(&(V[1].x)); glVertex3fv(&(V[2].x));
|
||||
glVertex3fv(&(V[3].x)); glVertex3fv(&(V[0].x));
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // FAR FACE
|
||||
glVertex3fv(&(V[4].x)); glVertex3fv(&(V[7].x));
|
||||
glVertex3fv(&(V[6].x)); glVertex3fv(&(V[5].x));
|
||||
glEnd();
|
||||
|
||||
// DRAW PROJECTOR LINES FROM EYE TO CORNERS OF VIEWPLANE WINDOW
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(&(Orig.x)); glVertex3fv(&(V[1].x));
|
||||
glVertex3fv(&(Orig.x)); glVertex3fv(&(V[2].x));
|
||||
glVertex3fv(&(Orig.x)); glVertex3fv(&(V[3].x));
|
||||
glVertex3fv(&(Orig.x)); glVertex3fv(&(V[0].x));
|
||||
glEnd();
|
||||
|
||||
}
|
||||
void Camera::DisplayInGreen() const
|
||||
{
|
||||
//draws the camera in unlit green lines, then restores the GL state
|
||||
glPushAttrib(GL_LIGHTING_BIT);
|
||||
glDisable(GL_LIGHTING);
|
||||
glPushAttrib(GL_LINE_BIT);
|
||||
glLineWidth(1.0);
|
||||
glColor3f(0,1,0);
|
||||
|
||||
Display();
|
||||
|
||||
glPopAttrib();
|
||||
glPopAttrib();
|
||||
|
||||
}
|
||||
409
simgear/scene/sky/clouds3d/camera.cpp
Normal file
409
simgear/scene/sky/clouds3d/camera.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : camera.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// camera.cpp : camera class implementation
|
||||
//----------------------------------------------------------------------------
|
||||
// $Id$
|
||||
//============================================================================
|
||||
#include "camera.hpp"
|
||||
#include <iostream.h>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CONSTRUCTOR: defines a default camera system defined as (45 DEG FOV)
|
||||
//----------------------------------------------------------------------------
|
||||
Camera::Camera()
|
||||
{
|
||||
X.Set(1,0,0); Y.Set(0,1,0); Z.Set(0,0,1);
|
||||
Orig.Set(0,0,0);
|
||||
Near=0.5f; Far=140.0f; wL=-1; wR=1; wT=1; wB=-1;
|
||||
|
||||
}
|
||||
|
||||
Camera::Camera(const Camera &Cam)
|
||||
{
|
||||
Copy(Cam);
|
||||
}
|
||||
|
||||
void Camera::Copy(const Camera &Cam)
|
||||
{
|
||||
X=Cam.X; Y=Cam.Y; Z=Cam.Z; Orig=Cam.Orig;
|
||||
Near=Cam.Near; Far=Cam.Far;
|
||||
wL=Cam.wL; wR=Cam.wR; wT=Cam.wT; wB=Cam.wB;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OpenGL CAMERA ORIENTATION ROUTINE (glLookAt)
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::LookAt(
|
||||
const Vec3f& Eye, const Vec3f& ViewRefPt, const Vec3f& ViewUp)
|
||||
{
|
||||
Z = Eye-ViewRefPt; Z.Normalize(); // CALC CAM AXES ("/" IS CROSS-PROD)
|
||||
X = ViewUp/Z; X.Normalize();
|
||||
Y = Z/X; Y.Normalize();
|
||||
Orig = Eye;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OpenGL PERSPECTIVE FRUSTUM DEFINITION ROUTINE (gluPerspective)
|
||||
// Aspect = Width/Height; Yfov in degrees
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::Perspective(float Yfov, float Aspect, float Ndist, float Fdist)
|
||||
{
|
||||
Yfov *= 0.0174532f; // CONVERT TO RADIANS
|
||||
Near=Ndist; Far=Fdist;
|
||||
wT=(float)tan(Yfov*0.5f)*Near; wB=-wT;
|
||||
wR=wT*Aspect; wL=-wR;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OpenGL PERSPECTIVE FRUSTUM DEFINITION ROUTINE (glFrustum). Window extents
|
||||
// are defined on the viewplane at z=-Ndist.
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::Frustum(float l, float r, float b, float t, float Ndist, float Fdist)
|
||||
{
|
||||
Near=Ndist; Far=Fdist;
|
||||
wR=r; wL=l; wB=b; wT=t;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Completely defines a camera as a tight fitting frustum surrounding the
|
||||
// given bounding sphere. This is useful when most precision
|
||||
// is required in pixel and depth resolution (for example, shadow-maps).
|
||||
// The resulting camera is not skewed!
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::TightlyFitToSphere(
|
||||
const Vec3f& Eye, const Vec3f& ViewUp, const Vec3f& Cntr, float Rad)
|
||||
{
|
||||
// FIRST DEFINE COORDINATE FRAME
|
||||
LookAt(Eye,Cntr,ViewUp);
|
||||
|
||||
// PROJECTED DIST TO CNTR ALONG VIEWDIR
|
||||
float DistToCntr = (Cntr-Orig) * ViewDir();
|
||||
|
||||
// CALC TIGHT-FITTING NEAR AND FAR PLANES
|
||||
Near = DistToCntr-Rad;
|
||||
Far = DistToCntr+Rad;
|
||||
|
||||
//x = n*R / sqrt(d2 - r2)
|
||||
|
||||
if (Near<=0 || Far<=0)
|
||||
printf("ERROR (Camera::TightlyFitToSphere) Eye is inside the sphere!\n");
|
||||
|
||||
// CALC TIGHT-FITTING SIDES
|
||||
wT = (Near * Rad) / (float)sqrt(DistToCntr*DistToCntr - Rad*Rad);//(Near * Rad) / DistToCntr;
|
||||
wB = -wT;
|
||||
wL = wB;
|
||||
wR = wT;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Routines to return the Lookat, Perspective, and Frustum params.
|
||||
// NOTE: Perspective is designed for non-skewed cameras: the viewing
|
||||
// direction must be centered on the viewplane window. Use frustum
|
||||
// for off-axis cameras.
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::GetLookAtParams(Vec3f *Eye, Vec3f *ViewRefPt, Vec3f *ViewUp) const
|
||||
{
|
||||
*Eye = Orig;
|
||||
*ViewRefPt = Orig - Z;
|
||||
*ViewUp = Y;
|
||||
}
|
||||
|
||||
void Camera::GetPerspectiveParams(float *Yfov, float *Aspect,
|
||||
float *Ndist, float *Fdist) const
|
||||
{
|
||||
*Yfov = (float)atan(wT/Near) * 57.29578f * 2.0f; // CONVERT TO DEGREES
|
||||
*Aspect = wR/wT;
|
||||
*Ndist = Near;
|
||||
*Fdist = Far;
|
||||
}
|
||||
|
||||
void Camera::GetFrustumParams(float *l, float *r, float *b, float *t,
|
||||
float *Ndist, float *Fdist) const
|
||||
{
|
||||
*l = wL;
|
||||
*r = wR;
|
||||
*b = wB;
|
||||
*t = wT;
|
||||
*Ndist = Near;
|
||||
*Fdist = Far;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RETURNS THE COP OR EYE IN WORLD COORDS (ORIG OF CAMERA SYSTEM)
|
||||
//----------------------------------------------------------------------------
|
||||
const Vec3f& Camera::wCOP() const
|
||||
{
|
||||
return( Orig );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RETURNS THE VIEWING DIRECTION
|
||||
//----------------------------------------------------------------------------
|
||||
Vec3f Camera::ViewDir() const
|
||||
{
|
||||
return( -Z );
|
||||
}
|
||||
|
||||
Vec3f Camera::ViewDirOffAxis() const
|
||||
{
|
||||
float x=(wL+wR)*0.5f, y=(wT+wB)*0.5f; // MIDPOINT ON VIEWPLANE WINDOW
|
||||
Vec3f ViewDir = X*x + Y*y - Z*Near;
|
||||
ViewDir.Normalize();
|
||||
return( ViewDir );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Vec3f WORLD-TO-CAM AND CAM-TO-WORLD ROUTINES
|
||||
//----------------------------------------------------------------------------
|
||||
Vec3f Camera::WorldToCam(const Vec3f& wP) const
|
||||
{
|
||||
Vec3f sP(wP-Orig);
|
||||
Vec3f cP(X*sP,Y*sP,Z*sP); return(cP);
|
||||
}
|
||||
|
||||
// Return the z-value of the world point in camera space
|
||||
float Camera::WorldToCamZ(const Vec3f& wP) const
|
||||
{
|
||||
Vec3f sP(wP-Orig);
|
||||
float zdist = Z*sP;
|
||||
return(zdist);
|
||||
}
|
||||
|
||||
|
||||
Vec3f Camera::CamToWorld(const Vec3f& cP) const
|
||||
{
|
||||
Vec3f wP(X*cP.x + Y*cP.y + Z*cP.z + Orig); return(wP);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Makes the camera pose be the identity. World and camera space will be the
|
||||
// same. Window extents and near/far planes are unaffected.
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::LoadIdentityXform()
|
||||
{
|
||||
X.Set(1,0,0);
|
||||
Y.Set(0,1,0);
|
||||
Z.Set(0,0,1);
|
||||
Orig.Set(0,0,0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Applies an OpenGL style premult/col vector xform to the coordinate frame.
|
||||
// Only rotates, translates, and uniform scales are allowed.
|
||||
// Window extents and near/far planes are affected by scaling.
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::Xform(const float M[16])
|
||||
{
|
||||
X.Set( X.x*M[0] + X.y*M[4] + X.z*M[8],
|
||||
X.x*M[1] + X.y*M[5] + X.z*M[9],
|
||||
X.x*M[2] + X.y*M[6] + X.z*M[10] );
|
||||
Y.Set( Y.x*M[0] + Y.y*M[4] + Y.z*M[8],
|
||||
Y.x*M[1] + Y.y*M[5] + Y.z*M[9],
|
||||
Y.x*M[2] + Y.y*M[6] + Y.z*M[10] );
|
||||
Z.Set( Z.x*M[0] + Z.y*M[4] + Z.z*M[8],
|
||||
Z.x*M[1] + Z.y*M[5] + Z.z*M[9],
|
||||
Z.x*M[2] + Z.y*M[6] + Z.z*M[10] );
|
||||
Orig.Set( Orig.x*M[0] + Orig.y*M[4] + Orig.z*M[8] + M[12],
|
||||
Orig.x*M[1] + Orig.y*M[5] + Orig.z*M[9] + M[13],
|
||||
Orig.x*M[2] + Orig.y*M[6] + Orig.z*M[10] + M[14] );
|
||||
|
||||
// MUST RENORMALIZE AXES TO FIND THE UNIFORM SCALE
|
||||
float Scale = X.Length();
|
||||
X /= Scale;
|
||||
Y /= Scale;
|
||||
Z /= Scale;
|
||||
|
||||
// SCALE THE WINDOW EXTENTS AND THE NEAR/FAR PLANES
|
||||
wL*=Scale;
|
||||
wR*=Scale;
|
||||
wB*=Scale;
|
||||
wT*=Scale;
|
||||
Near*=Scale;
|
||||
Far*=Scale;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Translates the camera by the vector amount trans.
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::Translate(const Vec3f& trans)
|
||||
{
|
||||
Orig += trans;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Translates the camera about its origin by the rotation matrix M.
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::Rotate(const float M[9])
|
||||
{
|
||||
X.Set( X.x*M[0] + X.y*M[3] + X.z*M[6],
|
||||
X.x*M[1] + X.y*M[4] + X.z*M[7],
|
||||
X.x*M[2] + X.y*M[5] + X.z*M[8] );
|
||||
Y.Set( Y.x*M[0] + Y.y*M[3] + Y.z*M[6],
|
||||
Y.x*M[1] + Y.y*M[4] + Y.z*M[7],
|
||||
Y.x*M[2] + Y.y*M[5] + Y.z*M[8] );
|
||||
Z.Set( Z.x*M[0] + Z.y*M[3] + Z.z*M[6],
|
||||
Z.x*M[1] + Z.y*M[4] + Z.z*M[7],
|
||||
Z.x*M[2] + Z.y*M[5] + Z.z*M[8] );
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Returns the COMPOSITE xform matrix that takes a point in the object space
|
||||
// to a screen space (pixel) point. The inverse is also provided.
|
||||
// You have to give the pixel dimensions of the viewport window.
|
||||
//----------------------------------------------------------------------------
|
||||
float* Camera::GetXform_Screen2Obj(float* M, int WW, int WH) const
|
||||
{
|
||||
Screen2WorldXform16fv(M,&(X.x),&(Y.x),&(Z.x),&(Orig.x),
|
||||
wL,wR,wB,wT,Near,Far,WW,WH);
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Camera::GetXform_Obj2Screen(float* M, int WW, int WH) const
|
||||
{
|
||||
World2ScreenXform16fv(M,&(X.x),&(Y.x),&(Z.x),&(Orig.x),
|
||||
wL,wR,wB,wT,Near,Far,WW,WH);
|
||||
return(M);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OPENGL STYLE CAMERA VIEWING MATRIX ROUTINES (PREMULT/COL VECT, 4x4 MATRIX)
|
||||
// A POINT IN THE WORLD SPACE CAN BE TRANSFORMED TO A PIXEL ON THE CAMERA
|
||||
// VIEWPLANE BY TRANSFORMING WITH THE COMPOSITE MATRIX: C = V*P*M
|
||||
// WHERE V IS THE Viewport XFORM, P IS THE Projection XFORM, AND M IS THE
|
||||
// Modelview XFORM. The associated inverse matrices are also provided.
|
||||
//----------------------------------------------------------------------------
|
||||
float* Camera::GetModelviewMatrix(float* M) const
|
||||
{
|
||||
Viewing16fv(M,&(X.x),&(Y.x),&(Z.x),&(Orig.x));
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Camera::GetInvModelviewMatrix(float* M) const
|
||||
{
|
||||
invViewing16fv(M,&(X.x),&(Y.x),&(Z.x),&(Orig.x));
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Camera::GetProjectionMatrix(float* M) const
|
||||
{
|
||||
Frustum16fv(M,wL,wR,wB,wT,Near,Far);
|
||||
return(M);
|
||||
}
|
||||
|
||||
void Camera::SetModelviewMatrix(const float* M)
|
||||
{
|
||||
Viewing2CoordFrame16fv(M, &(X.x), &(Y.x), &(Z.x), &(Orig.x));
|
||||
}
|
||||
|
||||
float* Camera::GetInvProjectionMatrix(float* M) const
|
||||
{
|
||||
invFrustum16fv(M,wL,wR,wB,wT,Near,Far);
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Camera::GetViewportMatrix(float* M, int WW, int WH) const
|
||||
{
|
||||
Viewport16fv(M,WW,WH);
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Camera::GetInvViewportMatrix(float* M, int WW, int WH) const
|
||||
{
|
||||
invViewport16fv(M,WW,WH);
|
||||
return(M);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Given a screen pixel location (sx,sy) w/ (0,0) at the lower-left and the
|
||||
// screen dimensions, return the ray (start,dir) of the ray in world coords.
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::GetPixelRay(float sx, float sy, int ww, int wh,
|
||||
Vec3f *Start, Vec3f *Dir) const
|
||||
{
|
||||
Vec3f wTL = Orig + (X*wL) + (Y*wT) - (Z*Near); // FIND LOWER-LEFT
|
||||
Vec3f dX = (X*(wR-wL))/(float)ww; // WORLD WIDTH OF PIXEL
|
||||
Vec3f dY = (Y*(wT-wB))/(float)wh; // WORLD HEIGHT OF PIXEL
|
||||
wTL += (dX*sx - dY*sy); // INCR TO WORLD PIXEL
|
||||
wTL += (dX*0.5 - dY*0.5); // INCR TO PIXEL CNTR
|
||||
*Start = Orig;
|
||||
*Dir = wTL-Orig;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// READ AND WRITE CAMERA AXES AND ORIGIN TO AND FROM A FILE GIVEN A FILE PTR.
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::WriteToFile(FILE *fp) const
|
||||
{
|
||||
if (fp==NULL) { printf("ERROR WRITING CAM TO FILE!\n"); return; }
|
||||
fprintf(fp,"%f %f %f %f %f %f %f %f %f %f %f %f\n",
|
||||
X.x,X.y,X.z, Y.x,Y.y,Y.z, Z.x,Z.y,Z.z, Orig.x,Orig.y,Orig.z);
|
||||
}
|
||||
|
||||
int Camera::ReadFromFile(FILE *fp) // RETURNS "1" IF SUCCESSFUL, "0" IF EOF
|
||||
{
|
||||
int Cond = fscanf(fp,"%f %f %f %f %f %f %f %f %f %f %f %f",
|
||||
&X.x,&X.y,&X.z, &Y.x,&Y.y,&Y.z,
|
||||
&Z.x,&Z.y,&Z.z, &Orig.x,&Orig.y,&Orig.z);
|
||||
return(Cond!=EOF);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// 0=RTN,1=LTN,2=LBN,3=RBN,4=RTF,5=LTF,6=LBF,7=RBF
|
||||
// (Left,Right, Bottom,Top, Near,Far)
|
||||
// In order, near pts counter-clockwise starting with right-top-near (RTN) pt
|
||||
// and then far pts ccw starting with right-top-far (RTF) pt
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::CalcVerts(Vec3f *V) const // MUST BE PREALLOCED : "Vec3f V[8]"
|
||||
{
|
||||
// WINDOW EXTENTS ARE DEFINED ON THE NEAR PLANE, CALC NEAR PTS (IN CAM COORDS)
|
||||
float NearZ = -Near;
|
||||
V[0].Set(wR,wT,NearZ);
|
||||
V[1].Set(wL,wT,NearZ);
|
||||
V[2].Set(wL,wB,NearZ);
|
||||
V[3].Set(wR,wB,NearZ);
|
||||
|
||||
// CALC FAR PTS (IN CAM COORDS)
|
||||
float FarZ=-Far, FN=Far/Near;
|
||||
float fwL=wL*FN, fwR=wR*FN, fwB=wB*FN, fwT=wT*FN;
|
||||
V[4].Set(fwR,fwT,FarZ);
|
||||
V[5].Set(fwL,fwT,FarZ);
|
||||
V[6].Set(fwL,fwB,FarZ);
|
||||
V[7].Set(fwR,fwB,FarZ);
|
||||
|
||||
// XFORM FRUSTUM IN CAM COORDS TO WORLD SPACE
|
||||
for (int i=0; i<8; i++)
|
||||
V[i] = CamToWorld(V[i]);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// PRINT ROUTINE
|
||||
//----------------------------------------------------------------------------
|
||||
void Camera::Print() const
|
||||
{
|
||||
printf("Camera System Parameters:\n");
|
||||
printf(" X: (%.3f, %.3f, %.3f)\n", X.x, X.y, X.z);
|
||||
printf(" Y: (%.3f, %.3f, %.3f)\n", Y.x, Y.y, Y.z);
|
||||
printf(" Z: (%.3f, %.3f, %.3f)\n", Z.x, Z.y, Z.z);
|
||||
printf(" Origin: (%.3f, %.3f, %.3f)\n", Orig.x, Orig.y, Orig.z);
|
||||
printf(" NFLRBT: (%.3f, %.3f, %.3f, %.3f, %.3f, %.3f)\n",
|
||||
Near,Far,wL,wR,wB,wT);
|
||||
};
|
||||
102
simgear/scene/sky/clouds3d/camera.hpp
Normal file
102
simgear/scene/sky/clouds3d/camera.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : camera.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// camera.hpp : OPENGL-style camera class definition
|
||||
// Defines and stores a "camera" composed of 3 coord axes, an origin for
|
||||
// these axes (center-of-projection or eye location), a near and far plane
|
||||
// as distances from the origin projected along the viewing direction,
|
||||
// the viewplane window extents (projection window defined in cam coords
|
||||
// on the viewplane - near plane). ViewPlane is defined as the near plane.
|
||||
// Viewing direction is always defined along the -Z axis with eye at origin.
|
||||
//----------------------------------------------------------------------------
|
||||
// $Id$
|
||||
//============================================================================
|
||||
|
||||
#ifndef CAMERA
|
||||
#define CAMERA
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vec3f.hpp>
|
||||
#include <mat16fv.hpp>
|
||||
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
|
||||
Vec3f X, Y, Z; // NORMALIZED CAMERA COORDINATE-AXIS VECTORS
|
||||
Vec3f Orig; // LOCATION OF ORIGIN OF CAMERA SYSTEM IN WORLD COORDS
|
||||
float wL,wR,wB,wT; // WINDOW EXTENTS DEFINED AS A RECT ON NearPlane
|
||||
float Near,Far; // DISTANCES TO NEAR AND FAR PLANES (IN VIEWING DIR)
|
||||
|
||||
Camera();
|
||||
Camera(const Camera &Cam);
|
||||
void Copy(const Camera &Cam);
|
||||
|
||||
void LookAt(const Vec3f& Eye, const Vec3f& ViewRefPt, const Vec3f& ViewUp);
|
||||
void Perspective(float Yfov, float Aspect, float Ndist, float Fdist);
|
||||
void Frustum(float l, float r, float b, float t, float Ndist, float Fdist);
|
||||
|
||||
void TightlyFitToSphere(
|
||||
const Vec3f& Eye, const Vec3f& ViewUp, const Vec3f& Cntr, float Rad);
|
||||
|
||||
void GetLookAtParams(Vec3f *Eye, Vec3f *ViewRefPt, Vec3f *ViewUp) const;
|
||||
void GetPerspectiveParams(float *Yfov, float *Aspect,
|
||||
float *Ndist, float *Fdist) const;
|
||||
void GetFrustumParams(float *l, float *r, float *b, float *t,
|
||||
float *Ndist, float *Fdist) const;
|
||||
const Vec3f& wCOP() const; // WORLD COORDINATE CENTER-OF-PROJECTION (EYE)
|
||||
Vec3f ViewDir() const; // VIEWING DIRECTION
|
||||
Vec3f ViewDirOffAxis() const;
|
||||
|
||||
float* GetXform_Screen2Obj(float* M, int WW, int WH) const;
|
||||
float* GetXform_Obj2Screen(float* M, int WW, int WH) const;
|
||||
|
||||
float* GetModelviewMatrix(float* M) const;
|
||||
float* GetProjectionMatrix(float* M) const;
|
||||
float* GetViewportMatrix(float* M, int WW, int WH) const;
|
||||
|
||||
void SetModelviewMatrix(const float* M);
|
||||
|
||||
float* GetInvModelviewMatrix(float* M) const;
|
||||
float* GetInvProjectionMatrix(float* M) const;
|
||||
float* GetInvViewportMatrix(float* M, int WW, int WH) const;
|
||||
|
||||
Vec3f WorldToCam(const Vec3f &wP) const;
|
||||
float WorldToCamZ(const Vec3f &wP) const;
|
||||
Vec3f CamToWorld(const Vec3f &cP) const;
|
||||
|
||||
void LoadIdentityXform();
|
||||
void Xform(const float M[16]);
|
||||
|
||||
void Translate(const Vec3f& trans);
|
||||
void Rotate(const float M[9]);
|
||||
|
||||
void GetPixelRay(float sx, float sy, int ww, int wh,
|
||||
Vec3f *Start, Vec3f *Dir) const;
|
||||
|
||||
void WriteToFile(FILE *fp) const;
|
||||
int ReadFromFile(FILE *fp); // RETURNS "1" IF SUCCESSFUL, "0" IF EOF
|
||||
|
||||
void CalcVerts(Vec3f *V) const; // CALCS EIGHT CORNERS OF VIEW-FRUSTUM
|
||||
void Print() const;
|
||||
void Display() const;
|
||||
void DisplaySolid() const;
|
||||
void DisplayInGreen() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
324
simgear/scene/sky/clouds3d/camutils.cpp
Normal file
324
simgear/scene/sky/clouds3d/camutils.cpp
Normal file
@@ -0,0 +1,324 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : camutils.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// camutils.cpp : a set of camera utility functions
|
||||
//============================================================================
|
||||
|
||||
#include "camutils.hpp"
|
||||
#include <plane.hpp>
|
||||
#include <tri.hpp>
|
||||
#include <minmaxbox.hpp>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Given a camera's 8 corner vertices and its 6 side planes and a triangle ABC,
|
||||
// return whether or not the tri overlaps the camera's frustum.
|
||||
//----------------------------------------------------------------------------
|
||||
int CamTriOverlap(const Vec3f V[8], const float P[][4],
|
||||
const Vec3f& A, const Vec3f& B, const Vec3f& C)
|
||||
{
|
||||
// TEST TRIANGLE AGAINST ALL PLANES OF CAMERA, FOR EACH VERTEX CLASSIFY
|
||||
// AS INSIDE OR OUTSIDE OF PLANE (BY SETTING APPROPRIATE BIT IN BITMASK)
|
||||
// FOR EACH VERTEX, WE HAVE A BITMASK INDICATING WHETHER THE VERTEX
|
||||
// IS IN OR OUT OF EACH PLANE (LS 6-BITS, SET MEANS "OUT")
|
||||
unsigned int BitMaskA=0, BitMaskB=0, BitMaskC=0;
|
||||
unsigned int PlaneBitMask=1; // CURRENT PLANE BEING CHECKED
|
||||
int i;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
if ( PlanePtOutTest(P[i], &(A.x)) ) BitMaskA |= PlaneBitMask;
|
||||
if ( PlanePtOutTest(P[i], &(B.x)) ) BitMaskB |= PlaneBitMask;
|
||||
if ( PlanePtOutTest(P[i], &(C.x)) ) BitMaskC |= PlaneBitMask;
|
||||
PlaneBitMask<<=1;
|
||||
}
|
||||
|
||||
// TRIVIAL ACCEPTANCE: IF ANY VERTEX IS COMPLETELY INSIDE ALL PLANES (=0)
|
||||
if (BitMaskA==0 || BitMaskB==0 || BitMaskC==0) return(1);
|
||||
|
||||
// TRIVIAL REJECTION: IF ALL VERTICES ARE OUTSIDE OF ANY PLANE
|
||||
PlaneBitMask=1;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
if ((BitMaskA & BitMaskB & BitMaskC & PlaneBitMask) > 0) return(0);
|
||||
PlaneBitMask<<=1;
|
||||
}
|
||||
|
||||
// TEST EDGES OF TRIANGLE AGAINST PLANES OF CAMERA
|
||||
float InT, OutT;
|
||||
if ( PlanesEdgeIsect(P,6,&(A.x),&(B.x),&InT,&OutT) ) return(1);
|
||||
if ( PlanesEdgeIsect(P,6,&(B.x),&(C.x),&InT,&OutT) ) return(1);
|
||||
if ( PlanesEdgeIsect(P,6,&(C.x),&(A.x),&InT,&OutT) ) return(1);
|
||||
|
||||
// TEST EDGES OF CAMERA AGAINST TRIANGLE
|
||||
float IsectPt[3];
|
||||
if ( EdgeTriIsect(&(V[0].x),&(V[4].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[1].x),&(V[5].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[2].x),&(V[6].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[3].x),&(V[7].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[1].x),&(V[0].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[5].x),&(V[4].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[6].x),&(V[7].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[2].x),&(V[3].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[4].x),&(V[7].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[5].x),&(V[6].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[1].x),&(V[2].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
if ( EdgeTriIsect(&(V[0].x),&(V[3].x),&(A.x),&(B.x),&(C.x),IsectPt) ) return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int CamTriOverlap(const Camera *Cam,
|
||||
const Vec3f& A, const Vec3f& B, const Vec3f& C)
|
||||
{
|
||||
// GET CAMERA VERTICES
|
||||
Vec3f V[8];
|
||||
Cam->CalcVerts(V);
|
||||
|
||||
// CALCULATE SIX CAMERA PLANES FROM CAMERA VERTICES
|
||||
float P[6][4];
|
||||
CalcCamPlanes(V,P);
|
||||
|
||||
return( CamTriOverlap(V,P,A,B,C) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Temporary implementation of CamQuadOverlap (uses CamTriOverlap).
|
||||
//----------------------------------------------------------------------------
|
||||
int CamQuadOverlap(
|
||||
const Camera *Cam,
|
||||
const Vec3f& A, const Vec3f& B, const Vec3f& C, const Vec3f& D)
|
||||
{
|
||||
if ( CamTriOverlap(Cam,A,B,C) ) return(1);
|
||||
if ( CamTriOverlap(Cam,C,D,A) ) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int CamQuadOverlap(
|
||||
const Camera *Cam,
|
||||
const float A[3], const float B[3], const float C[3], const float D[3])
|
||||
{
|
||||
Vec3f a(A),b(B),c(C),d(D);
|
||||
return( CamQuadOverlap(Cam,a,b,c,d) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Calculate the six planes for a camera. User must have prealloced an array
|
||||
// of 24 floats (6 planes * 4 coeffs each). Two version: 1 that calculates
|
||||
// the camera vertices, requires the cam verts to be precomputed
|
||||
//----------------------------------------------------------------------------
|
||||
void CalcCamPlanes(const Vec3f *V, float P[][4])
|
||||
{
|
||||
PlaneEquation(P[0], &(V[2].x),&(V[5].x),&(V[6].x)); // LEFT
|
||||
PlaneEquation(P[1], &(V[0].x),&(V[7].x),&(V[4].x)); // RIGHT
|
||||
PlaneEquation(P[2], &(V[3].x),&(V[6].x),&(V[7].x)); // BOTTOM
|
||||
PlaneEquation(P[3], &(V[1].x),&(V[4].x),&(V[5].x)); // TOP
|
||||
PlaneEquation(P[4], &(V[1].x),&(V[2].x),&(V[0].x)); // NEAR
|
||||
PlaneEquation(P[5], &(V[4].x),&(V[6].x),&(V[5].x)); // FAR
|
||||
}
|
||||
|
||||
void CalcCamPlanes(const Camera *Cam, float P[][4])
|
||||
{
|
||||
Vec3f V[8];
|
||||
Cam->CalcVerts(V);
|
||||
CalcCamPlanes(V,P);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Camera view-frustum/MinMaxBox (AABB) overlap test: given the extents of the
|
||||
// AABB returns the type of overlap determined (complete out(1), partial (0),
|
||||
// complete in (-1)) m and M are the min and max extents of the AABB respectively.
|
||||
// Version is provided that takes in a precomputed set of camera vertices
|
||||
// and planes
|
||||
//--------------------------------------------------------------------------
|
||||
int CamMinMaxBoxOverlap(
|
||||
const Camera *Cam, const Vec3f V1[8], const float cP[][4],
|
||||
const Vec3f& m, const Vec3f& M)
|
||||
{
|
||||
// GO FOR TRIVIAL REJECTION OR ACCEPTANCE USING "FASTER OVERLAP TEST"
|
||||
int CompletelyIn=1; // ASSUME COMPLETELY IN UNTIL ONE COUNTEREXAMPLE
|
||||
int R; // TEST RETURN VALUE
|
||||
for (int i=0; i<6; i++)
|
||||
{
|
||||
R=PlaneMinMaxBoxOverlap(cP[i],&(m.x),&(M.x));
|
||||
if(R==COMPLETEOUT) return(COMPLETEOUT);
|
||||
else if(R==PARTIAL) CompletelyIn=0;
|
||||
}
|
||||
|
||||
if (CompletelyIn) return(COMPLETEIN); // CHECK IF STILL COMPLETELY "IN"
|
||||
|
||||
// TEST IF VIEW-FRUSTUM EDGES PROTRUDE THROUGH AABB
|
||||
float InT, OutT;
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[0].x),&(V1[4].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[1].x),&(V1[5].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[2].x),&(V1[6].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[3].x),&(V1[7].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[0].x),&(V1[1].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[1].x),&(V1[2].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[2].x),&(V1[3].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[3].x),&(V1[0].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[4].x),&(V1[5].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[5].x),&(V1[6].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[6].x),&(V1[7].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
if ( EdgeMinMaxBoxIsect(&(V1[7].x),&(V1[0].x),&(m.x),&(M.x),&InT,&OutT) ) return(PARTIAL);
|
||||
|
||||
// COMPUTE VERTICES OF AABB
|
||||
float bV[8][3];
|
||||
GetMinMaxBoxVerts(&(m.x),&(M.x),bV);
|
||||
|
||||
// TEST FOR PROTRUSION OF AABB EDGES THROUGH VIEW-FRUSTUM
|
||||
if ( PlanesEdgeIsect(cP,6,bV[0],bV[4],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[1],bV[5],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[2],bV[6],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[3],bV[7],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[0],bV[1],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[1],bV[2],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[2],bV[3],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[3],bV[0],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[4],bV[5],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[5],bV[6],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[6],bV[7],&InT,&OutT) ) return(PARTIAL);
|
||||
if ( PlanesEdgeIsect(cP,6,bV[7],bV[0],&InT,&OutT) ) return(PARTIAL);
|
||||
|
||||
// VF MUST BE COMPLETELY ENCLOSED SINCE PT IS NOT "OUT "OF ANY AABB PLANE.
|
||||
//return(COMPLETEOUT);
|
||||
return (PARTIAL);
|
||||
};
|
||||
|
||||
int CamMinMaxBoxOverlap(
|
||||
const Camera *Cam, const float m[3], const float M[3])
|
||||
{
|
||||
// GET CAMERA VERTICES
|
||||
Vec3f V1[8];
|
||||
Cam->CalcVerts(V1);
|
||||
|
||||
// CALCULATE SIX CAMERA PLANES FROM CAMERA VERTICES
|
||||
float cP[6][4];
|
||||
CalcCamPlanes(V1,cP);
|
||||
|
||||
return( CamMinMaxBoxOverlap(Cam,V1,cP,m,M) );
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Returns 1 if and only if the specified box is completely culled away.
|
||||
bool VFC(const Camera *Cam, const float m[3], const float M[3])
|
||||
{
|
||||
return (CamMinMaxBoxOverlap(Cam, m, M) == COMPLETEOUT);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Given the 8 corner vertices and the 6 side planes for two cameras,
|
||||
// returns the type of overlap (complete out(1), partial (0), complete in (-1))
|
||||
// with respect to the first camera.
|
||||
//----------------------------------------------------------------------------
|
||||
int CamCamOverlap(
|
||||
const Vec3f V1[8], const float P1[][4],
|
||||
const Vec3f V2[8], const float P2[][4])
|
||||
{
|
||||
int i, NumVertsOutAllPlanes, NumVertsOutOnePlane;
|
||||
float InT, OutT;
|
||||
|
||||
// TEST ALL CAM1 VERTICES AGAINST PLANES OF CAM2
|
||||
NumVertsOutAllPlanes=0;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
NumVertsOutOnePlane=0;
|
||||
for (int j=0; j<8; j++)
|
||||
NumVertsOutOnePlane += PlanePtOutTest(P2[i],&(V1[i].x));
|
||||
if (NumVertsOutOnePlane==8) return(1); // TRIVIAL REJECT, COMPLETELY OUT!
|
||||
NumVertsOutAllPlanes+=NumVertsOutOnePlane;
|
||||
}
|
||||
if (NumVertsOutAllPlanes==0) return(0); // TRIVIAL ACCEPT, PARTIAL!
|
||||
|
||||
// TEST ALL CAM2 VERTICES AGAINST PLANES OF CAM1
|
||||
NumVertsOutAllPlanes=0;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
NumVertsOutOnePlane=0;
|
||||
for (int j=0; j<8; j++)
|
||||
NumVertsOutOnePlane += PlanePtOutTest(P1[i],&(V2[i].x));
|
||||
if (NumVertsOutOnePlane==8) return(1); // TRIVIAL REJECT, COMPLETELY OUT!
|
||||
NumVertsOutAllPlanes+=NumVertsOutOnePlane;
|
||||
}
|
||||
if (NumVertsOutAllPlanes==0) return(-1); // TRIVIAL ACCEPT, COMPLETELY IN!
|
||||
|
||||
// TEST ALL CAM1 EDGES AGAINST SET OF CAM2 PLANES
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[0].x),&(V1[4].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[1].x),&(V1[5].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[2].x),&(V1[6].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[3].x),&(V1[7].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[0].x),&(V1[1].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[1].x),&(V1[2].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[2].x),&(V1[3].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[3].x),&(V1[0].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[4].x),&(V1[5].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[5].x),&(V1[6].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[6].x),&(V1[7].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P2,6,&(V1[7].x),&(V1[0].x),&InT,&OutT) ) return(0);
|
||||
|
||||
// TEST ALL CAM2 EDGES AGAINST SET OF CAM1 PLANES
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[0].x),&(V2[4].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[1].x),&(V2[5].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[2].x),&(V2[6].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[3].x),&(V2[7].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[0].x),&(V2[1].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[1].x),&(V2[2].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[2].x),&(V2[3].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[3].x),&(V2[0].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[4].x),&(V2[5].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[5].x),&(V2[6].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[6].x),&(V2[7].x),&InT,&OutT) ) return(0);
|
||||
if ( PlanesEdgeIsect(P1,6,&(V2[7].x),&(V2[0].x),&InT,&OutT) ) return(0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
int CamCamOverlap(const Camera *Cam1, const Camera *Cam2)
|
||||
{
|
||||
// GET CAMERA VERTICES
|
||||
Vec3f V1[8], V2[8];
|
||||
Cam1->CalcVerts(V1);
|
||||
Cam2->CalcVerts(V2);
|
||||
|
||||
// CALCULATE SIX CAMERA PLANES FROM CAMERA VERTICES
|
||||
float P1[6][4], P2[6][4];
|
||||
CalcCamPlanes(V1,P1);
|
||||
CalcCamPlanes(V2,P2);
|
||||
|
||||
return( CamCamOverlap(V1,P1,V2,P2) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Given a camera and a plane (defined by four coefficient of implicit
|
||||
// form: Ax+By+Cz+D=0), reflect the camera about the plane and invert
|
||||
// back into right-handed system (reflection inverts the space, so we
|
||||
// have to invert the X-axis and flip the window boundaries).
|
||||
//--------------------------------------------------------------------------
|
||||
void CamReflectAboutPlane(Camera *Cam, const float Plane[4])
|
||||
{
|
||||
// CREATE PLANAR REFLECTION MATRIX
|
||||
float M[16];
|
||||
PlanarReflection16fv(M,Plane);
|
||||
|
||||
// XFORM CAMERA
|
||||
Cam->Xform(M);
|
||||
|
||||
// RESULTING CAM IS LEFT-HANDED, FLIP THE X-AXIS, FLIP X WINDOW BOUNDS
|
||||
Cam->X = -(Cam->X);
|
||||
float t = -(Cam->wL);
|
||||
Cam->wL = -(Cam->wR);
|
||||
Cam->wR = t;
|
||||
}
|
||||
58
simgear/scene/sky/clouds3d/camutils.hpp
Normal file
58
simgear/scene/sky/clouds3d/camutils.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : camutils.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// camutils.hpp : a set of camera utility functions
|
||||
//============================================================================
|
||||
|
||||
#include "camera.hpp"
|
||||
|
||||
#define COMPLETEOUT 1
|
||||
#define PARTIAL 0
|
||||
#define COMPLETEIN -1
|
||||
|
||||
int CamTriOverlap(const Vec3f V[8], const float P[][4],
|
||||
const Vec3f& A, const Vec3f& B, const Vec3f& C);
|
||||
int CamTriOverlap(const Camera *Cam,
|
||||
const Vec3f& A, const Vec3f& B, const Vec3f& C);
|
||||
|
||||
int CamQuadOverlap(
|
||||
const Camera *Cam,
|
||||
const Vec3f& A, const Vec3f& B, const Vec3f& C, const Vec3f& D);
|
||||
|
||||
int CamQuadOverlap(
|
||||
const Camera *Cam,
|
||||
const float A[3], const float B[3], const float C[3], const float D[3]);
|
||||
|
||||
void CalcCamPlanes(const Vec3f V[8], float P[][4]);
|
||||
|
||||
void CalcCamPlanes(const Camera *Cam, float P[][4]);
|
||||
|
||||
int CamMinMaxBoxOverlap(const Camera *Cam,
|
||||
const Vec3f cV[8], const float cP[][4],
|
||||
const Vec3f& m, const Vec3f& M);
|
||||
|
||||
int CamMinMaxBoxOverlap(const Camera *Cam,
|
||||
const float m[3], const float M[3]);
|
||||
|
||||
bool VFC(const Camera *Cam, const float m[3], const float M[3]);
|
||||
|
||||
int CamCamOverlap(const Vec3f V1[8], const float P1[][4],
|
||||
const Vec3f V2[8], const float P2[][4]);
|
||||
int CamCamOverlap(const Camera *Cam1, const Camera *Cam2);
|
||||
|
||||
void CamReflectAboutPlane(Camera *Cam, const float Plane[4]);
|
||||
475
simgear/scene/sky/clouds3d/mat16fv.cpp
Normal file
475
simgear/scene/sky/clouds3d/mat16fv.cpp
Normal file
@@ -0,0 +1,475 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : mat16fv.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// $Id$
|
||||
//----------------------------------------------------------------------------
|
||||
// mat16fv.cpp : opengl-style float[16] matrix routines.
|
||||
//
|
||||
// OPENGL STYLE CAMERA VIEWING MATRIX ROUTINES (PREMULT/ROW VECT, 4x4 MATRIX)
|
||||
// A POINT IN THE WORLD SPACE CAN BE TRANSFORMED TO A PIXEL ON THE CAMERA
|
||||
// VIEWPLANE BY TRANSFORMING WITH THE COMPOSITE MATRIX: C = V*P*M
|
||||
// WHERE V IS THE Viewport XFORM, P IS THE Projection XFORM, AND M IS THE
|
||||
// Modelview XFORM. The associated inverse matrices are also provided.
|
||||
// Matrices are of the following form:
|
||||
// M[16] : 0 4 8 12
|
||||
// 1 5 9 13
|
||||
// 2 6 10 14
|
||||
// 3 7 11 15
|
||||
//============================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "vec3fv.hpp"
|
||||
|
||||
|
||||
float* Copy16fv(float* A, const float* B) // A=B
|
||||
{
|
||||
A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3];
|
||||
A[4]=B[4]; A[5]=B[5]; A[6]=B[6]; A[7]=B[7];
|
||||
A[8]=B[8]; A[9]=B[9]; A[10]=B[10]; A[11]=B[11];
|
||||
A[12]=B[12]; A[13]=B[13]; A[14]=B[14]; A[15]=B[15];
|
||||
return A;
|
||||
}
|
||||
|
||||
float* Mult16fv(float* C, const float* A, const float* B) // C=A*B
|
||||
{
|
||||
float tC[16];
|
||||
|
||||
tC[0] = A[0]*B[0] + A[4]*B[1] + A[8]*B[2] + A[12]*B[3];
|
||||
tC[1] = A[1]*B[0] + A[5]*B[1] + A[9]*B[2] + A[13]*B[3];
|
||||
tC[2] = A[2]*B[0] + A[6]*B[1] + A[10]*B[2] + A[14]*B[3];
|
||||
tC[3] = A[3]*B[0] + A[7]*B[1] + A[11]*B[2] + A[15]*B[3];
|
||||
|
||||
tC[4] = A[0]*B[4] + A[4]*B[5] + A[8]*B[6] + A[12]*B[7];
|
||||
tC[5] = A[1]*B[4] + A[5]*B[5] + A[9]*B[6] + A[13]*B[7];
|
||||
tC[6] = A[2]*B[4] + A[6]*B[5] + A[10]*B[6] + A[14]*B[7];
|
||||
tC[7] = A[3]*B[4] + A[7]*B[5] + A[11]*B[6] + A[15]*B[7];
|
||||
|
||||
tC[8] = A[0]*B[8] + A[4]*B[9] + A[8]*B[10] + A[12]*B[11];
|
||||
tC[9] = A[1]*B[8] + A[5]*B[9] + A[9]*B[10] + A[13]*B[11];
|
||||
tC[10] = A[2]*B[8] + A[6]*B[9] + A[10]*B[10] + A[14]*B[11];
|
||||
tC[11] = A[3]*B[8] + A[7]*B[9] + A[11]*B[10] + A[15]*B[11];
|
||||
|
||||
tC[12] = A[0]*B[12] + A[4]*B[13] + A[8]*B[14] + A[12]*B[15];
|
||||
tC[13] = A[1]*B[12] + A[5]*B[13] + A[9]*B[14] + A[13]*B[15];
|
||||
tC[14] = A[2]*B[12] + A[6]*B[13] + A[10]*B[14] + A[14]*B[15];
|
||||
tC[15] = A[3]*B[12] + A[7]*B[13] + A[11]*B[14] + A[15]*B[15];
|
||||
|
||||
Copy16fv(C,tC);
|
||||
|
||||
return(C);
|
||||
}
|
||||
|
||||
float* Mult16fv3fv(float *NewV, const float* M, const float *V)
|
||||
{
|
||||
NewV[0] = M[0]*V[0] + M[4]*V[1] + M[8]*V[2];
|
||||
NewV[1] = M[1]*V[0] + M[5]*V[1] + M[9]*V[2];
|
||||
NewV[2] = M[2]*V[0] + M[6]*V[1] + M[10]*V[2];
|
||||
return(NewV);
|
||||
}
|
||||
|
||||
float* Mult16fv3fvPerspDiv(float *NewV, const float* M, const float *V)
|
||||
{
|
||||
float W = M[3]*V[0] + M[7]*V[1] + M[11]*V[2] + M[15];
|
||||
NewV[0] = (M[0]*V[0] + M[4]*V[1] + M[8]*V[2] + M[12]) / W;
|
||||
NewV[1] = (M[1]*V[0] + M[5]*V[1] + M[9]*V[2] + M[13]) / W;
|
||||
NewV[2] = (M[2]*V[0] + M[6]*V[1] + M[10]*V[2] + M[14]) / W;
|
||||
return(NewV);
|
||||
}
|
||||
|
||||
float* Mult16fv4fv(float *NewV, const float* M, const float *V)
|
||||
{
|
||||
NewV[0] = M[0]*V[0] + M[4]*V[1] + M[8]*V[2] + M[12]*V[3];
|
||||
NewV[1] = M[1]*V[0] + M[5]*V[1] + M[9]*V[2] + M[13]*V[3];
|
||||
NewV[2] = M[2]*V[0] + M[6]*V[1] + M[10]*V[2] + M[14]*V[3];
|
||||
NewV[3] = M[3]*V[0] + M[7]*V[1] + M[11]*V[2] + M[15]*V[3];
|
||||
return(NewV);
|
||||
}
|
||||
|
||||
float* Identity16fv(float* M)
|
||||
{
|
||||
M[0]=M[5]=M[10]=M[15]=1;
|
||||
M[1]=M[2]=M[3]=M[4]=M[6]=M[7]=M[8]=M[9]=M[11]=M[12]=M[13]=M[14]=0;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Transpose16fv(float* M)
|
||||
{
|
||||
#define SWAP(a,b,t) (t)=(a);(a)=(b);(b)=(t);
|
||||
float t;
|
||||
SWAP(M[1],M[4],t);
|
||||
SWAP(M[2],M[8],t);
|
||||
SWAP(M[6],M[9],t);
|
||||
SWAP(M[3],M[12],t);
|
||||
SWAP(M[7],M[13],t);
|
||||
SWAP(M[11],M[14],t);
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Rotate16fv(float *M, float DegAng, const float Axis[3])
|
||||
{
|
||||
float RadAng = DegAng * 0.0174532f;
|
||||
float ca=(float)cos(RadAng),
|
||||
sa=(float)sin(RadAng);
|
||||
if (Axis[0]==1 && Axis[1]==0 && Axis[2]==0) // ABOUT X-AXIS
|
||||
{
|
||||
M[0]=1; M[4]=0; M[8]=0; M[12]=0;
|
||||
M[1]=0; M[5]=ca; M[9]=-sa; M[13]=0;
|
||||
M[2]=0; M[6]=sa; M[10]=ca; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
if (Axis[0]==0 && Axis[1]==1 && Axis[2]==0) // ABOUT Y-AXIS
|
||||
{
|
||||
M[0]=ca; M[4]=0; M[8]=sa; M[12]=0;
|
||||
M[1]=0; M[5]=1; M[9]=0; M[13]=0;
|
||||
M[2]=-sa; M[6]=0; M[10]=ca; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
if (Axis[0]==0 && Axis[1]==0 && Axis[2]==1) // ABOUT Z-AXIS
|
||||
{
|
||||
M[0]=ca; M[4]=-sa; M[8]=0; M[12]=0;
|
||||
M[1]=sa; M[5]=ca; M[9]=0; M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=1; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
else // ARBITRARY AXIS
|
||||
{
|
||||
float l = Axis[0]*Axis[0]+Axis[1]*Axis[1]+Axis[2]*Axis[2];
|
||||
float x, y, z;
|
||||
x=Axis[0],y=Axis[1],z=Axis[2];
|
||||
if (l > 1.0001f || l < 0.9999f && l!=0)
|
||||
{
|
||||
// needs normalization
|
||||
l=1.0f/(float)sqrt(l);
|
||||
x*=l; y*=l; z*=l;
|
||||
}
|
||||
float x2=x*x, y2=y*y, z2=z*z;
|
||||
M[0]=x2+ca*(1-x2); M[4]=(x*y)+ca*(-x*y)+sa*(-z); M[8]=(x*z)+ca*(-x*z)+sa*y;
|
||||
M[1]=(x*y)+ca*(-x*y)+sa*z; M[5]=y2+ca*(1-y2); M[9]=(y*z)+ca*(-y*z)+sa*(-x);
|
||||
M[2]=(x*z)+ca*(-x*z)+sa*(-y); M[6]=(y*z)+ca*(-y*z)+sa*x; M[10]=z2+ca*(1-z2);
|
||||
M[12]=M[13]=M[14]=M[3]=M[7]=M[11]=0;
|
||||
M[15]=1;
|
||||
}
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* invRotate16fv(float *M, float DegAng, const float Axis[3])
|
||||
{
|
||||
Rotate16fv(M,DegAng,Axis);
|
||||
Transpose16fv(M);
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Scale16fv(float* M, float sx, float sy, float sz)
|
||||
{
|
||||
M[0]=sx; M[4]=0; M[8]=0; M[12]=0;
|
||||
M[1]=0; M[5]=sy; M[9]=0; M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=sz; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* invScale16fv(float* M, float sx, float sy, float sz)
|
||||
{
|
||||
M[0]=1/sx; M[4]=0; M[8]=0; M[12]=0;
|
||||
M[1]=0; M[5]=1/sy; M[9]=0; M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=1/sz; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Translate16fv(float* M, float tx, float ty, float tz)
|
||||
{
|
||||
M[0]=1; M[4]=0; M[8]=0; M[12]=tx;
|
||||
M[1]=0; M[5]=1; M[9]=0; M[13]=ty;
|
||||
M[2]=0; M[6]=0; M[10]=1; M[14]=tz;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* invTranslate16fv(float* M, float tx, float ty, float tz)
|
||||
{
|
||||
M[0]=1; M[4]=0; M[8]=0; M[12]=-tx;
|
||||
M[1]=0; M[5]=1; M[9]=0; M[13]=-ty;
|
||||
M[2]=0; M[6]=0; M[10]=1; M[14]=-tz;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* LookAt(float* M,
|
||||
const float Eye[3],
|
||||
const float LookAtPt[3],
|
||||
const float ViewUp[3])
|
||||
{
|
||||
float X[3], Y[3], Z[3];
|
||||
Subtract3fv(Z,Eye,LookAtPt); Normalize3fv(Z);
|
||||
CrossProd3fv(X,ViewUp,Z); Normalize3fv(X);
|
||||
CrossProd3fv(Y,Z,X); Normalize3fv(Y);
|
||||
M[0]=X[0]; M[4]=X[1]; M[8]=X[2]; M[12]=-DotProd3fv(X,Eye); // TRANS->ROT
|
||||
M[1]=Y[0]; M[5]=Y[1]; M[9]=Y[2]; M[13]=-DotProd3fv(Y,Eye);
|
||||
M[2]=Z[0]; M[6]=Z[1]; M[10]=Z[2]; M[14]=-DotProd3fv(Z,Eye);
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* invLookAt(float* M,
|
||||
const float Eye[3],
|
||||
const float LookAtPt[3],
|
||||
const float ViewUp[3])
|
||||
{
|
||||
float X[3], Y[3], Z[3];
|
||||
Subtract3fv(Z,Eye,LookAtPt); Normalize3fv(Z);
|
||||
CrossProd3fv(X,ViewUp,Z); Normalize3fv(X);
|
||||
CrossProd3fv(Y,Z,X); Normalize3fv(Y);
|
||||
M[0]=X[0]; M[4]=Y[0]; M[8]=Z[0]; M[12]=Eye[0]; // ROT->TRANS
|
||||
M[1]=X[1]; M[5]=Y[1]; M[9]=Z[1]; M[13]=Eye[1];
|
||||
M[2]=X[2]; M[6]=Y[2]; M[10]=Z[2]; M[14]=Eye[2];
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Frustum16fv(float* M, float l, float r, float b, float t,
|
||||
float n, float f)
|
||||
{
|
||||
M[0]=(2*n)/(r-l); M[4]=0; M[8]=(r+l)/(r-l); M[12]=0;
|
||||
M[1]=0; M[5]=(2*n)/(t-b); M[9]=(t+b)/(t-b); M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=-(f+n)/(f-n); M[14]=(-2*f*n)/(f-n);
|
||||
M[3]=0; M[7]=0; M[11]=-1; M[15]=0;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* invFrustum16fv(float* M, float l, float r, float b, float t,
|
||||
float n, float f)
|
||||
{
|
||||
M[0]=(r-l)/(2*n); M[4]=0; M[8]=0; M[12]=(r+l)/(2*n);
|
||||
M[1]=0; M[5]=(t-b)/(2*n); M[9]=0; M[13]=(t+b)/(2*n);
|
||||
M[2]=0; M[6]=0; M[10]=0; M[14]=-1;
|
||||
M[3]=0; M[7]=0; M[11]=-(f-n)/(2*f*n); M[15]=(f+n)/(2*f*n);
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Perspective(float* M, float Yfov, float Aspect,
|
||||
float Ndist, float Fdist)
|
||||
{
|
||||
Yfov *= 0.0174532f; // CONVERT TO RADIANS
|
||||
float wT=(float)tan(Yfov*0.5f)*Ndist, wB=-wT;
|
||||
float wR=wT*Aspect, wL=-wR;
|
||||
Frustum16fv(M,wL,wR,wB,wT,Ndist,Fdist);
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* invPerspective(float* M, float Yfov, float Aspect,
|
||||
float Ndist, float Fdist)
|
||||
{
|
||||
Yfov *= 0.0174532f; // CONVERT TO RADIANS
|
||||
float wT=(float)tan(Yfov*0.5f)*Ndist, wB=-wT;
|
||||
float wR=wT*Aspect, wL=-wR;
|
||||
invFrustum16fv(M,wL,wR,wB,wT,Ndist,Fdist);
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Viewing16fv(
|
||||
float* M,
|
||||
const float X[3], const float Y[3], const float Z[3], const float O[3])
|
||||
{
|
||||
M[0]=X[0]; M[4]=X[1]; M[8]=X[2]; M[12]=-DotProd3fv(X,O);
|
||||
M[1]=Y[0]; M[5]=Y[1]; M[9]=Y[2]; M[13]=-DotProd3fv(Y,O);
|
||||
M[2]=Z[0]; M[6]=Z[1]; M[10]=Z[2]; M[14]=-DotProd3fv(Z,O);
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
// THE INVERSE OF Viewing16fv,
|
||||
// THIS TAKES A VIEW MATRIX AND RETURNS VIEWING AXES.
|
||||
// MATRIX ASSUMED TO BE ORTHONORMAL
|
||||
void Viewing2CoordFrame16fv(
|
||||
const float *M, float X[3], float Y[3], float Z[3], float O[3])
|
||||
{
|
||||
X[0]=M[0]; X[1]=M[4]; X[2]=M[8]; O[0]=-DotProd3fv(M,M+12);
|
||||
Y[0]=M[1]; Y[1]=M[5]; Y[2]=M[9]; O[1]=-DotProd3fv(M+4,M+12);
|
||||
Z[0]=M[2]; Z[1]=M[6]; Z[2]=M[10]; O[2]=-DotProd3fv(M+8,M+12);
|
||||
};
|
||||
|
||||
float* invViewing16fv(
|
||||
float* M,
|
||||
const float X[3], const float Y[3], const float Z[3], const float O[3])
|
||||
{
|
||||
M[0]=X[0]; M[4]=Y[0]; M[8]=Z[0]; M[12]=O[0];
|
||||
M[1]=X[1]; M[5]=Y[1]; M[9]=Z[1]; M[13]=O[1];
|
||||
M[2]=X[2]; M[6]=Y[2]; M[10]=Z[2]; M[14]=O[2];
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* Viewport16fv(float* M, int WW, int WH)
|
||||
{
|
||||
float WW2=(float)WW*0.5f, WH2=(float)WH*0.5f;
|
||||
M[0]=WW2; M[4]=0; M[8]=0; M[12]=WW2;
|
||||
M[1]=0; M[5]=WH2; M[9]=0; M[13]=WH2;
|
||||
M[2]=0; M[6]=0; M[10]=0.5f; M[14]=0.5f;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* invViewport16fv(float* M, int WW, int WH)
|
||||
{
|
||||
float WW2=2.0f/(float)WW, WH2=2.0f/(float)WH;
|
||||
M[0]=WW2; M[4]=0; M[8]=0; M[12]=-1.0;
|
||||
M[1]=0; M[5]=WH2; M[9]=0; M[13]=-1.0;
|
||||
M[2]=0; M[6]=0; M[10]=2.0; M[14]=-1.0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Given the coefficient [A B C D] of a plane in the implicit form
|
||||
// Ax+By+Cz+D=0 (see plane.hpp), this routine generates a reflection matrix
|
||||
// that will "reflect" all points/vectors about the given plane.
|
||||
// NOTE: the plane is assumed to be normalized: normal vector (A,B,C) is
|
||||
// normalized (unit-length), and D is the negative distance from the origin
|
||||
// to the plane along the normal.
|
||||
//--------------------------------------------------------------------------
|
||||
float* PlanarReflection16fv(float M[16], const float P[4])
|
||||
{
|
||||
float AA=P[0]*P[0], AB=P[0]*P[1], AC=P[0]*P[2], AD=P[0]*P[3],
|
||||
BB=P[1]*P[1], BC=P[1]*P[2], BD=P[1]*P[3],
|
||||
CC=P[2]*P[2], CD=P[2]*P[3];
|
||||
M[0]=1-2*AA; M[4]=-2*AB; M[8]=-2*AC; M[12]=-2*AD;
|
||||
M[1]=-2*AB; M[5]=1-2*BB; M[9]=-2*BC; M[13]=-2*BD;
|
||||
M[2]=-2*AC; M[6]=-2*BC; M[10]=1-2*CC; M[14]=-2*CD;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Returns a matrix that will xform a point from the given object-space
|
||||
// coordinate frame to world space
|
||||
// A composite matrix is formed as follows:
|
||||
// C = Translation * Rotation * Scaling (using column vectors/pre-multiplication)
|
||||
// WorldPt = C * ModelPt
|
||||
// The corresponding inverse Xform is also provided (GetWorld2ObjXform)
|
||||
//--------------------------------------------------------------------------
|
||||
float* Obj2WorldXform16fv(
|
||||
float *M,
|
||||
const float X[3], const float Y[3], const float Z[3],
|
||||
const float O[3], float Scale)
|
||||
{
|
||||
float sX[3], sY[3], sZ[3]; // CREATE SCALED VERSION OF ROT AXES
|
||||
ScalarMult3fv(sX,X,Scale);
|
||||
ScalarMult3fv(sY,Y,Scale);
|
||||
ScalarMult3fv(sZ,Z,Scale);
|
||||
M[0]=sX[0]; M[4]=sY[0]; M[8]=sZ[0]; M[12]=O[0];
|
||||
M[1]=sX[1]; M[5]=sY[1]; M[9]=sZ[1]; M[13]=O[1];
|
||||
M[2]=sX[2]; M[6]=sY[2]; M[10]=sZ[2]; M[14]=O[2];
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* World2ObjXform16fv(
|
||||
float *M,
|
||||
const float X[3], const float Y[3], const float Z[3],
|
||||
const float O[3], float Scale)
|
||||
{
|
||||
if (Scale<=0) { printf("Too small scale!\n"); Scale=1; }
|
||||
float invScale = 1/Scale;
|
||||
float sX[3], sY[3], sZ[3];
|
||||
ScalarMult3fv(sX,X,invScale);
|
||||
ScalarMult3fv(sY,Y,invScale);
|
||||
ScalarMult3fv(sZ,Z,invScale);
|
||||
M[0]=sX[0]; M[4]=sX[1]; M[8]=sX[2]; M[12]=-DotProd3fv(O,sX);
|
||||
M[1]=sY[0]; M[5]=sY[1]; M[9]=sY[2]; M[13]=-DotProd3fv(O,sY);
|
||||
M[2]=sZ[0]; M[6]=sZ[1]; M[10]=sZ[2]; M[14]=-DotProd3fv(O,sZ);
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
return(M);
|
||||
}
|
||||
|
||||
// ONLY TRANSLATES, ROTATES, AND SCALES ARE ALLOWED
|
||||
float XformCoordFrame16fv(
|
||||
const float *M, float X[3], float Y[3], float Z[3], float O[3])
|
||||
{
|
||||
Set3fv(X, X[0]*M[0] + X[1]*M[4] + X[2]*M[8],
|
||||
X[0]*M[1] + X[1]*M[5] + X[2]*M[9],
|
||||
X[0]*M[2] + X[1]*M[6] + X[2]*M[10] );
|
||||
Set3fv(Y, Y[0]*M[0] + Y[1]*M[4] + Y[2]*M[8],
|
||||
Y[0]*M[1] + Y[1]*M[5] + Y[2]*M[9],
|
||||
Y[0]*M[2] + Y[1]*M[6] + Y[2]*M[10] );
|
||||
Set3fv(Z, Z[0]*M[0] + Z[1]*M[4] + Z[2]*M[8],
|
||||
Z[0]*M[1] + Z[1]*M[5] + Z[2]*M[9],
|
||||
Z[0]*M[2] + Z[1]*M[6] + Z[2]*M[10] );
|
||||
Set3fv(O, O[0]*M[0] + O[1]*M[4] + O[2]*M[8] + M[12],
|
||||
O[0]*M[1] + O[1]*M[5] + O[2]*M[9] + M[13],
|
||||
O[0]*M[2] + O[1]*M[6] + O[2]*M[10] + M[14] );
|
||||
|
||||
// MUST RENORMALIZE AXES TO FIND THE UNIFORM SCALE
|
||||
float Scale = Length3fv(X);
|
||||
ScalarDiv3fv(X,Scale);
|
||||
ScalarDiv3fv(Y,Scale);
|
||||
ScalarDiv3fv(Z,Scale);
|
||||
|
||||
// RETURN UNIFORM SCALING OF AXES (how much coordinate frame was scaled)
|
||||
return(Scale);
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Given a complete definition for a particular view (viewing, projection,
|
||||
// and viewport), returns the COMPOSITE xform matrix that takes a point in the
|
||||
// world space to a screen space (pixel) point. The inverse is also provided.
|
||||
//----------------------------------------------------------------------------
|
||||
float* Screen2WorldXform16fv(
|
||||
float* M,
|
||||
const float X[3], const float Y[3], const float Z[3], // VIEWING AXES
|
||||
const float O[3], // VIEWING ORIGIN
|
||||
float l, float r, float b, float t, float n, float f, // PROJECTION
|
||||
int WW, int WH) // VIEWPORT
|
||||
{
|
||||
// C = InverseModelview * InverseProjection * InverseViewport
|
||||
float N[16];
|
||||
invViewing16fv(M,X,Y,Z,O);
|
||||
invFrustum16fv(N,l,r,b,t,n,f);
|
||||
Mult16fv(M,M,N); // M=M*N;
|
||||
invViewport16fv(N,WW,WH);
|
||||
Mult16fv(M,M,N); // M=M*N;
|
||||
return(M);
|
||||
}
|
||||
|
||||
float* World2ScreenXform16fv(
|
||||
float* M,
|
||||
const float X[3], const float Y[3], const float Z[3], // VIEWING AXES
|
||||
const float O[3], // VIEWING ORIGIN
|
||||
float l, float r, float b, float t, float n, float f, // PROJECTION
|
||||
int WW, int WH) // VIEWPORT
|
||||
{
|
||||
// C = Viewport * Projection * Modelview
|
||||
float N[16];
|
||||
Viewport16fv(M,WW,WH);
|
||||
Frustum16fv(N,l,r,b,t,n,f);
|
||||
Mult16fv(M,M,N); // M=M*N;
|
||||
Viewing16fv(N,X,Y,Z,O);
|
||||
Mult16fv(M,M,N); // M=M*N;
|
||||
return(M);
|
||||
}
|
||||
|
||||
void Print16fv(const float* M)
|
||||
{
|
||||
printf("\n%f %f %f %f\n",M[0],M[4],M[8],M[12]);
|
||||
printf("%f %f %f %f\n",M[1],M[5],M[9],M[13]);
|
||||
printf("%f %f %f %f\n",M[2],M[6],M[10],M[14]);
|
||||
printf("%f %f %f %f\n\n",M[3],M[7],M[11],M[15]);
|
||||
}
|
||||
|
||||
119
simgear/scene/sky/clouds3d/mat16fv.hpp
Normal file
119
simgear/scene/sky/clouds3d/mat16fv.hpp
Normal file
@@ -0,0 +1,119 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : mat16fv.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// mat16fv.hpp : opengl-style float[16] matrix routines.
|
||||
//----------------------------------------------------------------------------
|
||||
// $Id$
|
||||
//============================================================================
|
||||
|
||||
float* Copy16fv(float* A, const float* B); // A=B
|
||||
|
||||
float* Mult16fv(float* C, const float* A, const float* B); // C=A*B
|
||||
|
||||
float* Mult16fv3fv(
|
||||
float *NewV, const float* M, const float *V); // NewV = M * [Vx,Vy,Vz,0]
|
||||
|
||||
float* Mult16fv3fvPerspDiv(
|
||||
float *NewV, const float* M, const float *V); // NewV = M * [Vx,Vy,Vz,1]
|
||||
|
||||
float* Mult16fv4fv(
|
||||
float *NewV, const float* M, const float *V); // NewV = M * [Vx,Vy,Vz,Vw]
|
||||
|
||||
float* Identity16fv(float* M);
|
||||
float* Transpose16fv(float* M);
|
||||
|
||||
float* Rotate16fv(float *M, float DegAng, const float Axis[3]);
|
||||
float* invRotate16fv(float *M, float DegAng, const float Axis[3]);
|
||||
|
||||
float* Scale16fv(float* M, float sx, float sy, float sz);
|
||||
float* invScale16fv(float* M, float sx, float sy, float sz);
|
||||
|
||||
float* Translate16fv(float* M, float tx, float ty, float tz);
|
||||
float* invTranslate16fv(float* M, float tx, float ty, float tz);
|
||||
|
||||
float* LookAt(
|
||||
float* M,
|
||||
const float Eye[3],
|
||||
const float LookAtPt[3],
|
||||
const float ViewUp[3]);
|
||||
|
||||
float* invLookAt(
|
||||
float* M,
|
||||
const float Eye[3],
|
||||
const float LookAtPt[3],
|
||||
const float ViewUp[3]);
|
||||
|
||||
float* Frustum16fv(
|
||||
float* M, float l, float r, float b, float t, float n, float f);
|
||||
|
||||
float* invFrustum16fv(
|
||||
float* M, float l, float r, float b, float t, float n, float f);
|
||||
|
||||
float* Perspective(
|
||||
float* M, float Yfov, float Aspect, float Ndist, float Fdist);
|
||||
|
||||
float* invPerspective(
|
||||
float* M, float Yfov, float Aspect, float Ndist, float Fdist);
|
||||
|
||||
float* Viewing16fv(
|
||||
float* M,
|
||||
const float X[3], const float Y[3], const float Z[3],
|
||||
const float O[3]);
|
||||
|
||||
float* invViewing16fv(
|
||||
float* M,
|
||||
const float X[3], const float Y[3], const float Z[3],
|
||||
const float O[3]);
|
||||
|
||||
void Viewing2CoordFrame16fv(
|
||||
const float *M, float X[3], float Y[3], float Z[3], float O[3]);
|
||||
|
||||
|
||||
float* Viewport16fv(float* M, int WW, int WH);
|
||||
|
||||
float* invViewport16fv(float* M, int WW, int WH);
|
||||
|
||||
float* PlanarReflection16fv(float M[16], const float P[4]);
|
||||
|
||||
float XformCoordFrame16fv(
|
||||
const float *M, float X[3], float Y[3], float Z[3], float O[3]);
|
||||
|
||||
float* Obj2WorldXform16fv(
|
||||
float *M, float X[3], float Y[3], float Z[3], float O[3], float Scale);
|
||||
|
||||
float* World2ObjXform16fv(
|
||||
float *M,
|
||||
const float X[3],
|
||||
const float Y[3],
|
||||
const float Z[3],
|
||||
const float O[3],
|
||||
float Scale);
|
||||
|
||||
float* Screen2WorldXform16fv(
|
||||
float* M,
|
||||
const float X[3], const float Y[3], const float Z[3], const float O[3],
|
||||
float l, float r, float b, float t, float n, float f,
|
||||
int WW, int WH);
|
||||
|
||||
float* World2ScreenXform16fv(
|
||||
float* M,
|
||||
const float X[3], const float Y[3], const float Z[3], const float O[3],
|
||||
float l, float r, float b, float t, float n, float f,
|
||||
int WW, int WH);
|
||||
|
||||
void Print16fv(const float* M);
|
||||
113
simgear/scene/sky/clouds3d/mat33.hpp
Normal file
113
simgear/scene/sky/clouds3d/mat33.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : mat33.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// mat33.hpp : 3x3 matrix template.
|
||||
//============================================================================
|
||||
|
||||
#ifndef _MAT33_
|
||||
#define _MAT33_
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include "mat44.hpp"
|
||||
|
||||
static const float Mat33TORADS = 0.0174532f;
|
||||
static const float Mat33VIEWPORT_TOL = 0.001f;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// M[9] = [ 0 3 6 ]
|
||||
// [ 1 4 7 ]
|
||||
// [ 2 5 8 ]
|
||||
//
|
||||
//
|
||||
//
|
||||
// [ x' y' z' ] = [ 0 3 6 ] [ x ]
|
||||
// [ 1 4 7 ] * [ y ]
|
||||
// [ 2 5 8 ] [ z ]
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
class Mat33
|
||||
{
|
||||
public:
|
||||
Type M[9]; // 0,1,2 = 1st col; 3,4,5 = 2nd col; etc.
|
||||
|
||||
Mat33();
|
||||
Mat33(const Type *N);
|
||||
Mat33(Type M0, Type M3, Type M6,
|
||||
Type M1, Type M4, Type M7,
|
||||
Type M2, Type M5, Type M8);
|
||||
Mat33<Type>& operator = (const Mat33& A); // ASSIGNMENT (=)
|
||||
// ASSIGNMENT (=) FROM AN ARRAY OF Type
|
||||
Mat33<Type>& operator = (const Type* a);
|
||||
Mat33<Type> operator * (const Mat33& A) const; // MULTIPLICATION (*)
|
||||
// MAT-VECTOR MULTIPLICATION (*)
|
||||
Vec3<Type> operator * (const Vec3<Type>& V) const;
|
||||
// MAT-VECTOR PRE-MULTIPLICATON (*)
|
||||
friend Vec3<Type> operator * (const Vec3<Type>& V, const Mat33<Type>& M);
|
||||
// SCALAR POST-MULTIPLICATION
|
||||
Mat33<Type> operator * (Type a) const;
|
||||
// SCALAR PRE-MULTIPLICATION
|
||||
friend Mat33<Type> operator * (Type a, const Mat44<Type>& M);
|
||||
|
||||
Mat33<Type> operator / (Type a) const; // SCALAR DIVISION
|
||||
Mat33<Type> operator + (Mat33& M) const; // ADDITION (+)
|
||||
Mat33<Type>& operator += (Mat33& M); // ACCUMULATE ADD (+=)
|
||||
Mat33<Type>& operator -= (Mat33& M); // ACCUMULATE SUB (-=)
|
||||
Mat33<Type>& operator *= (Type a); // ACCUMULATE MULTIPLY (*=)
|
||||
Mat33<Type>& operator /= (Type a); // ACCUMULATE DIVIDE (/=)
|
||||
|
||||
bool Inverse(Mat33<Type> &inv, Type tolerance) const;// MATRIX INVERSE
|
||||
|
||||
operator const Type*() const; // CAST TO A Type ARRAY
|
||||
operator Type*(); // CAST TO A Type ARRAY
|
||||
|
||||
void RowMajor(Type m[9]); // return array in row-major order
|
||||
|
||||
Type& operator()(int col, int row); // 2D ARRAY ACCESSOR
|
||||
const Type& operator()(int col, int row) const; // 2D ARRAY ACCESSOR
|
||||
void Set(const Type* a); // SAME AS ASSIGNMENT (=) FROM AN ARRAY OF TypeS
|
||||
void Set(Type M0, Type M3, Type M6,
|
||||
Type M1, Type M4, Type M7,
|
||||
Type M2, Type M5, Type M8);
|
||||
|
||||
void Identity();
|
||||
void Zero();
|
||||
void Transpose();
|
||||
void Scale(Type Sx, Type Sy, Type Sz);
|
||||
void Scale(const Vec3<Type>& S);
|
||||
void invScale(Type Sx, Type Sy, Type Sz);
|
||||
void invScale(const Vec3<Type>& S);
|
||||
void Rotate(Type DegAng, const Vec3<Type>& Axis);
|
||||
void invRotate(Type DegAng, const Vec3<Type>& Axis);
|
||||
void Star(const Vec3<Type>& v); // SKEW-SYMM MATRIX EQUIV TO CROSS PROD WITH V
|
||||
void OuterProduct(const Vec3<Type>& u, const Vec3<Type>& v); // SET TO u * v^t
|
||||
Type Trace() const;
|
||||
void Print() const;
|
||||
void CopyInto(Type *Mat) const;
|
||||
static void SWAP(Type& a, Type& b) {Type t; t=a;a=b;b=t;}
|
||||
};
|
||||
|
||||
#include "mat33impl.hpp"
|
||||
|
||||
typedef Mat33<float> Mat33f;
|
||||
typedef Mat33<double> Mat33d;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
412
simgear/scene/sky/clouds3d/mat33impl.hpp
Normal file
412
simgear/scene/sky/clouds3d/mat33impl.hpp
Normal file
@@ -0,0 +1,412 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : mat33impl.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// mat33impl.hpp : 3x3 matrix template.
|
||||
// This is the template implementation file. It is included by mat33.hpp.
|
||||
//============================================================================
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// CONSTRUCTORS
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
Mat33<Type>::Mat33()
|
||||
{
|
||||
Identity();
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat33<Type>::Mat33(const Type *N)
|
||||
{
|
||||
M[0]=N[0]; M[3]=N[3]; M[6]=N[6];
|
||||
M[1]=N[1]; M[4]=N[4]; M[7]=N[7];
|
||||
M[2]=N[2]; M[5]=N[5]; M[8]=N[8];
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat33<Type>::Mat33(Type M0, Type M3, Type M6,
|
||||
Type M1, Type M4, Type M7,
|
||||
Type M2, Type M5, Type M8)
|
||||
|
||||
{
|
||||
M[0]=M0; M[3]=M3; M[6]=M6;
|
||||
M[1]=M1; M[4]=M4; M[7]=M7;
|
||||
M[2]=M2; M[5]=M5; M[8]=M8;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// MATRIX/MATRIX AND MATRIX/VECTOR OPERATORS
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
Mat33<Type>& Mat33<Type>::operator = (const Mat33& A) // ASSIGNMENT (=)
|
||||
{
|
||||
M[0]=A.M[0]; M[3]=A.M[3]; M[6]=A.M[6];
|
||||
M[1]=A.M[1]; M[4]=A.M[4]; M[7]=A.M[7];
|
||||
M[2]=A.M[2]; M[5]=A.M[5]; M[8]=A.M[8];
|
||||
return(*this);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat33<Type>& Mat33<Type>::operator = (const Type* a) {
|
||||
for (int i=0;i<9;i++) {
|
||||
M[i] = a[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat33<Type> Mat33<Type>::operator * (const Mat33& A) const // MULTIPLICATION (*)
|
||||
{
|
||||
Mat33<Type> NewM(
|
||||
M[0]*A.M[0] + M[3]*A.M[1] + M[6]*A.M[2], // ROW 1
|
||||
M[0]*A.M[3] + M[3]*A.M[4] + M[6]*A.M[5],
|
||||
M[0]*A.M[6] + M[3]*A.M[7] + M[6]*A.M[8],
|
||||
|
||||
M[1]*A.M[0] + M[4]*A.M[1] + M[7]*A.M[2], // ROW 2
|
||||
M[1]*A.M[3] + M[4]*A.M[4] + M[7]*A.M[5],
|
||||
M[1]*A.M[6] + M[4]*A.M[7] + M[7]*A.M[8],
|
||||
|
||||
M[2]*A.M[0] + M[5]*A.M[1] + M[8]*A.M[2], // ROW 3
|
||||
M[2]*A.M[3] + M[5]*A.M[4] + M[8]*A.M[5],
|
||||
M[2]*A.M[6] + M[5]*A.M[7] + M[8]*A.M[8]);
|
||||
return(NewM);
|
||||
}
|
||||
|
||||
// MAT-VECTOR MULTIPLICATION (*)
|
||||
template<class Type>
|
||||
Vec3<Type> Mat33<Type>::operator * (const Vec3<Type>& V) const
|
||||
{
|
||||
Vec3<Type> NewV;
|
||||
NewV.x = M[0]*V.x + M[3]*V.y + M[6]*V.z;
|
||||
NewV.y = M[1]*V.x + M[4]*V.y + M[7]*V.z;
|
||||
NewV.z = M[2]*V.x + M[5]*V.y + M[8]*V.z;
|
||||
return(NewV);
|
||||
}
|
||||
|
||||
// MAT-VECTOR PRE-MULTIPLICATON (*) (non-member)
|
||||
// interpreted as V^t M
|
||||
template<class Type>
|
||||
Vec3<Type> operator *(const Vec3<Type>& V, const Mat33<Type>& A)
|
||||
{
|
||||
Vec3<Type> NewV;
|
||||
NewV.x = A[0]*V.x + A[1]*V.y + A[2]*V.z;
|
||||
NewV.y = A[3]*V.x + A[4]*V.y + A[5]*V.z;
|
||||
NewV.z = A[6]*V.x + A[7]*V.y + A[8]*V.z;
|
||||
return(NewV);
|
||||
}
|
||||
|
||||
// SCALAR POST-MULTIPLICATION
|
||||
template<class Type>
|
||||
Mat33<Type> Mat33<Type>::operator * (Type a) const
|
||||
{
|
||||
Mat33<Type> NewM;
|
||||
for (int i = 0; i < 9; i++)
|
||||
NewM[i] = M[i]*a;
|
||||
return(NewM);
|
||||
}
|
||||
|
||||
// SCALAR PRE-MULTIPLICATION (non-member)
|
||||
template <class Type>
|
||||
Mat33<Type> operator * (Type a, const Mat44<Type>& M)
|
||||
{
|
||||
Mat33<Type> NewM;
|
||||
for (int i = 0; i < 9; i++)
|
||||
NewM[i] = a*M[i];
|
||||
return(NewM);
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Mat33<Type> Mat33<Type>::operator / (Type a) const // SCALAR DIVISION
|
||||
{
|
||||
Mat33<Type> NewM;
|
||||
Type ainv = Type(1.0)/a;
|
||||
for (int i = 0; i < 9; i++)
|
||||
NewM[i] = M[i]*ainv;
|
||||
return(NewM);
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Mat33<Type> Mat33<Type>::operator + (Mat33& N) const // ADDITION (+)
|
||||
{
|
||||
Mat33<Type> NewM;
|
||||
for (int i = 0; i < 9; i++)
|
||||
NewM[i] = M[i]+N.M[i];
|
||||
return(NewM);
|
||||
}
|
||||
template <class Type>
|
||||
Mat33<Type>& Mat33<Type>::operator += (Mat33& N) // ACCUMULATE ADD (+=)
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
M[i] += N.M[i];
|
||||
return(*this);
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Mat33<Type>& Mat33<Type>::operator -= (Mat33& N) // ACCUMULATE SUB (-=)
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
M[i] -= N.M[i];
|
||||
return(*this);
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Mat33<Type>& Mat33<Type>::operator *= (Type a) // ACCUMULATE MULTIPLY (*=)
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
M[i] *= a;
|
||||
return(*this);
|
||||
}
|
||||
template <class Type>
|
||||
Mat33<Type>& Mat33<Type>::operator /= (Type a) // ACCUMULATE DIVIDE (/=)
|
||||
{
|
||||
Type ainv = Type(1.0)/a;
|
||||
for (int i = 0; i < 9; i++)
|
||||
M[i] *= ainv;
|
||||
return(*this);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
bool Mat33<Type>::Inverse(Mat33<Type> &inv, Type tolerance) const // MATRIX INVERSE
|
||||
{
|
||||
// Invert using cofactors.
|
||||
|
||||
inv[0] = M[4]*M[8] - M[7]*M[5];
|
||||
inv[3] = M[6]*M[5] - M[3]*M[8];
|
||||
inv[6] = M[3]*M[7] - M[6]*M[4];
|
||||
inv[1] = M[7]*M[2] - M[1]*M[8];
|
||||
inv[4] = M[0]*M[8] - M[6]*M[2];
|
||||
inv[7] = M[6]*M[1] - M[0]*M[7];
|
||||
inv[2] = M[1]*M[5] - M[4]*M[2];
|
||||
inv[5] = M[3]*M[2] - M[0]*M[5];
|
||||
inv[8] = M[0]*M[4] - M[3]*M[1];
|
||||
|
||||
Type det = M[0]*inv[0] + M[3]*inv[1] + M[6]*inv[2];
|
||||
|
||||
if (fabs(det) <= tolerance) // singular
|
||||
return false;
|
||||
|
||||
Type invDet = 1.0f / det;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
inv[i] *= invDet;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat33<Type>::operator const Type*() const
|
||||
{
|
||||
return M;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat33<Type>::operator Type*()
|
||||
{
|
||||
return M;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::RowMajor(Type m[9])
|
||||
{
|
||||
m[0] = M[0]; m[1] = M[3]; m[2] = M[6];
|
||||
m[3] = M[1]; m[4] = M[4]; m[5] = M[7];
|
||||
m[6] = M[2]; m[7] = M[5]; m[8] = M[8];
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Type& Mat33<Type>::operator()(int col, int row)
|
||||
{
|
||||
return M[3*col+row];
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
const Type& Mat33<Type>::operator()(int col, int row) const
|
||||
{
|
||||
return M[3*col+row];
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::Set(const Type* a)
|
||||
{
|
||||
for (int i=0;i<9;i++) {
|
||||
M[i] = a[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::Set(Type M0, Type M3, Type M6,
|
||||
Type M1, Type M4, Type M7,
|
||||
Type M2, Type M5, Type M8)
|
||||
{
|
||||
M[0]=M0; M[3]=M3; M[6]=M6;
|
||||
M[1]=M1; M[4]=M4; M[7]=M7;
|
||||
M[2]=M2; M[5]=M5; M[8]=M8;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Standard Matrix Operations
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat33<Type>::Identity()
|
||||
{
|
||||
M[0]=M[4]=M[8]=1;
|
||||
M[1]=M[2]=M[3]=M[5]=M[6]=M[7]=0;
|
||||
}
|
||||
template<class Type>
|
||||
void Mat33<Type>::Zero()
|
||||
{
|
||||
M[0]=M[1]=M[2]=M[3]=M[4]=M[5]=M[6]=M[7]=M[8]=0;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::Transpose()
|
||||
{
|
||||
SWAP(M[1],M[3]);
|
||||
SWAP(M[2],M[6]);
|
||||
SWAP(M[5],M[7]);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Standard Matrix Affine Transformations
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat33<Type>::Scale(Type Sx, Type Sy, Type Sz)
|
||||
{
|
||||
M[0]=Sx; M[3]=0; M[6]=0;
|
||||
M[1]=0; M[4]=Sy; M[7]=0;
|
||||
M[2]=0; M[5]=0; M[8]=Sz;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::Scale(const Vec3<Type>& S)
|
||||
{
|
||||
M[0]=S.x; M[3]=0; M[6]=0;
|
||||
M[1]=0; M[4]=S.y; M[7]=0;
|
||||
M[2]=0; M[5]=0; M[8]=S.z;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::invScale(Type Sx, Type Sy, Type Sz)
|
||||
{
|
||||
M[0]=1/Sx; M[3]=0; M[6]=0;
|
||||
M[1]=0; M[4]=1/Sy; M[7]=0;
|
||||
M[2]=0; M[5]=0; M[8]=1/Sz;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::invScale(const Vec3<Type>& S)
|
||||
{
|
||||
M[0]=1/S.x; M[3]=0; M[6]=0;
|
||||
M[1]=0; M[4]=1/S.y; M[7]=0;
|
||||
M[2]=0; M[5]=0; M[8]=1/S.z;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::Rotate(Type DegAng, const Vec3<Type>& Axis)
|
||||
{
|
||||
Type RadAng = DegAng*Mat33TORADS;
|
||||
Type ca=(Type)cos(RadAng),
|
||||
sa=(Type)sin(RadAng);
|
||||
if (Axis.x==1 && Axis.y==0 && Axis.z==0) // ABOUT X-AXIS
|
||||
{
|
||||
M[0]=1; M[3]=0; M[6]=0;
|
||||
M[1]=0; M[4]=ca; M[7]=-sa;
|
||||
M[2]=0; M[5]=sa; M[8]=ca;
|
||||
|
||||
}
|
||||
else if (Axis.x==0 && Axis.y==1 && Axis.z==0) // ABOUT Y-AXIS
|
||||
{
|
||||
M[0]=ca; M[3]=0; M[6]=sa;
|
||||
M[1]=0; M[4]=1; M[7]=0;
|
||||
M[2]=-sa; M[5]=0; M[8]=ca;
|
||||
}
|
||||
else if (Axis.x==0 && Axis.y==0 && Axis.z==1) // ABOUT Z-AXIS
|
||||
{
|
||||
M[0]=ca; M[3]=-sa; M[6]=0;
|
||||
M[1]=sa; M[4]=ca; M[7]=0;
|
||||
M[2]=0; M[5]=0; M[8]=1;
|
||||
}
|
||||
else // ARBITRARY AXIS
|
||||
{
|
||||
Type l = Axis.LengthSqr();
|
||||
Type x, y, z;
|
||||
x=Axis.x, y=Axis.y, z=Axis.z;
|
||||
if (l > Type(1.0001) || l < Type(0.9999) && l!=0)
|
||||
{
|
||||
// needs normalization
|
||||
l=Type(1.0)/sqrt(l);
|
||||
x*=l; y*=l; z*=l;
|
||||
}
|
||||
Type x2=x*x, y2=y*y, z2=z*z;
|
||||
M[0]=x2+ca*(1-x2); M[3]=(x*y)+ca*(-x*y)+sa*(-z); M[6]=(x*z)+ca*(-x*z)+sa*y;
|
||||
M[1]=(x*y)+ca*(-x*y)+sa*z; M[4]=y2+ca*(1-y2); M[7]=(y*z)+ca*(-y*z)+sa*(-x);
|
||||
M[2]=(x*z)+ca*(-x*z)+sa*(-y); M[5]=(y*z)+ca*(-y*z)+sa*x; M[8]=z2+ca*(1-z2);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat33<Type>::invRotate(Type DegAng, const Vec3<Type>& Axis)
|
||||
{
|
||||
Rotate(DegAng,Axis);
|
||||
Transpose();
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
inline void Mat33<Type>::Star(const Vec3<Type>& v)
|
||||
{
|
||||
M[0]= 0; M[3]=-v.z; M[6]= v.y;
|
||||
M[1]= v.z; M[4]= 0; M[7]=-v.x;
|
||||
M[2]=-v.y; M[5]= v.x; M[8]= 0;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
inline void Mat33<Type>::OuterProduct(const Vec3<Type>& u, const Vec3<Type>& v)
|
||||
{
|
||||
M[0]=u.x*v.x; M[3]=u.x*v.y; M[6]=u.x*v.z;
|
||||
M[1]=u.y*v.x; M[4]=u.y*v.y; M[7]=u.y*v.z;
|
||||
M[2]=u.z*v.x; M[5]=u.z*v.y; M[8]=u.z*v.z;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
inline Type Mat33<Type>::Trace() const
|
||||
{
|
||||
return M[0] + M[4] + M[8];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Handy matrix printing routine.
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat33<Type>::Print() const
|
||||
{
|
||||
printf("\n%f %f %f\n",M[0],M[3],M[6]);
|
||||
printf("%f %f %f\n",M[1],M[4],M[7]);
|
||||
printf("%f %f %f\n",M[2],M[5],M[8]);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Copy contents of matrix into matrix array.
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat33<Type>::CopyInto(Type *Mat) const
|
||||
{
|
||||
Mat[0]=M[0]; Mat[3]=M[3]; Mat[6]=M[6];
|
||||
Mat[1]=M[1]; Mat[4]=M[4]; Mat[7]=M[7];
|
||||
Mat[2]=M[2]; Mat[5]=M[5]; Mat[8]=M[8];
|
||||
}
|
||||
|
||||
135
simgear/scene/sky/clouds3d/mat44.hpp
Normal file
135
simgear/scene/sky/clouds3d/mat44.hpp
Normal file
@@ -0,0 +1,135 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : mat44.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// mat44.hpp : 4x4 OpenGL-style matrix template.
|
||||
//============================================================================
|
||||
|
||||
#ifndef _MAT44_
|
||||
#define _MAT44_
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include "vec4f.hpp"
|
||||
|
||||
static const float Mat44TORADS = 0.0174532f;
|
||||
static const float Mat44VIEWPORT_TOL = 0.001f;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// M[16] = [ 0 4 8 12 ] | 16 floats were used instead of the normal [4][4]
|
||||
// [ 1 5 9 13 ] | to be compliant with OpenGL. OpenGL uses
|
||||
// [ 2 6 10 14 ] | premultiplication with column vectors. These
|
||||
// [ 3 7 11 15 ] | matrices can be fed directly into the OpenGL
|
||||
// | matrix stack with glLoadMatrix or glMultMatrix.
|
||||
//
|
||||
// [ x' y' z' w' ] = [ 0 4 8 12 ] [ x ]
|
||||
// [ 1 5 9 13 ] * [ y ]
|
||||
// [ 2 6 10 14 ] [ z ]
|
||||
// [ 3 7 11 15 ] [ w ]
|
||||
//
|
||||
// Loading a [4][4] format matrix directly into the matrix stack (assuming
|
||||
// premult/col vecs) results in a transpose matrix. M[0]=M[0][0], but
|
||||
// M[1]!=M[1][0] since M[0][1] would cast to M[1].
|
||||
//
|
||||
// However, if we assumed postmult/row vectors we could use [4][4] format,
|
||||
// but all transformations in this module would be transposed.
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
class Mat44
|
||||
{
|
||||
public:
|
||||
Type M[16]; // 0,1,2,3 = 1st col; 4,5,6,7 = 2nd col; etc.
|
||||
|
||||
Mat44();
|
||||
Mat44(const Type *N);
|
||||
Mat44(Type M0, Type M4, Type M8, Type M12,
|
||||
Type M1, Type M5, Type M9, Type M13,
|
||||
Type M2, Type M6, Type M10, Type M14,
|
||||
Type M3, Type M7, Type M11, Type M15);
|
||||
Mat44<Type>& operator = (const Mat44& A); // ASSIGNMENT (=)
|
||||
Mat44<Type>& operator = (const Type* a); // ASSIGNMENT (=) FROM AN ARRAY OF TypeS
|
||||
Mat44<Type> operator * (const Mat44& A) const; // MULTIPLICATION (*)
|
||||
Vec3<Type> operator * (const Vec3<Type>& V) const; // MAT-VECTOR MULTIPLICATION (*) W/ PERSP DIV
|
||||
Vec3<Type> multNormal(const Vec3<Type>& V) const; // MAT-VECTOR MULTIPLICATION _WITHOUT_ PERSP DIV
|
||||
Vec3<Type> multPoint(const Vec3<Type>& V) const; // MAT-POINT MULTIPLICATION _WITHOUT_ PERSP DIV
|
||||
Vec4<Type> operator * (const Vec4<Type>& V) const; // MAT-VECTOR MULTIPLICATION (*)
|
||||
Mat44<Type> operator * (Type a) const; // SCALAR POST-MULTIPLICATION
|
||||
Mat44<Type>& operator *= (Type a); // ACCUMULATE MULTIPLY (*=)
|
||||
////////////// NOT IMPLEMENTED YET. ANY TAKERS?
|
||||
// friend Vec3<Type> operator * (const Vec3<Type>& V, const Mat44& M); // MAT-VECTOR PRE-MULTIPLICATON (*) W/ PERP DIV
|
||||
// friend Vec4<Type> operator * (const Vec4<Type>& V, const Mat44& M); // MAT-VECTOR PRE-MULTIPLICATON (*)
|
||||
// friend Mat44<Type> operator * (Type a, const Mat44& M) const; // SCALAR PRE-MULTIPLICATION
|
||||
// Mat44<Type> operator / (Type a) const; // SCALAR DIVISION
|
||||
// Mat44<Type> operator + (Mat44& M) const; // ADDITION (+)
|
||||
// Mat44<Type>& operator += (Mat44& M); // ACCUMULATE ADD (+=)
|
||||
// Mat44<Type>& operator /= (Type a); // ACCUMULATE DIVIDE (/=)
|
||||
// bool Invserse(); // MATRIX INVERSE
|
||||
////////////// NOT IMPLEMENTED YET. ANY TAKERS?
|
||||
|
||||
operator const Type*() const; // CAST TO A Type ARRAY
|
||||
operator Type*(); // CAST TO A Type ARRAY
|
||||
Type& operator()(int col, int row); // 2D ARRAY ACCESSOR
|
||||
const Type& operator()(int col, int row) const; // 2D ARRAY ACCESSOR
|
||||
void Set(const Type* a); // SAME AS ASSIGNMENT (=) FROM AN ARRAY OF TypeS
|
||||
void Set(Type M0, Type M4, Type M8, Type M12,
|
||||
Type M1, Type M5, Type M9, Type M13,
|
||||
Type M2, Type M6, Type M10, Type M14,
|
||||
Type M3, Type M7, Type M11, Type M15);
|
||||
|
||||
|
||||
void Identity();
|
||||
void Transpose();
|
||||
void Translate(Type Tx, Type Ty, Type Tz);
|
||||
void Translate(const Vec3<Type>& T);
|
||||
void invTranslate(Type Tx, Type Ty, Type Tz);
|
||||
void invTranslate(const Vec3<Type>& T);
|
||||
void Scale(Type Sx, Type Sy, Type Sz);
|
||||
void Scale(const Vec3<Type>& S);
|
||||
void invScale(Type Sx, Type Sy, Type Sz);
|
||||
void invScale(const Vec3<Type>& S);
|
||||
void Rotate(Type DegAng, const Vec3<Type>& Axis);
|
||||
void invRotate(Type DegAng, const Vec3<Type>& Axis);
|
||||
Type Trace(void) const;
|
||||
void Frustum(Type l, Type r, Type b, Type t, Type n, Type f);
|
||||
void invFrustum(Type l, Type r, Type b, Type t, Type n, Type f);
|
||||
void Perspective(Type Yfov, Type Aspect, Type Ndist, Type Fdist);
|
||||
void invPerspective(Type Yfov, Type Aspect, Type Ndist, Type Fdist);
|
||||
void Viewport(int WW, int WH);
|
||||
void invViewport(int WW, int WH);
|
||||
void LookAt(const Vec3<Type>& Eye,
|
||||
const Vec3<Type>& LookAtPt,
|
||||
const Vec3<Type>& ViewUp);
|
||||
void invLookAt(const Vec3<Type>& Eye,
|
||||
const Vec3<Type>& LookAtPt,
|
||||
const Vec3<Type>& ViewUp);
|
||||
void Viewport2(int WW, int WH);
|
||||
void invViewport2(int WW, int WH);
|
||||
void Print() const;
|
||||
void CopyInto(Type *Mat) const;
|
||||
|
||||
static void SWAP(Type& a, Type& b) {Type t; t=a;a=b;b=t;}
|
||||
};
|
||||
|
||||
#include "mat44impl.hpp"
|
||||
|
||||
typedef Mat44<float> Mat44f;
|
||||
typedef Mat44<double> Mat44d;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
536
simgear/scene/sky/clouds3d/mat44impl.hpp
Normal file
536
simgear/scene/sky/clouds3d/mat44impl.hpp
Normal file
@@ -0,0 +1,536 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : mat44impl.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// mat44.hpp : 4x4 OpenGL-style matrix template.
|
||||
// This is the template implementation file. It is included by mat44.hpp.
|
||||
//============================================================================
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// CONSTRUCTORS
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
Mat44<Type>::Mat44()
|
||||
{
|
||||
Identity();
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat44<Type>::Mat44(const Type *N)
|
||||
{
|
||||
M[0]=N[0]; M[4]=N[4]; M[8]=N[8]; M[12]=N[12];
|
||||
M[1]=N[1]; M[5]=N[5]; M[9]=N[9]; M[13]=N[13];
|
||||
M[2]=N[2]; M[6]=N[6]; M[10]=N[10]; M[14]=N[14];
|
||||
M[3]=N[3]; M[7]=N[7]; M[11]=N[11]; M[15]=N[15];
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat44<Type>::Mat44(Type M0, Type M4, Type M8, Type M12,
|
||||
Type M1, Type M5, Type M9, Type M13,
|
||||
Type M2, Type M6, Type M10, Type M14,
|
||||
Type M3, Type M7, Type M11, Type M15)
|
||||
{
|
||||
M[0]=M0; M[4]=M4; M[8]=M8; M[12]=M12;
|
||||
M[1]=M1; M[5]=M5; M[9]=M9; M[13]=M13;
|
||||
M[2]=M2; M[6]=M6; M[10]=M10; M[14]=M14;
|
||||
M[3]=M3; M[7]=M7; M[11]=M11; M[15]=M15;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// MATRIX/MATRIX AND MATRIX/VECTOR OPERATORS
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
Mat44<Type>& Mat44<Type>::operator = (const Mat44& A) // ASSIGNMENT (=)
|
||||
{
|
||||
M[0]=A.M[0]; M[4]=A.M[4]; M[8]=A.M[8]; M[12]=A.M[12];
|
||||
M[1]=A.M[1]; M[5]=A.M[5]; M[9]=A.M[9]; M[13]=A.M[13];
|
||||
M[2]=A.M[2]; M[6]=A.M[6]; M[10]=A.M[10]; M[14]=A.M[14];
|
||||
M[3]=A.M[3]; M[7]=A.M[7]; M[11]=A.M[11]; M[15]=A.M[15];
|
||||
return(*this);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat44<Type>& Mat44<Type>::operator = (const Type* a) {
|
||||
for (int i=0;i<16;i++) {
|
||||
M[i] = a[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat44<Type> Mat44<Type>::operator * (const Mat44& A) const // MULTIPLICATION (*)
|
||||
{
|
||||
Mat44<Type> NewM( M[0]*A.M[0] + M[4]*A.M[1] + M[8]*A.M[2] + M[12]*A.M[3], // ROW 1
|
||||
M[0]*A.M[4] + M[4]*A.M[5] + M[8]*A.M[6] + M[12]*A.M[7],
|
||||
M[0]*A.M[8] + M[4]*A.M[9] + M[8]*A.M[10] + M[12]*A.M[11],
|
||||
M[0]*A.M[12] + M[4]*A.M[13] + M[8]*A.M[14] + M[12]*A.M[15],
|
||||
|
||||
M[1]*A.M[0] + M[5]*A.M[1] + M[9]*A.M[2] + M[13]*A.M[3], // ROW 2
|
||||
M[1]*A.M[4] + M[5]*A.M[5] + M[9]*A.M[6] + M[13]*A.M[7],
|
||||
M[1]*A.M[8] + M[5]*A.M[9] + M[9]*A.M[10] + M[13]*A.M[11],
|
||||
M[1]*A.M[12] + M[5]*A.M[13] + M[9]*A.M[14] + M[13]*A.M[15],
|
||||
|
||||
M[2]*A.M[0] + M[6]*A.M[1] + M[10]*A.M[2] + M[14]*A.M[3], // ROW 3
|
||||
M[2]*A.M[4] + M[6]*A.M[5] + M[10]*A.M[6] + M[14]*A.M[7],
|
||||
M[2]*A.M[8] + M[6]*A.M[9] + M[10]*A.M[10] + M[14]*A.M[11],
|
||||
M[2]*A.M[12] + M[6]*A.M[13] + M[10]*A.M[14] + M[14]*A.M[15],
|
||||
|
||||
M[3]*A.M[0] + M[7]*A.M[1] + M[11]*A.M[2] + M[15]*A.M[3], // ROW 4
|
||||
M[3]*A.M[4] + M[7]*A.M[5] + M[11]*A.M[6] + M[15]*A.M[7],
|
||||
M[3]*A.M[8] + M[7]*A.M[9] + M[11]*A.M[10] + M[15]*A.M[11],
|
||||
M[3]*A.M[12] + M[7]*A.M[13] + M[11]*A.M[14] + M[15]*A.M[15] );
|
||||
return(NewM);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Vec3<Type> Mat44<Type>::operator * (const Vec3<Type>& V) const // MAT-VECTOR MULTIPLICATION (*) W/ PERSP DIV
|
||||
{
|
||||
Type W = M[3]*V.x + M[7]*V.y + M[11]*V.z + M[15];
|
||||
Vec3<Type> NewV( (M[0]*V.x + M[4]*V.y + M[8]*V.z + M[12]) / W,
|
||||
(M[1]*V.x + M[5]*V.y + M[9]*V.z + M[13]) / W,
|
||||
(M[2]*V.x + M[6]*V.y + M[10]*V.z + M[14]) / W );
|
||||
return(NewV);
|
||||
}
|
||||
|
||||
|
||||
// MAT-VECTOR MULTIPLICATION _WITHOUT_ PERSP DIV
|
||||
// For transforming normals or other pure vectors.
|
||||
// Assumes matrix is affine, i.e. bottom row is 0,0,0,1
|
||||
template<class Type>
|
||||
Vec3<Type> Mat44<Type>::multNormal(const Vec3<Type>& N) const
|
||||
{
|
||||
Vec3<Type> NewN( (M[0]*N.x + M[4]*N.y + M[8]*N.z ),
|
||||
(M[1]*N.x + M[5]*N.y + M[9]*N.z ),
|
||||
(M[2]*N.x + M[6]*N.y + M[10]*N.z) );
|
||||
return (NewN);
|
||||
}
|
||||
|
||||
// MAT-POINT MULTIPLICATION _WITHOUT_ PERSP DIV
|
||||
// (for transforming points in space)
|
||||
// Assumes matrix is affine, i.e. bottom row is 0,0,0,1
|
||||
template<class Type>
|
||||
Vec3<Type> Mat44<Type>::multPoint(const Vec3<Type>& P) const
|
||||
{
|
||||
Vec3<Type> NewP( (M[0]*P.x + M[4]*P.y + M[8]*P.z + M[12]),
|
||||
(M[1]*P.x + M[5]*P.y + M[9]*P.z + M[13]),
|
||||
(M[2]*P.x + M[6]*P.y + M[10]*P.z + M[14]) );
|
||||
return (NewP);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Vec4<Type> Mat44<Type>::operator * (const Vec4<Type>& V) const // MAT-VECTOR MULTIPLICATION (*)
|
||||
{
|
||||
Vec4<Type> NewV;
|
||||
NewV.x = M[0]*V.x + M[4]*V.y + M[8]*V.z + M[12]*V.w;
|
||||
NewV.y = M[1]*V.x + M[5]*V.y + M[9]*V.z + M[13]*V.w;
|
||||
NewV.z = M[2]*V.x + M[6]*V.y + M[10]*V.z + M[14]*V.w;
|
||||
NewV.w = M[3]*V.x + M[7]*V.y + M[11]*V.z + M[15]*V.w;
|
||||
return(NewV);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Mat44<Type> Mat44<Type>::operator * (Type a) const // SCALAR POST-MULTIPLICATION
|
||||
{
|
||||
Mat44<Type> NewM( M[0] * a, M[1] * a, M[2] * a, M[3] * a,
|
||||
M[4] * a, M[5] * a, M[6] * a, M[7] * a,
|
||||
M[8] * a, M[9] * a, M[10] * a, M[11] * a,
|
||||
M[12] * a, M[13] * a, M[14] * a, M[15] * a);
|
||||
return NewM;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat44<Type>& Mat44<Type>::operator *= (Type a) // SCALAR ACCUMULATE POST-MULTIPLICATION
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
M[i] *= a;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat44<Type>::operator const Type*() const
|
||||
{
|
||||
return M;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Mat44<Type>::operator Type*()
|
||||
{
|
||||
return M;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
Type& Mat44<Type>::operator()(int col, int row)
|
||||
{
|
||||
return M[4*col+row];
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
const Type& Mat44<Type>::operator()(int col, int row) const
|
||||
{
|
||||
return M[4*col+row];
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::Set(const Type* a)
|
||||
{
|
||||
for (int i=0;i<16;i++) {
|
||||
M[i] = a[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::Set(Type M0, Type M4, Type M8, Type M12,
|
||||
Type M1, Type M5, Type M9, Type M13,
|
||||
Type M2, Type M6, Type M10, Type M14,
|
||||
Type M3, Type M7, Type M11, Type M15)
|
||||
{
|
||||
M[0]=M0; M[4]=M4; M[8]=M8; M[12]=M12;
|
||||
M[1]=M1; M[5]=M5; M[9]=M9; M[13]=M13;
|
||||
M[2]=M2; M[6]=M6; M[10]=M10; M[14]=M14;
|
||||
M[3]=M3; M[7]=M7; M[11]=M11; M[15]=M15;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Standard Matrix Operations
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat44<Type>::Identity()
|
||||
{
|
||||
M[0]=M[5]=M[10]=M[15]=1;
|
||||
M[1]=M[2]=M[3]=M[4]=M[6]=M[7]=M[8]=M[9]=M[11]=M[12]=M[13]=M[14]=0;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::Transpose()
|
||||
{
|
||||
SWAP(M[1],M[4]);
|
||||
SWAP(M[2],M[8]);
|
||||
SWAP(M[6],M[9]);
|
||||
SWAP(M[3],M[12]);
|
||||
SWAP(M[7],M[13]);
|
||||
SWAP(M[11],M[14]);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Standard Matrix Affine Transformations
|
||||
//---------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
void Mat44<Type>::Translate(Type Tx, Type Ty, Type Tz)
|
||||
{
|
||||
M[0]=1; M[4]=0; M[8]=0; M[12]=Tx;
|
||||
M[1]=0; M[5]=1; M[9]=0; M[13]=Ty;
|
||||
M[2]=0; M[6]=0; M[10]=1; M[14]=Tz;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::Translate(const Vec3<Type>& T)
|
||||
{
|
||||
M[0]=1; M[4]=0; M[8]=0; M[12]=T.x;
|
||||
M[1]=0; M[5]=1; M[9]=0; M[13]=T.y;
|
||||
M[2]=0; M[6]=0; M[10]=1; M[14]=T.z;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invTranslate(Type Tx, Type Ty, Type Tz)
|
||||
{
|
||||
M[0]=1; M[4]=0; M[8]=0; M[12]=-Tx;
|
||||
M[1]=0; M[5]=1; M[9]=0; M[13]=-Ty;
|
||||
M[2]=0; M[6]=0; M[10]=1; M[14]=-Tz;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invTranslate(const Vec3<Type>& T)
|
||||
{
|
||||
M[0]=1; M[4]=0; M[8]=0; M[12]=-T.x;
|
||||
M[1]=0; M[5]=1; M[9]=0; M[13]=-T.y;
|
||||
M[2]=0; M[6]=0; M[10]=1; M[14]=-T.z;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::Scale(Type Sx, Type Sy, Type Sz)
|
||||
{
|
||||
M[0]=Sx; M[4]=0; M[8]=0; M[12]=0;
|
||||
M[1]=0; M[5]=Sy; M[9]=0; M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=Sz; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::Scale(const Vec3<Type>& S)
|
||||
{
|
||||
M[0]=S.x; M[4]=0; M[8]=0; M[12]=0;
|
||||
M[1]=0; M[5]=S.y; M[9]=0; M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=S.z; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invScale(Type Sx, Type Sy, Type Sz)
|
||||
{
|
||||
M[0]=1/Sx; M[4]=0; M[8]=0; M[12]=0;
|
||||
M[1]=0; M[5]=1/Sy; M[9]=0; M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=1/Sz; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invScale(const Vec3<Type>& S)
|
||||
{
|
||||
M[0]=1/S.x; M[4]=0; M[8]=0; M[12]=0;
|
||||
M[1]=0; M[5]=1/S.y; M[9]=0; M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=1/S.z; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::Rotate(Type DegAng, const Vec3<Type>& Axis)
|
||||
{
|
||||
Type RadAng = DegAng*Mat44TORADS;
|
||||
Type ca=(Type)cos(RadAng),
|
||||
sa=(Type)sin(RadAng);
|
||||
if (Axis.x==1 && Axis.y==0 && Axis.z==0) // ABOUT X-AXIS
|
||||
{
|
||||
M[0]=1; M[4]=0; M[8]=0; M[12]=0;
|
||||
M[1]=0; M[5]=ca; M[9]=-sa; M[13]=0;
|
||||
M[2]=0; M[6]=sa; M[10]=ca; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
else if (Axis.x==0 && Axis.y==1 && Axis.z==0) // ABOUT Y-AXIS
|
||||
{
|
||||
M[0]=ca; M[4]=0; M[8]=sa; M[12]=0;
|
||||
M[1]=0; M[5]=1; M[9]=0; M[13]=0;
|
||||
M[2]=-sa; M[6]=0; M[10]=ca; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
else if (Axis.x==0 && Axis.y==0 && Axis.z==1) // ABOUT Z-AXIS
|
||||
{
|
||||
M[0]=ca; M[4]=-sa; M[8]=0; M[12]=0;
|
||||
M[1]=sa; M[5]=ca; M[9]=0; M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=1; M[14]=0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
else // ARBITRARY AXIS
|
||||
{
|
||||
Type l = Axis.LengthSqr();
|
||||
Type x, y, z;
|
||||
x=Axis.x, y=Axis.y, z=Axis.z;
|
||||
if (l > Type(1.0001) || l < Type(0.9999) && l!=0)
|
||||
{
|
||||
// needs normalization
|
||||
l=Type(1.0)/sqrt(l);
|
||||
x*=l; y*=l; z*=l;
|
||||
}
|
||||
Type x2=x*x, y2=y*y, z2=z*z;
|
||||
M[0]=x2+ca*(1-x2); M[4]=(x*y)+ca*(-x*y)+sa*(-z); M[8]=(x*z)+ca*(-x*z)+sa*y;
|
||||
M[1]=(x*y)+ca*(-x*y)+sa*z; M[5]=y2+ca*(1-y2); M[9]=(y*z)+ca*(-y*z)+sa*(-x);
|
||||
M[2]=(x*z)+ca*(-x*z)+sa*(-y); M[6]=(y*z)+ca*(-y*z)+sa*x; M[10]=z2+ca*(1-z2);
|
||||
M[12]=M[13]=M[14]=M[3]=M[7]=M[11]=0;
|
||||
M[15]=1;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invRotate(Type DegAng, const Vec3<Type>& Axis)
|
||||
{
|
||||
Rotate(DegAng,Axis);
|
||||
Transpose();
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
inline Type Mat44<Type>::Trace() const
|
||||
{
|
||||
return M[0] + M[5] + M[10] + M[15];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Same as glFrustum() : Perspective transformation matrix defined by a
|
||||
// truncated pyramid viewing frustum that starts at the origin (eye)
|
||||
// going in the -Z axis direction (viewer looks down -Z)
|
||||
// with the four pyramid sides passing through the sides of a window
|
||||
// defined through x=l, x=r, y=b, y=t on the viewplane at z=-n.
|
||||
// The top and bottom of the pyramid are truncated by the near and far
|
||||
// planes at z=-n and z=-f. A 4-vector (x,y,z,w) inside this frustum
|
||||
// transformed by this matrix will have x,y,z values in the range
|
||||
// [-w,w]. Homogeneous clipping is applied to restrict (x,y,z) to
|
||||
// this range. Later, a perspective divide by w will result in an NDC
|
||||
// coordinate 3-vector of the form (x/w,y/w,z/w,w/w)=(x',y',z',1) where
|
||||
// x', y', and z' all are in the range [-1,1]. Perspectively divided z'
|
||||
// will be in [-1,1] with -1 being the near plane and +1 being the far.
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat44<Type>::Frustum(Type l, Type r, Type b, Type t, Type n, Type f)
|
||||
{
|
||||
M[0]=(2*n)/(r-l); M[4]=0; M[8]=(r+l)/(r-l); M[12]=0;
|
||||
M[1]=0; M[5]=(2*n)/(t-b); M[9]=(t+b)/(t-b); M[13]=0;
|
||||
M[2]=0; M[6]=0; M[10]=-(f+n)/(f-n); M[14]=(-2*f*n)/(f-n);
|
||||
M[3]=0; M[7]=0; M[11]=-1; M[15]=0;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invFrustum(Type l, Type r, Type b, Type t, Type n, Type f)
|
||||
{
|
||||
M[0]=(r-l)/(2*n); M[4]=0; M[8]=0; M[12]=(r+l)/(2*n);
|
||||
M[1]=0; M[5]=(t-b)/(2*n); M[9]=0; M[13]=(t+b)/(2*n);
|
||||
M[2]=0; M[6]=0; M[10]=0; M[14]=-1;
|
||||
M[3]=0; M[7]=0; M[11]=-(f-n)/(2*f*n); M[15]=(f+n)/(2*f*n);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Same as gluPerspective : calls Frustum()
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat44<Type>::Perspective(Type Yfov, Type Aspect, Type Ndist, Type Fdist)
|
||||
{
|
||||
Yfov *= 0.0174532f; // CONVERT TO RADIANS
|
||||
Type wT=tanf(Yfov*0.5f)*Ndist, wB=-wT;
|
||||
Type wR=wT*Aspect, wL=-wR;
|
||||
Frustum(wL,wR,wB,wT,Ndist,Fdist);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invPerspective(Type Yfov, Type Aspect, Type Ndist, Type Fdist)
|
||||
{
|
||||
Yfov *= 0.0174532f; // CONVERT TO RADIANS
|
||||
Type wT=tanf(Yfov*0.5f)*Ndist, wB=-wT;
|
||||
Type wR=wT*Aspect, wL=-wR;
|
||||
invFrustum(wL,wR,wB,wT,Ndist,Fdist);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OpenGL VIEWPORT XFORM MATRIX : given Window width and height in pixels
|
||||
// Transforms the x,y,z NDC values in [-1,1] to (x',y') pixel values and
|
||||
// normalized z' in [0,1] (near and far respectively).
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat44<Type>::Viewport(int WW, int WH)
|
||||
{
|
||||
Type WW2=(Type)WW*0.5f, WH2=(Type)WH*0.5f;
|
||||
M[0]=WW2; M[4]=0; M[8]=0; M[12]=WW2;
|
||||
M[1]=0; M[5]=WH2; M[9]=0; M[13]=WH2;
|
||||
M[2]=0; M[6]=0; M[10]=0.5; M[14]=0.5;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invViewport(int WW, int WH)
|
||||
{
|
||||
Type WW2=2.0f/(Type)WW, WH2=2.0f/(Type)WH;
|
||||
M[0]=WW2; M[4]=0; M[8]=0; M[12]=-1.0;
|
||||
M[1]=0; M[5]=WH2; M[9]=0; M[13]=-1.0;
|
||||
M[2]=0; M[6]=0; M[10]=2.0; M[14]=-1.0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Same as gluLookAt()
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat44<Type>::LookAt(const Vec3<Type>& Eye,
|
||||
const Vec3<Type>& LookAtPt,
|
||||
const Vec3<Type>& ViewUp)
|
||||
{
|
||||
Vec3<Type> Z = Eye-LookAtPt; Z.Normalize(); // CALC CAM AXES ("/" IS CROSS-PROD)
|
||||
Vec3<Type> X = ViewUp/Z; X.Normalize();
|
||||
Vec3<Type> Y = Z/X; Y.Normalize();
|
||||
Vec3<Type> Tr = -Eye;
|
||||
M[0]=X.x; M[4]=X.y; M[8]=X.z; M[12]=X*Tr; // TRANS->ROT
|
||||
M[1]=Y.x; M[5]=Y.y; M[9]=Y.z; M[13]=Y*Tr;
|
||||
M[2]=Z.x; M[6]=Z.y; M[10]=Z.z; M[14]=Z*Tr;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invLookAt(const Vec3<Type>& Eye,
|
||||
const Vec3<Type>& LookAtPt,
|
||||
const Vec3<Type>& ViewUp)
|
||||
{
|
||||
Vec3<Type> Z = Eye-LookAtPt; Z.Normalize(); // CALC CAM AXES ("/" IS CROSS-PROD)
|
||||
Vec3<Type> X = ViewUp/Z; X.Normalize();
|
||||
Vec3<Type> Y = Z/X; Y.Normalize();
|
||||
M[0]=X.x; M[4]=Y.x; M[8]=Z.x; M[12]=Eye.x; // ROT->TRANS
|
||||
M[1]=X.y; M[5]=Y.y; M[9]=Z.y; M[13]=Eye.y;
|
||||
M[2]=X.z; M[6]=Y.z; M[10]=Z.z; M[14]=Eye.z;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// VIEWPORT TRANFORMATION MATRIX : given Window width and height in pixels
|
||||
// FROM "JIM BLINN'S CORNER" JULY '91. This function transforms an
|
||||
// 4-vector in homogeneous space of the form (x,y,z,w) where
|
||||
// -w<=x,y,z<=w into (x',y',z',1) where (x',y') is the vectors
|
||||
// projected pixel location in ([0,WW-1],[0,WH-1]) and z' is the
|
||||
// normalized depth value mapped into [0,1]; 0 is the near plane
|
||||
// and 1 is the far plane. Mat44VIEWPORT_TOL is introduced to have correct
|
||||
// mappings. (-1,-1,?,?) in NDC refers to the bottom-left of the
|
||||
// viewplane window and (0,0,?,?) in screen space refers to the
|
||||
// bottom-left pixel.
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat44<Type>::Viewport2(int WW, int WH)
|
||||
{
|
||||
Type WW2=(WW-Mat44VIEWPORT_TOL)*0.5f, WH2=(WH-Mat44VIEWPORT_TOL)*0.5f;
|
||||
M[0]=WW2; M[4]=0; M[8]=0; M[12]=WW2;
|
||||
M[1]=0; M[5]=WH2; M[9]=0; M[13]=WH2;
|
||||
M[2]=0; M[6]=0; M[10]=0.5; M[14]=0.5;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Mat44<Type>::invViewport2(int WW, int WH)
|
||||
{
|
||||
Type WW2=2.0f/(WW-Mat44VIEWPORT_TOL), WH2=2.0f/(WH-Mat44VIEWPORT_TOL);
|
||||
M[0]=WW2; M[4]=0; M[8]=0; M[12]=-1.0;
|
||||
M[1]=0; M[5]=WH2; M[9]=0; M[13]=-1.0;
|
||||
M[2]=0; M[6]=0; M[10]=2.0; M[14]=-1.0;
|
||||
M[3]=0; M[7]=0; M[11]=0; M[15]=1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Handy matrix printing routine.
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat44<Type>::Print() const
|
||||
{
|
||||
printf("\n%f %f %f %f\n",M[0],M[4],M[8],M[12]);
|
||||
printf("%f %f %f %f\n",M[1],M[5],M[9],M[13]);
|
||||
printf("%f %f %f %f\n",M[2],M[6],M[10],M[14]);
|
||||
printf("%f %f %f %f\n\n",M[3],M[7],M[11],M[15]);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Copy contents of matrix into matrix array.
|
||||
//---------------------------------------------------------------------------
|
||||
template<class Type>
|
||||
void Mat44<Type>::CopyInto(Type *Mat) const
|
||||
{
|
||||
Mat[0]=M[0]; Mat[4]=M[4]; Mat[8]=M[8]; Mat[12]=M[12];
|
||||
Mat[1]=M[1]; Mat[5]=M[5]; Mat[9]=M[9]; Mat[13]=M[13];
|
||||
Mat[2]=M[2]; Mat[6]=M[6]; Mat[10]=M[10]; Mat[14]=M[14];
|
||||
Mat[3]=M[3]; Mat[7]=M[7]; Mat[11]=M[11]; Mat[15]=M[15];
|
||||
}
|
||||
|
||||
66
simgear/scene/sky/clouds3d/mat44test.cpp
Normal file
66
simgear/scene/sky/clouds3d/mat44test.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : mat44test.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// mat44test -- test compilation of all the functions in mat44 library
|
||||
//----------------------------------------------------------------------------
|
||||
// $Id$
|
||||
//----------------------------------------------------------------------------
|
||||
#include <iostream.h>
|
||||
#include <vec3f.hpp>
|
||||
#include <mat44.hpp>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
cout << "This is not a comprehensive correctness test. " << endl
|
||||
<< "It merely tests whether all the functions in mat44 will compile." <<endl;
|
||||
|
||||
Mat44f m;
|
||||
float m2[16];
|
||||
Vec3f v(1.0, 1.0, 1.0);
|
||||
Vec3f up(0.0, 1.0, 0.0);
|
||||
|
||||
m.Identity();
|
||||
m.Transpose();
|
||||
m.Translate(1.0, 1.0, 1.0);
|
||||
m.Translate(v);
|
||||
m.invTranslate(v);
|
||||
m.Scale(1.0, 1.0, 1.0);
|
||||
m.Scale(v);
|
||||
m.invScale(1.0, 1.0, 1.0);
|
||||
m.invScale(v);
|
||||
m.Rotate(90, v);
|
||||
m.invRotate(90, v);
|
||||
m.Frustum(-1.0, 1.0, -1.0, 1.0, 0.01, 20);
|
||||
m.invFrustum(-1.0, 1.0, -1.0, 1.0, 0.01, 20);
|
||||
m.Perspective(60, 1.4, 0.01, 20);
|
||||
m.invPerspective(60, 1.4, 0.01, 20);
|
||||
m.Viewport(200, 200);
|
||||
m.invViewport(200, 200);
|
||||
m.LookAt(Vec3f::ZERO, v, up);
|
||||
m.invLookAt(Vec3f::ZERO, v, up);
|
||||
m.Viewport2(200, 200);
|
||||
m.invViewport2(200, 200);
|
||||
m.Print();
|
||||
m.Transpose();
|
||||
m.Print();
|
||||
// These two should be transpose of one another
|
||||
m.CopyInto(m2);
|
||||
|
||||
cout << "Ok there is this one test to make sure Transpose() is correct.\n"
|
||||
"The above two matricies should be the transpose of one another.\n" << endl;
|
||||
}
|
||||
108
simgear/scene/sky/clouds3d/minmaxbox.cpp
Normal file
108
simgear/scene/sky/clouds3d/minmaxbox.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : minmaxbox.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//=========================================================================
|
||||
// minmaxbox.cpp : min-max box routines
|
||||
//=========================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Calculates the eight corner vertices of the MinMaxBox.
|
||||
// V must be prealloced.
|
||||
// 5---4
|
||||
// / /|
|
||||
// 1---0 | VERTS : 0=RTN,1=LTN,2=LBN,3=RBN,4=RTF,5=LTF,6=LBF,7=RBF
|
||||
// | | 7 (L,R, B,T, N,F) = (Left,Right, Bottom,Top, Near,Far)
|
||||
// | |/
|
||||
// 2---3
|
||||
//-----------------------------------------------------------------------------
|
||||
void GetMinMaxBoxVerts(const float Min[3], const float Max[3], float V[8][3])
|
||||
{
|
||||
#define SET(v,x,y,z) v[0]=x; v[1]=y; v[2]=z;
|
||||
SET(V[0],Max[0],Max[1],Max[2]); SET(V[4],Max[0],Max[1],Min[2]);
|
||||
SET(V[1],Min[0],Max[1],Max[2]); SET(V[5],Min[0],Max[1],Min[2]);
|
||||
SET(V[2],Min[0],Min[1],Max[2]); SET(V[6],Min[0],Min[1],Min[2]);
|
||||
SET(V[3],Max[0],Min[1],Max[2]); SET(V[7],Max[0],Min[1],Min[2]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Ray-MinMaxBox intersection test. Returns 0 or 1, calcs In-Out "HitTimes"
|
||||
// IsectPts can be calculated as:
|
||||
// InIsectPt = Start + Dir * InT (if InT>0)
|
||||
// OutIsectPt = Start + Dir * OutT (if OutT>0)
|
||||
//--------------------------------------------------------------------------
|
||||
int RayMinMaxBoxIsect(const float Start[3], const float Dir[3],
|
||||
const float Min[3], const float Max[3],
|
||||
float *InT, float *OutT)
|
||||
{
|
||||
*InT=-99999, *OutT=99999; // INIT INTERVAL T-VAL ENDPTS TO -/+ "INFINITY"
|
||||
float NewInT, NewOutT; // STORAGE FOR NEW T VALUES
|
||||
|
||||
// X-SLAB (PARALLEL PLANES PERPENDICULAR TO X-AXIS) INTERSECTION (Xaxis is Normal)
|
||||
if (Dir[0] == 0) // CHECK IF RAY IS PARALLEL TO THE SLAB PLANES
|
||||
{ if ((Start[0] < Min[0]) || (Start[0] > Max[0])) return(0); }
|
||||
else
|
||||
{
|
||||
NewInT = (Min[0]-Start[0])/Dir[0]; // CALC Tval ENTERING MIN PLANE
|
||||
NewOutT = (Max[0]-Start[0])/Dir[0]; // CALC Tval ENTERING MAX PLANE
|
||||
if (NewOutT>NewInT) { if (NewInT>*InT) *InT=NewInT; if (NewOutT<*OutT) *OutT=NewOutT; }
|
||||
else { if (NewOutT>*InT) *InT=NewOutT; if (NewInT<*OutT) *OutT=NewInT; }
|
||||
if (*InT>*OutT) return(0);
|
||||
}
|
||||
|
||||
// Y-SLAB (PARALLEL PLANES PERPENDICULAR TO Y-AXIS) INTERSECTION (Yaxis is Normal)
|
||||
if (Dir[1] == 0) // CHECK IF RAY IS PARALLEL TO THE SLAB PLANES
|
||||
{ if ((Start[1] < Min[1]) || (Start[1] > Max[1])) return(0); }
|
||||
else
|
||||
{
|
||||
NewInT = (Min[1]-Start[1])/Dir[1]; // CALC Tval ENTERING MIN PLANE
|
||||
NewOutT = (Max[1] - Start[1])/Dir[1]; // CALC Tval ENTERING MAX PLANE
|
||||
if (NewOutT>NewInT) { if (NewInT>*InT) *InT=NewInT; if (NewOutT<*OutT) *OutT=NewOutT; }
|
||||
else { if (NewOutT>*InT) *InT=NewOutT; if (NewInT<*OutT) *OutT=NewInT; }
|
||||
if (*InT>*OutT) return(0);
|
||||
}
|
||||
|
||||
// Z-SLAB (PARALLEL PLANES PERPENDICULAR TO Z-AXIS) INTERSECTION (Zaxis is Normal)
|
||||
if (Dir[2] == 0) // CHECK IF RAY IS PARALLEL TO THE SLAB PLANES
|
||||
{ if ((Start[2] < Min[2]) || (Start[2] > Max[2])) return(0); }
|
||||
else
|
||||
{
|
||||
NewInT = (Min[2]-Start[2])/Dir[2]; // CALC Tval ENTERING MIN PLANE
|
||||
NewOutT = (Max[2]-Start[2])/Dir[2]; // CALC Tval ENTERING MAX PLANE
|
||||
if (NewOutT>NewInT) { if (NewInT>*InT) *InT=NewInT; if (NewOutT<*OutT) *OutT=NewOutT; }
|
||||
else { if (NewOutT>*InT) *InT=NewOutT; if (NewInT<*OutT) *OutT=NewInT; }
|
||||
if (*InT>*OutT) return(0);
|
||||
}
|
||||
|
||||
// CHECK IF INTERSECTIONS ARE "AT OR BEYOND" THE START OF THE RAY
|
||||
if (*InT>=0 || *OutT>=0) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// returns whether or not an edge intersects a MinMaxBox. The hit times
|
||||
// are returned just as in the ray isect test.
|
||||
//--------------------------------------------------------------------------
|
||||
int EdgeMinMaxBoxIsect(const float A[3], const float B[3],
|
||||
const float Min[3], const float Max[3],
|
||||
float *InT, float *OutT)
|
||||
{
|
||||
float Dir[3] = {B[0]-A[0],B[1]-A[1],B[2]-A[2]};
|
||||
if ( RayMinMaxBoxIsect(A,Dir,Min,Max,InT,OutT) )
|
||||
if (*InT>=0 && *InT<=1) return(1);
|
||||
else if (*OutT>=0 && *OutT<=1) return(1);
|
||||
return(0);
|
||||
}
|
||||
30
simgear/scene/sky/clouds3d/minmaxbox.hpp
Normal file
30
simgear/scene/sky/clouds3d/minmaxbox.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : minmaxbox.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//=========================================================================
|
||||
// minmaxbox.hpp : min-max box routines
|
||||
//=========================================================================
|
||||
|
||||
void GetMinMaxBoxVerts(const float Min[3], const float Max[3], float V[8][3]);
|
||||
|
||||
int RayMinMaxBoxIsect(const float Start[3], const float Dir[3],
|
||||
const float Min[3], const float Max[3],
|
||||
float *InT, float *OutT);
|
||||
int EdgeMinMaxBoxIsect(const float A[3], const float B[3],
|
||||
const float Min[3], const float Max[3],
|
||||
float *InT, float *OutT);
|
||||
|
||||
302
simgear/scene/sky/clouds3d/plane.cpp
Normal file
302
simgear/scene/sky/clouds3d/plane.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : plane.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//=========================================================================
|
||||
// plane.cpp
|
||||
//=========================================================================
|
||||
|
||||
#include <math.h>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculates the plane equation coeffients P = [ A B C D ] for the plane
|
||||
// equation: Ax+By+Cz+D=0 given three vertices defining the plane. The
|
||||
// normalized plane normal (A,B,C) is defined using the right-hand rule.
|
||||
//--------------------------------------------------------------------------
|
||||
float* PlaneEquation(float P[4],
|
||||
const float p0[3], const float p1[3], const float p2[3])
|
||||
{
|
||||
// CALCULATE PLANE NORMAL - FIRST THREE COEFFICIENTS (A,B,C)
|
||||
float u[3], v[3];
|
||||
u[0]=p1[0]-p0[0]; u[1]=p1[1]-p0[1]; u[2]=p1[2]-p0[2];
|
||||
v[0]=p2[0]-p0[0]; v[1]=p2[1]-p0[1]; v[2]=p2[2]-p0[2];
|
||||
|
||||
P[0] = u[1]*v[2] - u[2]*v[1]; // CROSS-PROD BETWEEN u AND v
|
||||
P[1] = u[2]*v[0] - u[0]*v[2]; // DEFINES UNNORMALIZED NORMAL
|
||||
P[2] = u[0]*v[1] - u[1]*v[0];
|
||||
|
||||
float l = (float)sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]); // NORMALIZE NORMAL
|
||||
P[0]/=l; P[1]/=l; P[2]/=l;
|
||||
|
||||
// CALCULATE D COEFFICIENT (USING FIRST PT ON PLANE - p0)
|
||||
P[3] = -(P[0]*p0[0] + P[1]*p0[1] + P[2]*p0[2]);
|
||||
|
||||
return(P);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculates the plane equation coeffients P = [ A B C D ] for the plane
|
||||
// equation: Ax+By+Cz+D=0 given an unnormalized normal N to the plane and
|
||||
// the distance along the normal to the plane Dist. The dot product between
|
||||
// the normalized normal and a point on the plane should equal the distance
|
||||
// along the normal to the plane (Dist): Ax+By+Cz=Dist, so D=-Dist.
|
||||
//--------------------------------------------------------------------------
|
||||
float* PlaneEquation(float P[4], const float N[3], float Dist)
|
||||
{
|
||||
// COPY AND NORMALIZE NORMAL
|
||||
P[0]=N[0]; P[1]=N[1]; P[2]=N[2];
|
||||
float l = (float)sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]);
|
||||
P[0]/=l; P[1]/=l; P[2]/=l;
|
||||
|
||||
// CALCULATE D COEFFICIENT
|
||||
P[3]=-Dist;
|
||||
|
||||
return(P);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculates the plane equation coeffients P = [ A B C D ] for the plane
|
||||
// equation: Ax+By+Cz+D=0 given an unnormalized normal N to the plane and
|
||||
// a point pt on the plane. The dot product between the normalized normal
|
||||
// and the point should equal the distance along the normal to the plane,
|
||||
// thus equalling negative D.
|
||||
//--------------------------------------------------------------------------
|
||||
float* PlaneEquation(float P[4], const float N[3], const float pt[3])
|
||||
{
|
||||
// COPY AND NORMALIZE NORMAL
|
||||
P[0]=N[0]; P[1]=N[1]; P[2]=N[2];
|
||||
float l = (float)sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]);
|
||||
P[0]/=l; P[1]/=l; P[2]/=l;
|
||||
|
||||
// CALCULATE D COEFFICIENT (USING PT ON PLANE)
|
||||
P[3] = -(P[0]*pt[0] + P[1]*pt[1] + P[2]*pt[2]);
|
||||
|
||||
return(P);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Transforms a plane by a 4x4 matrix (col-major order, assumes premult/col vect).
|
||||
// The given plane coefficients are altered. The normal (A,B,C) is normalized.
|
||||
// see HOFF tech report: "4x4 matrix transformation of the implicit form of the plane"
|
||||
//--------------------------------------------------------------------------
|
||||
void XformPlane(const float M[16], float P[4])
|
||||
{
|
||||
float NewP[4], L2, L;
|
||||
NewP[0] = M[0]*P[0] + M[4]*P[1] + M[8]*P[2];
|
||||
NewP[1] = M[1]*P[0] + M[5]*P[1] + M[9]*P[2];
|
||||
NewP[2] = M[2]*P[0] + M[6]*P[1] + M[10]*P[2];
|
||||
L2 = NewP[0]*NewP[0] + NewP[1]*NewP[1] + NewP[2]*NewP[2];
|
||||
L = (float)sqrt(L2);
|
||||
P[0] = NewP[0] / L;
|
||||
P[1] = NewP[1] / L;
|
||||
P[2] = NewP[2] / L;
|
||||
P[3] = P[3]*L2 - (NewP[0]*M[12] + NewP[1]*M[13] + NewP[2]*M[14]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// return 1 if point is "outside" (normal side) of plane, 0 if "inside" or on
|
||||
//--------------------------------------------------------------------------
|
||||
int PlanePtOutTest(const float P[4], const float Pt[3])
|
||||
{
|
||||
return( (P[0]*Pt[0] + P[1]*Pt[1] + P[2]*Pt[2]) > -P[3] );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// returns -1 inside, 0 on, 1 outside (normal side)
|
||||
//--------------------------------------------------------------------------
|
||||
int PlanePtInOutTest(const float P[4], const float Pt[3])
|
||||
{
|
||||
float DotProd = P[0]*Pt[0] + P[1]*Pt[1] + P[2]*Pt[2];
|
||||
if (DotProd < -P[3]) return(-1);
|
||||
if (DotProd > -P[3]) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculates the "signed" distance of a point from a plane (in units of
|
||||
// the normal length, if not normalized). +Dist is on normal dir side of plane.
|
||||
//--------------------------------------------------------------------------
|
||||
float PlaneDistToPt(const float P[4], const float Pt[3])
|
||||
{
|
||||
return( P[0]*Pt[0] + P[1]*Pt[1] + P[2]*Pt[2] + P[3] );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// returns 1 if ray (Start,Dir) intersects plane, 0 if not
|
||||
//--------------------------------------------------------------------------
|
||||
int PlaneRayIsect(const float P[4], const float Start[3], const float Dir[3])
|
||||
{
|
||||
float NdotDir = P[0]*Dir[0] + P[1]*Dir[1] + P[2]*Dir[2];
|
||||
float NdotStart = P[0]*Start[0] + P[1]*Start[1] + P[2]*Start[2];
|
||||
if (NdotDir==(float)0) return(0);
|
||||
float t = (-P[3] - NdotStart) / NdotDir;
|
||||
if (t>=0) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Also computes intersection point, if possible
|
||||
//--------------------------------------------------------------------------
|
||||
int PlaneRayIsect(const float P[4], const float Start[3], const float Dir[3],
|
||||
float IsectPt[3])
|
||||
{
|
||||
float NdotDir = P[0]*Dir[0] + P[1]*Dir[1] + P[2]*Dir[2];
|
||||
float NdotStart = P[0]*Start[0] + P[1]*Start[1] + P[2]*Start[2];
|
||||
if (NdotDir==(float)0) return(0);
|
||||
float t = (-P[3] - NdotStart) / NdotDir;
|
||||
if (t>=0)
|
||||
{
|
||||
IsectPt[0] = Start[0] + Dir[0]*t;
|
||||
IsectPt[1] = Start[1] + Dir[1]*t;
|
||||
IsectPt[2] = Start[2] + Dir[2]*t;
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Intersects a line with a plane with normal (0,0,-1) with distance d
|
||||
// from the origin. The line is given by position Start and direction Dir.
|
||||
//--------------------------------------------------------------------------
|
||||
int ZPlaneLineIsect(float d, const float Start[3], const float Dir[3],
|
||||
float IsectPt[3])
|
||||
{
|
||||
float NdotDir = -Dir[2];
|
||||
if (NdotDir==(float)0) return(0);
|
||||
float t = (d + Start[2]) / NdotDir;
|
||||
IsectPt[0] = Start[0] + Dir[0]*t;
|
||||
IsectPt[1] = Start[1] + Dir[1]*t;
|
||||
IsectPt[2] = Start[2] + Dir[2]*t;
|
||||
return(1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// returns 1 if edge AB intersects plane, 0 if not
|
||||
//--------------------------------------------------------------------------
|
||||
int PlaneEdgeIsect(const float P[4], const float A[3], const float B[3])
|
||||
{
|
||||
float Dir[3] = { B[0]-A[0], B[1]-A[1], B[2]-A[2] };
|
||||
float NdotDir = P[0]*Dir[0] + P[1]*Dir[1] + P[2]*Dir[2];
|
||||
float NdotA = P[0]*A[0] + P[1]*A[1] + P[2]*A[2];
|
||||
if (NdotDir==(float)0) return(0);
|
||||
float t = (-P[3] - NdotA) / NdotDir;
|
||||
if (t>=0 && t<=1) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Also computes intersection point, if possible
|
||||
//--------------------------------------------------------------------------
|
||||
int PlaneEdgeIsect(const float P[4], const float A[3], const float B[3],
|
||||
float IsectPt[3])
|
||||
{
|
||||
float Dir[3] = { B[0]-A[0], B[1]-A[1], B[2]-A[2] };
|
||||
float NdotDir = P[0]*Dir[0] + P[1]*Dir[1] + P[2]*Dir[2];
|
||||
float NdotA = P[0]*A[0] + P[1]*A[1] + P[2]*A[2];
|
||||
if (NdotDir==(float)0) return(0);
|
||||
float t = (-P[3] - NdotA) / NdotDir;
|
||||
if (t>=0 && t<=1)
|
||||
{
|
||||
IsectPt[0] = A[0] + Dir[0]*t;
|
||||
IsectPt[1] = A[1] + Dir[1]*t;
|
||||
IsectPt[2] = A[2] + Dir[2]*t;
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Box (m,M)/ Plane P overlap test.
|
||||
// returns type of overlap: 1=OUT (side of normal dir), -1=IN, 0=Overlapping
|
||||
// Finds the "closest" and "farthest" points from the plane with respect
|
||||
// to the plane normal dir (the "extremes" of the aabb) and tests for overlap.
|
||||
// m and M are the Min and Max extents of the AABB.
|
||||
//---------------------------------------------------------------------------
|
||||
int PlaneMinMaxBoxOverlap(const float P[4], const float m[3], const float M[3])
|
||||
{
|
||||
#define SET(v,x,y,z) v[0]=x; v[1]=y; v[2]=z;
|
||||
|
||||
// CALC EXTREME PTS (Neg,Pos) ALONG NORMAL AXIS (Pos in dir of norm, etc.)
|
||||
float Neg[3], Pos[3];
|
||||
if(P[0]>0)
|
||||
if(P[1]>0) { if(P[2]>0) { SET(Pos,M[0],M[1],M[2]); SET(Neg,m[0],m[1],m[2]); }
|
||||
else { SET(Pos,M[0],M[1],m[2]); SET(Neg,m[0],m[1],M[2]); } }
|
||||
else { if(P[2]>0) { SET(Pos,M[0],m[1],M[2]); SET(Neg,m[0],M[1],m[2]); }
|
||||
else { SET(Pos,M[0],m[1],m[2]); SET(Neg,m[0],M[1],M[2]); } }
|
||||
else
|
||||
if(P[1]>0) { if(P[2]>0) { SET(Pos,m[0],M[1],M[2]); SET(Neg,M[0],m[1],m[2]); }
|
||||
else { SET(Pos,m[0],M[1],m[2]); SET(Neg,M[0],m[1],M[2]); } }
|
||||
else { if(P[2]>0) { SET(Pos,m[0],m[1],M[2]); SET(Neg,M[0],M[1],m[2]); }
|
||||
else { SET(Pos,m[0],m[1],m[2]); SET(Neg,M[0],M[1],M[2]); } }
|
||||
|
||||
// CHECK DISTANCE TO PLANE FROM EXTREMAL POINTS TO DETERMINE OVERLAP
|
||||
if (PlaneDistToPt(P,Neg) > 0) return(1);
|
||||
else if (PlaneDistToPt(P,Pos) <= 0) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Edge/Planes intersection test. Returns 0 or 1, calcs In-Out "HitTimes"
|
||||
// IsectPts can be calculated as:
|
||||
// InIsectPt = Start + Dir * InT (if InT>0)
|
||||
// OutIsectPt = Start + Dir * OutT (if OutT>0)
|
||||
// Planes is defined as: float Planes[n][4] for n planes.
|
||||
//---------------------------------------------------------------------------
|
||||
int PlanesRayIsect(const float Planes[][4], int NumPlanes,
|
||||
const float Start[3], const float Dir[3],
|
||||
float *InT, float *OutT)
|
||||
{
|
||||
*InT=-99999, *OutT=99999; // INIT INTERVAL T-VAL ENDPTS TO -/+ INFINITY
|
||||
float NdotDir, NdotStart; // STORAGE FOR REPEATED CALCS NEEDED FOR NewT CALC
|
||||
float NewT;
|
||||
for (int i=0; i<NumPlanes; i++) // CHECK INTERSECTION AGAINST EACH VF PLANE
|
||||
{
|
||||
NdotDir = Planes[i][0]*Dir[0] + Planes[i][1]*Dir[1] + Planes[i][2]*Dir[2];
|
||||
NdotStart = Planes[i][0]*Start[0] + Planes[i][1]*Start[1] + Planes[i][2]*Start[2];
|
||||
if (NdotDir == 0) // CHECK IF RAY IS PARALLEL TO THE SLAB PLANES
|
||||
{
|
||||
if (NdotStart > -Planes[i][3]) return(0); // IF STARTS "OUTSIDE", NO INTERSECTION
|
||||
}
|
||||
else
|
||||
{
|
||||
NewT = (-Planes[i][3] - NdotStart) / NdotDir; // FIND HIT "TIME" (DISTANCE)
|
||||
if (NdotDir < 0) { if (NewT > *InT) *InT=NewT; } // IF "FRONTFACING", MUST BE NEW IN "TIME"
|
||||
else { if (NewT < *OutT) *OutT=NewT; } // IF "BACKFACING", MUST BE NEW OUT "TIME"
|
||||
}
|
||||
if (*InT > *OutT) return(0); // CHECK FOR EARLY EXITS (INTERSECTION INTERVAL "OUTSIDE")
|
||||
}
|
||||
|
||||
// IF AT LEAST ONE THE Tvals ARE IN THE INTERVAL [0,1] WE HAVE INTERSECTION
|
||||
if (*InT>=0 || *OutT>=0) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// returns whether or not an edge AB intersects a set of planes. The hit
|
||||
// times are returned just as in the ray isect test.
|
||||
//--------------------------------------------------------------------------
|
||||
int PlanesEdgeIsect(const float Planes[][4], int NumPlanes,
|
||||
const float A[3], const float B[3],
|
||||
float *InT, float *OutT)
|
||||
{
|
||||
float Dir[3] = {B[0]-A[0],B[1]-A[1],B[2]-A[2]};
|
||||
if ( PlanesRayIsect(Planes,NumPlanes,A,Dir,InT,OutT) )
|
||||
if (*InT>=0 && *InT<=1) return(1);
|
||||
else if (*OutT>=0 && *OutT<=1) return(1);
|
||||
return(0);
|
||||
}
|
||||
51
simgear/scene/sky/clouds3d/plane.hpp
Normal file
51
simgear/scene/sky/clouds3d/plane.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : plane.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//=========================================================================
|
||||
// plane.hpp
|
||||
//=========================================================================
|
||||
|
||||
// PLANE EQUATION COEFFICIENT GENERATION FUNCTIONS
|
||||
float* PlaneEquation(float P[4],
|
||||
const float p0[3], const float p1[3], const float p2[3]);
|
||||
float* PlaneEquation(float P[4], const float N[3], float Dist);
|
||||
float* PlaneEquation(float P[4], const float N[3], const float pt[3]);
|
||||
|
||||
int PlanePtOutTest(const float P[4], const float Pt[3]);
|
||||
int PlanePtInOutTest(const float P[4], const float Pt[3]);
|
||||
float PlaneDistToPt(const float P[4], const float Pt[3]);
|
||||
|
||||
int PlaneRayIsect(const float P[4], const float Start[3], const float Dir[3]);
|
||||
int PlaneRayIsect(const float P[4], const float Start[3], const float Dir[3],
|
||||
float IsectPt[3]);
|
||||
int ZPlaneLineIsect(float d, const float Start[3], const float Dir[3],
|
||||
float IsectPt[3]);
|
||||
int PlaneEdgeIsect(const float P[4], const float A[3], const float B[3]);
|
||||
int PlaneEdgeIsect(const float P[4], const float A[3], const float B[3],
|
||||
float IsectPt[3]);
|
||||
|
||||
void XformPlane(const float M[16], float P[4]);
|
||||
|
||||
int PlaneMinMaxBoxOverlap(const float P[4], const float m[3],
|
||||
const float M[3]);
|
||||
|
||||
int PlanesRayIsect(const float Planes[][4], int NumPlanes,
|
||||
const float Start[3], const float Dir[3],
|
||||
float *InT, float *OutT);
|
||||
int PlanesEdgeIsect(const float Planes[][4], int NumPlanes,
|
||||
const float A[3], const float B[3],
|
||||
float *InT, float *OutT);
|
||||
166
simgear/scene/sky/clouds3d/quat.hpp
Normal file
166
simgear/scene/sky/clouds3d/quat.hpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : quat.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
quat.hpp
|
||||
|
||||
A quaternion template class
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Feb 1998, Paul Rademacher (rademach@cs.unc.edu)
|
||||
|
||||
Modification History:
|
||||
- Oct 2000, Bill Baxter. Adapted to GLVU coding conventions and
|
||||
templetized. Also implemented many methods that were declared but
|
||||
not defined. Added some methods from quatlib and other sources.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef _QUAT_H_
|
||||
#define _QUAT_H_
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include "mat44.hpp"
|
||||
#include "mat33.hpp"
|
||||
|
||||
/****************************************************************
|
||||
* Quaternion *
|
||||
****************************************************************/
|
||||
|
||||
template <class Type>
|
||||
class Quat
|
||||
{
|
||||
public:
|
||||
typedef Vec3<Type> qvec;
|
||||
|
||||
Type s; /* scalar component */
|
||||
qvec v; /* quat vector component */
|
||||
|
||||
/* Constructors */
|
||||
|
||||
Quat(void);
|
||||
Quat(Type s, Type x, Type y, Type z);
|
||||
Quat(Type x, Type y, Type z); // s=0
|
||||
Quat(Type s, const qvec& v);
|
||||
Quat(const qvec& v, Type s = 0.0);
|
||||
Quat(const Type *d); /* copy from four-element Type array s,x,y,z */
|
||||
Quat(const Quat &q); /* copy from other Quat */
|
||||
|
||||
/* Setters */
|
||||
|
||||
void Set( Type x, Type y, Type z );
|
||||
void Set( Type s, Type x, Type y, Type z );
|
||||
void Set( Type s, const qvec& v );
|
||||
void Set( const qvec& v, Type s=0 );
|
||||
|
||||
/* Operators */
|
||||
|
||||
Quat &operator = ( const Quat &v ); /* assignment of a Quat */
|
||||
Quat &operator += ( const Quat &v ); /* incrementation by a Quat */
|
||||
Quat &operator -= ( const Quat &v ); /* decrementation by a Quat */
|
||||
Quat &operator *= ( const Type d ); /* multiplication by a scalar */
|
||||
Quat &operator *= ( const Quat &v ); /* quat product (this*v) */
|
||||
Quat &operator /= ( const Type d ); /* division by a scalar */
|
||||
Type &operator [] ( int i); /* indexing s=0,x=1,y=2,z=3 */
|
||||
|
||||
/* special functions */
|
||||
|
||||
Type Length(void) const; /* length of a Quat */
|
||||
Type LengthSqr(void) const; /* squared length of a Quat */
|
||||
Type Norm(void) const; /* also squared length of a Quat */
|
||||
Quat &Normalize(void); /* normalize a Quat */
|
||||
Quat &Invert(void); /* q = q^-1 */
|
||||
Quat &Conjugate(void); /* q = q* */
|
||||
qvec Xform( const qvec &v ) const; /* q*v*q-1 */
|
||||
Quat &Log(void); /* log(q) */
|
||||
Quat &Exp(void); /* exp(q) */
|
||||
qvec GetAxis( void ) const; /* Get rot axis */
|
||||
Type GetAngle( void ) const; /* Get rot angle (radians) */
|
||||
void SetAngle( Type rad_ang ); /* set rot angle (radians) */
|
||||
void ScaleAngle( Type f ); /* scale rot angle */
|
||||
void Print( ) const; /* print Quat */
|
||||
|
||||
/* Conversions */
|
||||
Mat44<Type>& ToMat( Mat44<Type> &dest ) const; /* to 4x4 matrix */
|
||||
Mat33<Type>& ToMat( Mat33<Type> &dest ) const; /* to 3x3 matrix */
|
||||
Quat& FromMat( const Mat44<Type>& src ); /* from 4x4 rot matrix */
|
||||
Quat& FromMat( const Mat33<Type>& src ); /* from 3x3 rot matrix */
|
||||
|
||||
void ToAngleAxis( Type &ang, qvec &ax ) const; /* to rot angle AND axis */
|
||||
Quat& FromAngleAxis( Type ang, const qvec &ax );/*from rot angle AND axis */
|
||||
Quat& FromTwoVecs(const qvec &a, const qvec& b); /* quat from a to b */
|
||||
// to/from Euler Angles (XYZ-Fixed/ZYX-Relative, angles in radians)
|
||||
// See quatimpl.hpp for more detailed comments.
|
||||
Quat& FromEuler( Type yaw_Z, Type pitch_Y, Type roll_X);
|
||||
void ToEuler(Type &yaw_Z, Type &pitch_Y, Type &roll_X) const;
|
||||
|
||||
|
||||
// HELPERS
|
||||
static Type DEG2RAD(Type d);
|
||||
static Type RAD2DEG(Type d);
|
||||
static Type Sin(double d);
|
||||
static Type Cos(double d);
|
||||
static Type ACos(double d);
|
||||
static Type ASin(double d);
|
||||
static Type ATan(double d);
|
||||
static Type ATan2(double n, double d);
|
||||
|
||||
// CONSTANTS
|
||||
static Type FUDGE();
|
||||
static Quat ZERO();
|
||||
static Quat IDENTITY();
|
||||
};
|
||||
|
||||
/* Utility functions */
|
||||
template <class Type>
|
||||
Quat<Type>& QuatSlerp(
|
||||
Quat<Type> &dest, const Quat<Type>& from, const Quat<Type>& to, Type t );
|
||||
template <class Type>
|
||||
Quat<Type> QuatSlerp(const Quat<Type>& from, const Quat<Type>& to, Type t );
|
||||
|
||||
/* "Friends" */
|
||||
template <class Type>
|
||||
Quat<Type> operator -(const Quat<Type> &v); // -q1
|
||||
template <class Type>
|
||||
Quat<Type> operator +(const Quat<Type> &a, const Quat<Type> &b); // q1 + q2
|
||||
template <class Type>
|
||||
Quat<Type> operator -(const Quat<Type> &a, const Quat<Type> &b); // q1 - q2
|
||||
template <class Type>
|
||||
Quat<Type> operator *(const Quat<Type> &a, const Type d); // q1 * 3.0
|
||||
template <class Type>
|
||||
Quat<Type> operator *(const Type d, const Quat<Type> &a); // 3.0 * q1
|
||||
template <class Type>
|
||||
Quat<Type> operator *(const Quat<Type> &a, const Quat<Type> &b); // q1 * q2
|
||||
template <class Type>
|
||||
Quat<Type> operator /(const Quat<Type> &a, const Type d); // q1 / 3.0
|
||||
template <class Type>
|
||||
bool operator ==(const Quat<Type> &a, const Quat<Type> &b); // q1 == q2 ?
|
||||
template <class Type>
|
||||
bool operator !=(const Quat<Type> &a, const Quat<Type> &b); // q1 != q2 ?
|
||||
|
||||
|
||||
|
||||
#include "quatimpl.hpp"
|
||||
|
||||
|
||||
|
||||
typedef Quat<float> Quatf;
|
||||
typedef Quat<double> Quatd;
|
||||
|
||||
#endif
|
||||
886
simgear/scene/sky/clouds3d/quatimpl.hpp
Normal file
886
simgear/scene/sky/clouds3d/quatimpl.hpp
Normal file
@@ -0,0 +1,886 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : quatimpl.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
quatimpl.hpp
|
||||
|
||||
A quaternion template class
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Feb 1998, Paul Rademacher (rademach@cs.unc.edu)
|
||||
Oct 2000, Bill Baxter
|
||||
|
||||
Modification History:
|
||||
- See main header file, quat.hpp
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#include "quat.hpp"
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//============================================================================
|
||||
// CONSTRUCTORS
|
||||
//============================================================================
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>::Quat( void )
|
||||
{
|
||||
// do nothing so default construction is fast
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>::Quat( Type _s, Type x, Type y, Type z )
|
||||
{
|
||||
s = _s;
|
||||
v.Set( x, y, z );
|
||||
}
|
||||
template <class Type>
|
||||
Quat<Type>::Quat( Type x, Type y, Type z )
|
||||
{
|
||||
s = 0.0;
|
||||
v.Set( x, y, z );
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>::Quat( const qvec& _v, Type _s )
|
||||
{
|
||||
Set( _v, _s );
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>::Quat( Type _s, const qvec& _v )
|
||||
{
|
||||
Set( _v, _s );
|
||||
}
|
||||
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>::Quat( const Type *d )
|
||||
{
|
||||
s = *d++;
|
||||
v.Set(d);
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>::Quat( const Quat &q )
|
||||
{
|
||||
s = q.s;
|
||||
v = q.v;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// SETTERS
|
||||
//============================================================================
|
||||
|
||||
template <class Type>
|
||||
void Quat<Type>::Set( Type _s, Type x, Type y, Type z )
|
||||
{
|
||||
s = _s;
|
||||
v.Set(x,y,z);
|
||||
}
|
||||
template <class Type>
|
||||
void Quat<Type>::Set( Type x, Type y, Type z )
|
||||
{
|
||||
s = 0.0;
|
||||
v.Set(x,y,z);
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
void Quat<Type>::Set( const qvec& _v, Type _s )
|
||||
{
|
||||
s = _s;
|
||||
v = _v;
|
||||
}
|
||||
template <class Type>
|
||||
void Quat<Type>::Set( Type _s, const qvec& _v )
|
||||
{
|
||||
s = _s;
|
||||
v = _v;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
// OPERATORS
|
||||
//============================================================================
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>& Quat<Type>::operator = (const Quat& q)
|
||||
{
|
||||
v = q.v; s = q.s; return *this;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>& Quat<Type>::operator += ( const Quat &q )
|
||||
{
|
||||
v += q.v; s += q.s; return *this;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>& Quat<Type>::operator -= ( const Quat &q )
|
||||
{
|
||||
v -= q.v; s -= q.s; return *this;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> &Quat<Type>::operator *= ( const Type d )
|
||||
{
|
||||
v *= d; s *= d; return *this;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> &Quat<Type>::operator *= ( const Quat& q )
|
||||
{
|
||||
#if 0
|
||||
// Quaternion multiplication with
|
||||
// temporary object construction minimized (hopefully)
|
||||
Type ns = s*q.s - v*q.v;
|
||||
qvec nv(v^q.v);
|
||||
v *= q.s;
|
||||
v += nv;
|
||||
nv.Set(s*q.v);
|
||||
v += nv;
|
||||
s = ns;
|
||||
return *this;
|
||||
#else
|
||||
// optimized (12 mults, and no compiler-generated temp objects)
|
||||
Type A, B, C, D, E, F, G, H;
|
||||
|
||||
A = (s + v.x)*(q.s + q.v.x);
|
||||
B = (v.z - v.y)*(q.v.y - q.v.z);
|
||||
C = (s - v.x)*(q.v.y + q.v.z);
|
||||
D = (v.y + v.z)*(q.s - q.v.x);
|
||||
E = (v.x + v.z)*(q.v.x + q.v.y);
|
||||
F = (v.x - v.z)*(q.v.x - q.v.y);
|
||||
G = (s + v.y)*(q.s - q.v.z);
|
||||
H = (s - v.y)*(q.s + q.v.z);
|
||||
|
||||
v.x = A - (E + F + G + H) * Type(0.5);
|
||||
v.y = C + (E - F + G - H) * Type(0.5);
|
||||
v.z = D + (E - F - G + H) * Type(0.5);
|
||||
s = B + (-E - F + G + H) * Type(0.5);
|
||||
|
||||
return *this;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> &Quat<Type>::operator /= ( const Type d )
|
||||
{
|
||||
Type r = Type(1.0)/d;
|
||||
v *= r;
|
||||
s *= r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Type &Quat<Type>::operator [] ( int i)
|
||||
{
|
||||
switch (i) {
|
||||
case 0: return s;
|
||||
case 1: return v.x;
|
||||
case 2: return v.y;
|
||||
case 3: return v.z;
|
||||
}
|
||||
assert(false);
|
||||
return s;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// SPECIAL FUNCTIONS
|
||||
//============================================================================
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::Length( void ) const
|
||||
{
|
||||
return Type( sqrt( v*v + s*s ) );
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::LengthSqr( void ) const
|
||||
{
|
||||
return Norm();
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::Norm( void ) const
|
||||
{
|
||||
return v*v + s*s;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
inline Quat<Type>& Quat<Type>::Normalize( void )
|
||||
{
|
||||
*this *= Type(1.0) / Type(sqrt(v*v + s*s));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
inline Quat<Type>& Quat<Type>::Invert( void )
|
||||
{
|
||||
Type scale = Type(1.0)/Norm();
|
||||
v *= -scale;
|
||||
s *= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
inline Quat<Type>& Quat<Type>::Conjugate( void )
|
||||
{
|
||||
v.x = -v.x;
|
||||
v.y = -v.y;
|
||||
v.z = -v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Xform
|
||||
//----------------------------------------------------------------------------
|
||||
// Transform a vector by this quaternion using q * v * q^-1
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type>::qvec Quat<Type>::Xform( const qvec &vec ) const
|
||||
{
|
||||
/* copy vector into temp quaternion for multiply */
|
||||
Quat vecQuat(vec);
|
||||
/* invert multiplier */
|
||||
Quat inverse(*this);
|
||||
inverse.Invert();
|
||||
|
||||
/* do q * vec * q(inv) */
|
||||
Quat tempVecQuat(*this * vecQuat);
|
||||
tempVecQuat *= inverse;
|
||||
|
||||
/* return vector part */
|
||||
return tempVecQuat.v;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Log
|
||||
//----------------------------------------------------------------------------
|
||||
// Natural log of quat
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type> &Quat<Type>::Log(void)
|
||||
{
|
||||
Type theta, scale;
|
||||
|
||||
scale = v.Length();
|
||||
theta = ATan2(scale, s);
|
||||
|
||||
if (scale > 0.0)
|
||||
scale = theta/scale;
|
||||
|
||||
v *= scale;
|
||||
s = 0.0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Exp
|
||||
//----------------------------------------------------------------------------
|
||||
// e to the quat: e^quat
|
||||
// -- assuming scalar part 0
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type> &Quat<Type>::Exp(void)
|
||||
{
|
||||
Type scale;
|
||||
Type theta = v.Length();
|
||||
|
||||
if (theta > FUDGE()) {
|
||||
scale = Sin(theta)/theta ;
|
||||
v *= scale;
|
||||
}
|
||||
|
||||
s = Cos(theta) ;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// SetAngle (radians)
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
void Quat<Type>::SetAngle( Type f )
|
||||
{
|
||||
qvec axis(GetAxis());
|
||||
f *= Type(0.5);
|
||||
s = Cos( f );
|
||||
v = axis * Sin( f );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ScaleAngle
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
inline void Quat<Type>::ScaleAngle( Type f )
|
||||
{
|
||||
SetAngle( f * GetAngle() );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// GetAngle (radians)
|
||||
//----------------------------------------------------------------------------
|
||||
// get rot angle in radians. Assumes s is between -1 and 1, which will always
|
||||
// be the case for unit quaternions.
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::GetAngle( void ) const
|
||||
{
|
||||
return ( Type(2.0) * ACos( s ) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// GetAxis
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type>::qvec Quat<Type>::GetAxis( void ) const
|
||||
{
|
||||
Type scale;
|
||||
|
||||
scale = Sin( acos( s ) ) ;
|
||||
if ( scale < FUDGE() && scale > -FUDGE() )
|
||||
return qvec( 0.0, 0.0, 0.0 );
|
||||
else
|
||||
return v / scale;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Print
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
inline void Quat<Type>::Print( ) const
|
||||
{
|
||||
printf( "(%3.2f, <%3.2f %3.2f %3.2f>)\n", s, v.x, v.y, v.z );
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
// CONVERSIONS
|
||||
//============================================================================
|
||||
|
||||
template <class Type>
|
||||
Mat44<Type>& Quat<Type>::ToMat( Mat44<Type>& dest ) const
|
||||
{
|
||||
Type t, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
|
||||
qvec a, c, b, d;
|
||||
|
||||
t = Type(2.0) / (v*v + s*s);
|
||||
const Type ONE(1.0);
|
||||
|
||||
xs = v.x*t; ys = v.y*t; zs = v.z*t;
|
||||
wx = s*xs; wy = s*ys; wz = s*zs;
|
||||
xx = v.x*xs; xy = v.x*ys; xz = v.x*zs;
|
||||
yy = v.y*ys; yz = v.y*zs; zz = v.z*zs;
|
||||
|
||||
dest.Set( ONE-(yy+zz), xy-wz, xz+wy, 0.0,
|
||||
xy+wz, ONE-(xx+zz), yz-wx, 0.0,
|
||||
xz-wy, yz+wx, ONE-(xx+yy), 0.0,
|
||||
0.0, 0.0, 0.0, ONE );
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Mat33<Type>& Quat<Type>::ToMat( Mat33<Type>& dest ) const
|
||||
{
|
||||
Type t, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
|
||||
qvec a, c, b, d;
|
||||
|
||||
t = Type(2.0) / Norm();
|
||||
const Type ONE(1.0);
|
||||
|
||||
xs = v.x*t; ys = v.y*t; zs = v.z*t;
|
||||
wx = s*xs; wy = s*ys; wz = s*zs;
|
||||
xx = v.x*xs; xy = v.x*ys; xz = v.x*zs;
|
||||
yy = v.y*ys; yz = v.y*zs; zz = v.z*zs;
|
||||
|
||||
dest.Set( ONE-(yy+zz), xy-wz, xz+wy,
|
||||
xy+wz, ONE-(xx+zz), yz-wx,
|
||||
xz-wy, yz+wx, ONE-(xx+yy) );
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// FromMat
|
||||
//----------------------------------------------------------------------------
|
||||
// Convert rotation matrix to quaternion
|
||||
// Results will be bad if matrix is not (very close to) orthonormal
|
||||
// Modified from gamasutra.com article:
|
||||
// http://www.gamasutra.com/features/programming/19980703/quaternions_07.htm
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type>& Quat<Type>::FromMat( const Mat44<Type>& m )
|
||||
{
|
||||
Type tr = m.Trace();
|
||||
|
||||
// check the diagonal
|
||||
if (tr > 0.0) {
|
||||
Type scale = Type( sqrt (tr) );
|
||||
s = scale * Type(0.5);
|
||||
scale = Type(0.5) / scale;
|
||||
v.x = (m(1,2) - m(2,1)) * scale;
|
||||
v.y = (m(2,0) - m(0,2)) * scale;
|
||||
v.z = (m(0,1) - m(1,0)) * scale;
|
||||
} else {
|
||||
// diagonal is negative or zero
|
||||
int i, j, k;
|
||||
i = 0;
|
||||
if (m(1,1) > m(0,0)) i = 1;
|
||||
if (m(2,2) > m(i,i)) i = 2;
|
||||
int nxt[3] = {1, 2, 0};
|
||||
j = nxt[i];
|
||||
k = nxt[j];
|
||||
|
||||
Type scale = Type( sqrt (Type(1.0) + m(i,i) - (m(j,j) + m(k,k)) ) );
|
||||
|
||||
v[i] = scale * Type(0.5);
|
||||
|
||||
if (scale != 0.0) scale = Type(0.5) / scale;
|
||||
|
||||
s = (m(j,k) - m(k,j)) * scale;
|
||||
v[j] = (m(i,j) + m(j,i)) * scale;
|
||||
v[k] = (m(i,k) + m(k,i)) * scale;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type>& Quat<Type>::FromMat( const Mat33<Type>& m )
|
||||
{
|
||||
Type tr = m.Trace();
|
||||
|
||||
// check the diagonal
|
||||
if (tr > 0.0) {
|
||||
Type scale = Type( sqrt (tr + Type(1.0)) );
|
||||
s = scale * Type(0.5);
|
||||
scale = Type(0.5) / scale;
|
||||
v.x = (m(1,2) - m(2,1)) * scale;
|
||||
v.y = (m(2,0) - m(0,2)) * scale;
|
||||
v.z = (m(0,1) - m(1,0)) * scale;
|
||||
} else {
|
||||
// diagonal is negative or zero
|
||||
int i, j, k;
|
||||
i = 0;
|
||||
if (m(1,1) > m(0,0)) i = 1;
|
||||
if (m(2,2) > m(i,i)) i = 2;
|
||||
int nxt[3] = {1, 2, 0};
|
||||
j = nxt[i];
|
||||
k = nxt[j];
|
||||
|
||||
Type scale = Type( sqrt (Type(1.0) + m(i,i) - (m(j,j) + m(k,k)) ) );
|
||||
|
||||
v[i] = scale * Type(0.5);
|
||||
|
||||
if (scale != 0.0) scale = Type(0.5) / scale;
|
||||
|
||||
s = (m(j,k) - m(k,j)) * scale;
|
||||
v[j] = (m(i,j) + m(j,i)) * scale;
|
||||
v[k] = (m(i,k) + m(k,i)) * scale;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ToAngleAxis (radians)
|
||||
//----------------------------------------------------------------------------
|
||||
// Convert to angle & axis representation
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
void Quat<Type>::ToAngleAxis( Type &angle, qvec &axis ) const
|
||||
{
|
||||
Type cinv = ACos( s );
|
||||
angle = Type(2.0) * cinv;
|
||||
|
||||
Type scale;
|
||||
|
||||
scale = Sin( cinv );
|
||||
if ( scale < FUDGE() && scale > -FUDGE() )
|
||||
axis = qvec::ZERO;
|
||||
else {
|
||||
axis = v;
|
||||
axis /= scale;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// FromAngleAxis (radians)
|
||||
//----------------------------------------------------------------------------
|
||||
// Convert to quat from angle & axis representation
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type>& Quat<Type>::FromAngleAxis( Type angle, const qvec &axis )
|
||||
{
|
||||
/* normalize vector */
|
||||
Type length = axis.Length();
|
||||
|
||||
/* if zero vector passed in, just set to identity quaternion */
|
||||
if ( length < FUDGE() )
|
||||
{
|
||||
*this = IDENTITY();
|
||||
return *this;
|
||||
}
|
||||
length = Type(1.0)/length;
|
||||
angle *= 0.5;
|
||||
v = axis;
|
||||
v *= length;
|
||||
v *= Sin(angle);
|
||||
|
||||
s = Cos(angle);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// FromTwoVecs
|
||||
//----------------------------------------------------------------------------
|
||||
// Return the quat that rotates vector a into vector b
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type>& Quat<Type>::FromTwoVecs(const qvec &a, const qvec& b)
|
||||
{
|
||||
qvec u1(a);
|
||||
qvec u2(b);
|
||||
double theta ; /* angle of rotation about axis */
|
||||
double theta_complement ;
|
||||
double crossProductMagnitude ;
|
||||
|
||||
|
||||
// Normalize both vectors and take cross product to get rotation axis.
|
||||
u1.Normalize();
|
||||
u2.Normalize();
|
||||
qvec axis( u1 ^ u2 );
|
||||
|
||||
|
||||
// | u1 X u2 | = |u1||u2|sin(theta)
|
||||
//
|
||||
// Since u1 and u2 are normalized,
|
||||
//
|
||||
// theta = arcsin(|axis|)
|
||||
crossProductMagnitude = axis.Length();
|
||||
|
||||
// Occasionally, even though the vectors are normalized, the
|
||||
// magnitude will be calculated to be slightly greater than one. If
|
||||
// this happens, just set it to 1 or asin() will barf.
|
||||
if( crossProductMagnitude > Type(1.0) )
|
||||
crossProductMagnitude = Type(1.0) ;
|
||||
|
||||
// Take arcsin of magnitude of rotation axis to compute rotation
|
||||
// angle. Since crossProductMagnitude=[0,1], we will have
|
||||
// theta=[0,pi/2].
|
||||
theta = ASin( crossProductMagnitude ) ;
|
||||
theta_complement = Type(3.14159265358979323846) - theta ;
|
||||
|
||||
// If cos(theta) < 0, use complement of theta as rotation angle.
|
||||
if( u1 * u2 < 0.0 )
|
||||
{
|
||||
double tmp = theta;
|
||||
theta = theta_complement ;
|
||||
theta_complement = tmp;
|
||||
}
|
||||
|
||||
// if angle is 0, just return identity quaternion
|
||||
if( theta < FUDGE() )
|
||||
{
|
||||
*this = IDENTITY();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( theta_complement < FUDGE() )
|
||||
{
|
||||
// The two vectors are opposed. Find some arbitrary axis vector.
|
||||
// First try cross product with x-axis if u1 not parallel to x-axis.
|
||||
if( (u1.y*u1.y + u1.z*u1.z) >= FUDGE() )
|
||||
{
|
||||
axis.Set( 0.0, u1.z, -u1.y ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// u1 is parallel to to x-axis. Use z-axis as axis of rotation.
|
||||
axis.Set(0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
axis.Normalize();
|
||||
FromAngleAxis(Type(theta), axis);
|
||||
Normalize();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// FromEuler
|
||||
//----------------------------------------------------------------------------
|
||||
// converts 3 euler angles (in radians) to a quaternion
|
||||
//
|
||||
// angles are in radians; Assumes roll is rotation about X, pitch is
|
||||
// rotation about Y, yaw is about Z. (So thinking of
|
||||
// Z as up) Assumes order of yaw, pitch, roll applied as follows:
|
||||
//
|
||||
// p' = roll( pitch( yaw(p) ) )
|
||||
//
|
||||
// Where yaw, pitch, and roll are defined in the BODY coordinate sys.
|
||||
// In other words these are ZYX-relative (or XYZ-fixed) Euler Angles.
|
||||
//
|
||||
// For a complete Euler angle implementation that handles all 24 angle
|
||||
// sets, see "Euler Angle Conversion" by Ken Shoemake, in "Graphics
|
||||
// Gems IV", Academic Press, 1994
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type>& Quat<Type>::FromEuler(Type yaw, Type pitch, Type roll)
|
||||
{
|
||||
Type cosYaw, sinYaw, cosPitch, sinPitch, cosRoll, sinRoll;
|
||||
Type half_roll, half_pitch, half_yaw;
|
||||
|
||||
/* put angles into radians and divide by two, since all angles in formula
|
||||
* are (angle/2)
|
||||
*/
|
||||
const Type HALF(0.5);
|
||||
half_yaw = yaw * HALF;
|
||||
half_pitch = pitch * HALF;
|
||||
half_roll = roll * HALF;
|
||||
|
||||
cosYaw = Cos(half_yaw);
|
||||
sinYaw = Sin(half_yaw);
|
||||
|
||||
cosPitch = Cos(half_pitch);
|
||||
sinPitch = Sin(half_pitch);
|
||||
|
||||
cosRoll = Cos(half_roll);
|
||||
sinRoll = Sin(half_roll);
|
||||
|
||||
Type cpcy = cosPitch * cosYaw;
|
||||
Type spsy = sinPitch * sinYaw;
|
||||
|
||||
v.x = sinRoll * cpcy - cosRoll * spsy;
|
||||
v.y = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw;
|
||||
v.z = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw;
|
||||
s = cosRoll * cpcy + sinRoll * spsy;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ToEuler
|
||||
//----------------------------------------------------------------------------
|
||||
// converts a quaternion to 3 euler angles (in radians)
|
||||
//
|
||||
// See FromEuler for details of which set of Euler Angles are returned
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
void Quat<Type>::ToEuler(Type& yaw, Type& pitch, Type& roll) const
|
||||
{
|
||||
// This is probably wrong
|
||||
Mat33<Type> M;
|
||||
ToMat(M);
|
||||
const int i = 0, j = 1, k = 2;
|
||||
double cy = sqrt(M(i,i)*M(i,i) + M(i,j)*M(i,j));
|
||||
if (cy > FUDGE()) {
|
||||
roll = ATan2(M(j,k), M(k,k));
|
||||
pitch = ATan2(-M(i,k), cy);
|
||||
yaw = ATan2(M(i,j), M(i,i));
|
||||
} else {
|
||||
roll = ATan2(-M(k,j), M(j,j));
|
||||
pitch = ATan2(-M(i,k), cy);
|
||||
yaw = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// QUAT FRIENDS
|
||||
//============================================================================
|
||||
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> operator + (const Quat<Type> &a, const Quat<Type> &b)
|
||||
{
|
||||
return Quat<Type>( a.s+b.s, a.v+b.v );
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> operator - (const Quat<Type> &a, const Quat<Type> &b)
|
||||
{
|
||||
return Quat<Type>( a.s-b.s, a.v-b.v );
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> operator - (const Quat<Type> &a )
|
||||
{
|
||||
return Quat<Type>( -a.s, -a.v );
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> operator * ( const Quat<Type> &a, const Quat<Type> &b)
|
||||
{
|
||||
#if 0
|
||||
// 16 mults
|
||||
return Quat<Type>( a.s*b.s - a.v*b.v, a.s*b.v + b.s*a.v + a.v^b.v );
|
||||
#else
|
||||
// optimized (12 mults, and no compiler-generated temp objects)
|
||||
Type A, B, C, D, E, F, G, H;
|
||||
|
||||
A = (a.s + a.v.x)*(b.s + b.v.x);
|
||||
B = (a.v.z - a.v.y)*(b.v.y - b.v.z);
|
||||
C = (a.s - a.v.x)*(b.v.y + b.v.z);
|
||||
D = (a.v.y + a.v.z)*(b.s - b.v.x);
|
||||
E = (a.v.x + a.v.z)*(b.v.x + b.v.y);
|
||||
F = (a.v.x - a.v.z)*(b.v.x - b.v.y);
|
||||
G = (a.s + a.v.y)*(b.s - b.v.z);
|
||||
H = (a.s - a.v.y)*(b.s + b.v.z);
|
||||
|
||||
return Quat<Type>(
|
||||
B + (-E - F + G + H) * Type(0.5),
|
||||
A - (E + F + G + H) * Type(0.5),
|
||||
C + (E - F + G - H) * Type(0.5),
|
||||
D + (E - F - G + H) * Type(0.5));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> operator * ( const Quat<Type> &a, const Type t)
|
||||
{
|
||||
return Quat<Type>( a.v * t, a.s * t );
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
Quat<Type> operator * ( const Type t, const Quat<Type> &a )
|
||||
{
|
||||
return Quat<Type>( a.v * t, a.s * t );
|
||||
}
|
||||
template <class Type>
|
||||
Quat<Type> operator / ( const Quat<Type> &a, const Type t )
|
||||
{
|
||||
return Quat<Type>( a.v / t, a.s / t );
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
bool operator == (const Quat<Type> &a, const Quat<Type> &b)
|
||||
{
|
||||
return (a.s == b.s && a.v == b.v);
|
||||
}
|
||||
template <class Type>
|
||||
bool operator != (const Quat<Type> &a, const Quat<Type> &b)
|
||||
{
|
||||
return (a.s != b.s || a.v != b.v);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
// UTILS
|
||||
//============================================================================
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::DEG2RAD(Type d)
|
||||
{
|
||||
return d * Type(0.0174532925199432957692369076848861);
|
||||
}
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::RAD2DEG(Type d)
|
||||
{
|
||||
return d * Type(57.2957795130823208767981548141052);
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::Sin(double d) { return Type(sin(d)); }
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::Cos(double d) { return Type(cos(d)); }
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::ACos(double d) { return Type(acos(d)); }
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::ASin(double d) { return Type(asin(d)); }
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::ATan(double d) { return Type(atan(d)); }
|
||||
template <class Type>
|
||||
inline Type Quat<Type>::ATan2(double n, double d) {return Type(atan2(n,d));}
|
||||
|
||||
template <class Type>
|
||||
inline Quat<Type> Quat<Type>::ZERO() {return Quat(0,0,0,0); }
|
||||
template <class Type>
|
||||
inline Quat<Type> Quat<Type>::IDENTITY() {return Quat(1,0,0,0); }
|
||||
|
||||
template<class Type>
|
||||
inline Type Quat<Type>::FUDGE() { return 1e-6; }
|
||||
template<>
|
||||
inline double Quat<double>::FUDGE() { return 1e-10; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// QuatSlerp
|
||||
//----------------------------------------------------------------------------
|
||||
template <class Type>
|
||||
Quat<Type>& QuatSlerp(
|
||||
Quat<Type> &dest,
|
||||
const Quat<Type> &from, const Quat<Type> &to, Type t )
|
||||
{
|
||||
#if 0
|
||||
// compact mathematical version
|
||||
// exp(t*log(to*from^-1))*from
|
||||
Quat<Type> fminv(from);
|
||||
Quat<Type> tofrom(to*fminv.Invert());
|
||||
Quat<Type> slerp = t*tofrom.Log();
|
||||
slerp.Exp();
|
||||
slerp *= from;
|
||||
return slerp;
|
||||
#endif
|
||||
Quat<Type> to1;
|
||||
double omega, cosom, sinom, scale0, scale1;
|
||||
|
||||
/* calculate cosine */
|
||||
cosom = from.v * to.v + from.s + to.s;
|
||||
|
||||
/* Adjust signs (if necessary) so we take shorter path */
|
||||
if ( cosom < 0.0 ) {
|
||||
cosom = -cosom;
|
||||
to1 = -to;
|
||||
}
|
||||
else
|
||||
{
|
||||
to1 = to;
|
||||
}
|
||||
|
||||
/* Calculate coefficients */
|
||||
if ((1.0 - cosom) > Quat<Type>::FUDGE ) {
|
||||
/* standard case (slerp) */
|
||||
omega = acos( cosom );
|
||||
sinom = sin( omega );
|
||||
scale0 = sin((1.0 - t) * omega) / sinom;
|
||||
scale1 = sin(t * omega) / sinom;
|
||||
}
|
||||
else {
|
||||
/* 'from' and 'to' are very close - just do linear interpolation */
|
||||
scale0 = 1.0 - t;
|
||||
scale1 = t;
|
||||
}
|
||||
|
||||
dest = from;
|
||||
dest *= Type(scale0);
|
||||
dest += Type(scale1) * to1;
|
||||
return dest;
|
||||
}
|
||||
|
||||
// This version creates more temporary objects
|
||||
template <class Type>
|
||||
inline Quat<Type> QuatSlerp(
|
||||
const Quat<Type>& from, const Quat<Type>& to, Type t )
|
||||
{
|
||||
Quat<Type> q;
|
||||
return QuatSlerp(q, from, to, t);
|
||||
}
|
||||
|
||||
|
||||
196
simgear/scene/sky/clouds3d/quattest.cpp
Normal file
196
simgear/scene/sky/clouds3d/quattest.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : quattest.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Quattest.cpp
|
||||
// Quaternion coverage (and maybe functionality) test.
|
||||
// The main objective is to just make sure every API gets called
|
||||
// to flush out lurking template bugs that might not otherwise get tickled.
|
||||
// A few checks to make sure things are functioning properly are also
|
||||
// included.
|
||||
//
|
||||
// For the API coverage, if the thing simply compiles then it was a success.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "quat.hpp"
|
||||
|
||||
void coverage_test()
|
||||
{
|
||||
float x = 0.5f, y = 1.1f, z = -0.1f, s = 0.2f;
|
||||
// TEST CONSTRUCTORS
|
||||
Quatf q1;
|
||||
Quatf q2 = Quatf(x, y, z, s);
|
||||
Quatf q3(x, y, z);
|
||||
Quatf q4(Vec3f(1,2,3));
|
||||
Quatf q5(Vec3f(2,3,4), 2.0);
|
||||
Quatf q6(1.0, Vec3f(-1,-2,-3));
|
||||
float floatarray[4] = { 1, 2, 3, 4 };
|
||||
Quatf q7(floatarray);
|
||||
Quatf q8(q7);
|
||||
|
||||
// TEST SETTERS
|
||||
q1.Set(1,2,3);
|
||||
q2.Set(1,2,3,4);
|
||||
q3.Set(Vec3f(1.0,1.0,1.0));
|
||||
q3.Set(Vec3f(1.0,1.0,1.0),-0.5);
|
||||
|
||||
// TEST OPERATORS
|
||||
// Quat &operator = ( const Quat &v ); /* assignment of a Quat */
|
||||
q4 = q6;
|
||||
// Quat &operator += ( const Quat &v ); /* incrementation by a Quat */
|
||||
q3 += q2;
|
||||
// Quat &operator -= ( const Quat &v ); /* decrementation by a Quat */
|
||||
q3 -= q2;
|
||||
// Quat &operator *= ( const Type d ); /* multiplication by a scalar */
|
||||
q4 *= 0.5f;
|
||||
// Quat &operator *= ( const Quat &v ); /* quat product (this*v) */
|
||||
q2 *= q1;
|
||||
// Quat &operator /= ( const Type d ); /* division by a scalar */
|
||||
q5 /= 2.0f;
|
||||
// Type &operator [] ( int i); /* indexing x=0, s=3 */
|
||||
float c0 = q1[0];
|
||||
float c1 = q1[1];
|
||||
float c2 = q1[2];
|
||||
float c3 = q1[3];
|
||||
|
||||
// TEST SPECIAL FUNCTIONS
|
||||
|
||||
// Type Length(void) const; /* length of a Quat */
|
||||
float l = q4.Length();
|
||||
// Type LengthSqr(void) const; /* squared length of a Quat */
|
||||
l = q4.LengthSqr();
|
||||
// Type LengthSqr(void) const; /* squared length of a Quat */
|
||||
l = q4.Norm();
|
||||
// Quat &Normalize(void); /* normalize a Quat */
|
||||
Quatf q9 = q4.Normalize();
|
||||
// Quat &Invert(void); /* q = q^-1 */
|
||||
q9 = q4.Invert();
|
||||
// Quat &Conjugate(void); /* q = q* */
|
||||
q9 = q4.Conjugate();
|
||||
// qvec Xform( const qvec &v ); /* q*v*q-1 */
|
||||
Vec3f v1 = q4.Xform(Vec3f(1.0,1.0,1.0));
|
||||
// Quat &Log(void); /* log(q) */
|
||||
q9 = q4.Log();
|
||||
// Quat &Exp(void); /* exp(q) */
|
||||
q9 = q4.Exp();
|
||||
// qvec GetAxis( void ) const; /* Get rot axis */
|
||||
v1 = q5.GetAxis();
|
||||
// Type GetAngle( void ) const; /* Get rot angle (radians) */
|
||||
float a = q5.GetAngle();
|
||||
// void SetAngle( Type rad_ang ); /* set rot angle (radians) */
|
||||
q2.SetAngle(a);
|
||||
// void ScaleAngle( Type f ); /* scale rot angle */
|
||||
q2.ScaleAngle(1.5);
|
||||
// void Print( ) const; /* print Quat */
|
||||
q3.Print();
|
||||
|
||||
/* TEST CONVERSIONS */
|
||||
Mat44f m44;
|
||||
Mat33f m33;
|
||||
//Mat44& ToMat( Mat44 &dest ) const;
|
||||
//Mat33& ToMat( Mat33 &dest ) const;
|
||||
// Quat& FromMat( const Mat44<Type>& src ) const;
|
||||
// Quat& FromMat( const Mat33<Type>& src ) const;
|
||||
q3.Normalize();
|
||||
m44 = q3.ToMat(m44);
|
||||
m33 = q3.ToMat(m33);
|
||||
q5 = q3.FromMat(m44);
|
||||
q5 = q3.FromMat(m33);
|
||||
//void ToAngleAxis( Type &ang, qvec &ax ) const;
|
||||
q3.ToAngleAxis( a, v1 );
|
||||
//Quat& FromAngleAxis( Type ang, const qvec &ax );
|
||||
q4 = q3.FromAngleAxis( a, v1 );
|
||||
//Quat& FromTwoVecs(const qvec &a, const qvec& b);
|
||||
Vec3f v2(-1,-2,-3);
|
||||
q4 = q3.FromTwoVecs( v2, v1 );
|
||||
//Quat& FromEuler( Type yaw, Type pitch, Type roll);
|
||||
q4 = q3.FromEuler( 2.2f, 1.2f, -0.4f );
|
||||
//void ToEuler(Type &yaw, Type &pitch, Type &roll) const;
|
||||
float p=0.3f,r=-1.57f; y= 0.1f;
|
||||
q3.ToEuler( y,p,r );
|
||||
|
||||
/* TEST FRIENDS */
|
||||
|
||||
//friend Quat operator - (const Quat &v); /* -q1 */
|
||||
q1 = -q2;
|
||||
//friend Quat operator + (const Quat &a, const Quat &b); /* q1 + q2 */
|
||||
q1 = q2 + q3;
|
||||
//friend Quat operator - (const Quat &a, const Quat &b); /* q1 - q2 */
|
||||
q1 = q2 - q3;
|
||||
//friend Quat operator * (const Quat &a, const Type d); /* q1 * 3.0 */
|
||||
q1 = q2 * 0.2f;
|
||||
//friend Quat operator * (const Type d, const Quat &a); /* 3.0 * q1 */
|
||||
q1 = 0.2f * q2;
|
||||
//friend Quat operator * (const Quat &a, const Quat &b); /* q1 * q2 */
|
||||
q1 = q2 * q3;
|
||||
//friend Quat operator / (const Quat &a, const Type d); /* q1 / 3.0 */
|
||||
q1 = q2 / 1.2f;
|
||||
//friend bool operator == (const Quat &a, const Quat &b); /* q1 == q2 ? */
|
||||
bool eq = (q1 == q2);
|
||||
//friend bool operator != (const Quat &a, const Quat &b); /* q1 != q2 ? */
|
||||
bool neq = (q1 != q2);
|
||||
|
||||
// HELPERS
|
||||
// static Type DEG2RAD(Type d);
|
||||
// static Type RAD2DEG(Type d);
|
||||
a = Quatf::RAD2DEG(a);
|
||||
a = Quatf::DEG2RAD(a);
|
||||
a = Quatf::Sin(a);
|
||||
a = Quatf::Cos(a);
|
||||
a = Quatf::ACos(a);
|
||||
a = Quatf::ASin(a);
|
||||
a = Quatf::ATan(a);
|
||||
a = Quatf::ATan2(a, p);
|
||||
|
||||
// CONSTANTS
|
||||
// static const Type FUDGE;
|
||||
// static const Quat ZERO;
|
||||
// static const Quat IDENTITY;
|
||||
a = Quatf::FUDGE;
|
||||
q3 = Quatf::ZERO();
|
||||
q4 = Quatf::IDENTITY();
|
||||
|
||||
q1 = QuatSlerp(q1, q3, q4, 0.5f );
|
||||
q1 = QuatSlerp(q3, q4, 0.5f );
|
||||
|
||||
}
|
||||
|
||||
Quatf StatQuat(Quatf::IDENTITY());
|
||||
Quatf StatQuat2 = Quatf::IDENTITY();
|
||||
|
||||
void functional_test()
|
||||
{
|
||||
printf("The ZERO quat: ");
|
||||
Quatf::ZERO().Print();
|
||||
printf("The IDENTITY quat: ");
|
||||
Quatf::IDENTITY().Print();
|
||||
printf("Statically constructed copy of IDENTITY quat: ");
|
||||
StatQuat.Print();
|
||||
printf("A different static copy of IDENTITY quat: ");
|
||||
StatQuat2.Print();
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
coverage_test();
|
||||
functional_test();
|
||||
|
||||
return (0);
|
||||
}
|
||||
106
simgear/scene/sky/clouds3d/tri.cpp
Normal file
106
simgear/scene/sky/clouds3d/tri.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : tri.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// tri.cpp : triangle defs and intersection routines.
|
||||
//============================================================================
|
||||
|
||||
#include <math.h>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CHECKS IF 2D POINT P IS IN A 2D TRI ABC.
|
||||
//----------------------------------------------------------------------------
|
||||
int PtInTri2D(float Px, float Py,
|
||||
float Ax, float Ay, float Bx, float By, float Cx, float Cy)
|
||||
{
|
||||
float dABx=Bx-Ax, dABy=By-Ay, dBCx=Cx-Bx, dBCy=Cy-By; // "REPEATS"
|
||||
if (dABx*dBCy < dABy*dBCx) // CW
|
||||
{
|
||||
if (dABx*(Py-Ay) >= dABy*(Px-Ax)) return(0); // ABxAP
|
||||
if (dBCx*(Py-By) >= dBCy*(Px-Bx)) return(0); // BCxBP
|
||||
if ((Ax-Cx)*(Py-Cy) >= (Ay-Cy)*(Px-Cx)) return(0); // CAxCP
|
||||
}
|
||||
else // CCW
|
||||
{
|
||||
if (dABx*(Py-Ay) < dABy*(Px-Ax)) return(0); // ABxAP
|
||||
if (dBCx*(Py-By) < dBCy*(Px-Bx)) return(0); // BCxBP
|
||||
if ((Ax-Cx)*(Py-Cy) < (Ay-Cy)*(Px-Cx)) return(0); // CAxCP
|
||||
}
|
||||
return(1); // "INSIDE" EACH EDGE'S IN-HALF-SPACE (PT P IS INSIDE TRIANGLE)
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CHECKS IF 3D POINT P (ON ABC'S PLANE) IS IN 3D TRI ABC.
|
||||
// P=PtOnTriPlane, N=PlaneNormal (does not have to be normalized)
|
||||
//----------------------------------------------------------------------------
|
||||
int PtInTri3D(const float P[3], float N[3],
|
||||
const float A[3], const float B[3], const float C[3])
|
||||
{
|
||||
#define ABS(x) (((x)<0)?(-(x)):x) // HANDY UNIVERSAL ABSOLUTE VALUE FUNC
|
||||
|
||||
// DETERMINE LARGEST COMPONENT OF NORMAL (magnitude, since we want the largest projection)
|
||||
N[0]=ABS(N[0]); N[1]=ABS(N[1]); N[2]=ABS(N[2]);
|
||||
|
||||
// PROJECT ONTO PLANE WHERE PERPENDICULAR TO LARGEST NORMAL COMPONENT AXIS
|
||||
if (N[0]>N[1] && N[0]>N[2]) // X IS LARGEST SO PROJECT ONTO YZ-PLANE
|
||||
return( PtInTri2D(P[1],P[2], A[1],A[2], B[1],B[2], C[1],C[2]) );
|
||||
else if (N[1]>N[0] && N[1]>N[2]) // Y IS LARGEST SO PROJECT ONTO XZ-PLANE
|
||||
return( PtInTri2D(P[0],P[2], A[0],A[2], B[0],B[2], C[0],C[2]) );
|
||||
else // Z IS LARGEST SO PROJECT ONTO XY-PLANE
|
||||
return( PtInTri2D(P[0],P[1], A[0],A[1], B[0],B[1], C[0],C[1]) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Checks if an edge UV intersects a triangle ABC. Returns whether or
|
||||
// not the edge intersects the plane (0 or 1) and the IsectPt.
|
||||
//--------------------------------------------------------------------------
|
||||
int EdgeTriIsect(const float U[3], const float V[3],
|
||||
const float A[3], const float B[3], const float C[3],
|
||||
float IsectPt[3])
|
||||
{
|
||||
// CALCULATE PLANE EQUATION COEFFICIENTS P FOR TRI ABC
|
||||
float P[4];
|
||||
float u[3] = {B[0]-A[0],B[1]-A[1],B[2]-A[2]};
|
||||
float v[3] = {C[0]-A[0],C[1]-A[1],C[2]-A[2]};
|
||||
P[0] = u[1]*v[2] - u[2]*v[1]; // CROSS-PROD BETWEEN u AND v
|
||||
P[1] = u[2]*v[0] - u[0]*v[2]; // DEFINES UNNORMALIZED NORMAL
|
||||
P[2] = u[0]*v[1] - u[1]*v[0];
|
||||
float l = (float)sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]); // NORMALIZE NORMAL
|
||||
P[0]/=l; P[1]/=l; P[2]/=l;
|
||||
P[3] = -(P[0]*A[0] + P[1]*A[1] + P[2]*A[2]);
|
||||
|
||||
// FIND INTERSECTION OF EDGE UV WITH PLANE P
|
||||
int EdgeIsectsPlane=0;
|
||||
float Dir[3] = { V[0]-U[0], V[1]-U[1], V[2]-U[2] };
|
||||
float NdotDir = P[0]*Dir[0] + P[1]*Dir[1] + P[2]*Dir[2];
|
||||
float NdotU = P[0]*U[0] + P[1]*U[1] + P[2]*U[2];
|
||||
if (NdotDir==(float)0) return(0);
|
||||
float t = (-P[3] - NdotU) / NdotDir;
|
||||
if (t>=0 && t<=1)
|
||||
{
|
||||
IsectPt[0] = U[0] + Dir[0]*t;
|
||||
IsectPt[1] = U[1] + Dir[1]*t;
|
||||
IsectPt[2] = U[2] + Dir[2]*t;
|
||||
EdgeIsectsPlane=1;
|
||||
}
|
||||
|
||||
// FIRST, DOES THE EDGE INTERSECT THE PLANE?
|
||||
if (!EdgeIsectsPlane) return(0);
|
||||
|
||||
// SEE IF ISECT PT IS IN THE TRI
|
||||
return( PtInTri3D(IsectPt,P,A,B,C) );
|
||||
}
|
||||
30
simgear/scene/sky/clouds3d/tri.hpp
Normal file
30
simgear/scene/sky/clouds3d/tri.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : tri.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// tri.hpp : triangle defs and intersection routines.
|
||||
//============================================================================
|
||||
|
||||
int PtInTri2D(float Px, float Py,
|
||||
float Ax, float Ay, float Bx, float By, float Cx, float Cy);
|
||||
|
||||
int PtInTri3D(const float P[3], float N[3],
|
||||
const float A[3], const float B[3], const float C[3]);
|
||||
|
||||
int EdgeTriIsect(const float U[3], const float V[3],
|
||||
const float A[3], const float B[3], const float C[3],
|
||||
float IsectPt[3]);
|
||||
137
simgear/scene/sky/clouds3d/vec2f.hpp
Normal file
137
simgear/scene/sky/clouds3d/vec2f.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// File : vec2f.hpp
|
||||
//-----------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//==========================================================================
|
||||
// vec2.hpp : 2d vector class template. Works for any integer or real type.
|
||||
//==========================================================================
|
||||
|
||||
#ifndef VEC2_H
|
||||
#define VEC2_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
template<class Type>
|
||||
class Vec2
|
||||
{
|
||||
public:
|
||||
Type x, y;
|
||||
|
||||
Vec2 (void) {};
|
||||
Vec2 (const Type X, const Type Y) { x=X; y=Y; };
|
||||
Vec2 (const Vec2& v) { x=v.x; y=v.y; };
|
||||
Vec2 (const Type v[2]) { x=v[0]; y=v[1]; };
|
||||
void Set (const Type X, const Type Y) { x=X; y=Y; }
|
||||
void Set (const Type v[2]) { x=v[0]; y=v[1]; };
|
||||
|
||||
operator Type*() // Type * CONVERSION
|
||||
{ return (Type *)&x; }
|
||||
operator const Type*() const // CONST Type * CONVERSION
|
||||
{ return &x; }
|
||||
|
||||
Vec2& operator = (const Vec2& A) // ASSIGNMENT (=)
|
||||
{ x=A.x; y=A.y;
|
||||
return(*this); };
|
||||
|
||||
bool operator == (const Vec2& A) const // COMPARISON (==)
|
||||
{ return (x==A.x && y==A.y); }
|
||||
bool operator != (const Vec2& A) const // COMPARISON (!=)
|
||||
{ return (x!=A.x || y!=A.y); }
|
||||
|
||||
Vec2 operator + (const Vec2& A) const // ADDITION (+)
|
||||
{ Vec2 Sum(x+A.x, y+A.y);
|
||||
return(Sum); }
|
||||
Vec2 operator - (const Vec2& A) const // SUBTRACTION (-)
|
||||
{ Vec2 Diff(x-A.x, y-A.y);
|
||||
return(Diff); }
|
||||
Type operator * (const Vec2& A) const // DOT-PRODUCT (*)
|
||||
{ Type DotProd = x*A.x+y*A.y;
|
||||
return(DotProd); }
|
||||
Type operator / (const Vec2& A) const // CROSS-PRODUCT (/)
|
||||
{ Type CrossProd = x*A.y-y*A.x;
|
||||
return(CrossProd); }
|
||||
Type operator ^ (const Vec2& A) const // ALSO CROSS-PRODUCT (^)
|
||||
{ Type CrossProd = x*A.y-y*A.x;
|
||||
return(CrossProd); }
|
||||
Vec2 operator * (const Type s) const // MULTIPLY BY SCALAR (*)
|
||||
{ Vec2 Scaled(x*s, y*s);
|
||||
return(Scaled); }
|
||||
Vec2 operator / (const Type s) const // DIVIDE BY SCALAR (/)
|
||||
{ Vec2 Scaled(x/s, y/s);
|
||||
return(Scaled); }
|
||||
Vec2 operator & (const Vec2& A) const // COMPONENT MULTIPLY (&)
|
||||
{ Vec2 CompMult(x*A.x, y*A.y);
|
||||
return(CompMult); }
|
||||
|
||||
friend inline Vec2 operator *(Type s, const Vec2& v) // SCALAR MULT s*V
|
||||
{ return Vec2(v.x*s, v.y*s); }
|
||||
|
||||
Vec2& operator += (const Vec2& A) // ACCUMULATED VECTOR ADDITION (+=)
|
||||
{ x+=A.x; y+=A.y; return *this; }
|
||||
Vec2& operator -= (const Vec2& A) // ACCUMULATED VECTOR SUBTRACTION (-=)
|
||||
{ x-=A.x; y-=A.y; return *this; }
|
||||
Vec2& operator *= (const Type s) // ACCUMULATED SCALAR MULT (*=)
|
||||
{ x*=s; y*=s; return *this; }
|
||||
Vec2& operator /= (const Type s) // ACCUMULATED SCALAR DIV (/=)
|
||||
{ x/=s; y/=s; return *this; }
|
||||
Vec2& operator &= (const Vec2& A) // ACCUMULATED COMPONENT MULTIPLY (&=)
|
||||
{ x*=A.x; y*=A.y; return *this; }
|
||||
Vec2 operator - (void) const // NEGATION (-)
|
||||
{ Vec2 Negated(-x, -y);
|
||||
return(Negated); };
|
||||
|
||||
/*
|
||||
const Type& operator [] (const int i) const // ALLOWS VECTOR ACCESS AS AN ARRAY.
|
||||
{ return( (i==0)?x:y ); };
|
||||
Type & operator [] (const int i)
|
||||
{ return( (i==0)?x:y ); };
|
||||
*/
|
||||
|
||||
Type Length (void) const // LENGTH OF VECTOR
|
||||
{ return ((Type)sqrt(x*x+y*y)); };
|
||||
Type LengthSqr (void) const // LENGTH OF VECTOR (SQUARED)
|
||||
{ return (x*x+y*y); };
|
||||
Vec2& Normalize (void) // NORMALIZE VECTOR
|
||||
{ Type L = Length(); // CALCULATE LENGTH
|
||||
if (L>0) { x/=L; y/=L; }
|
||||
return *this;
|
||||
}; // DIV COMPONENTS BY LENGTH
|
||||
|
||||
Vec2 Perpendicular() const // RETURNS A PERPENDICULAR
|
||||
{ Vec2 Perp(-y,x);
|
||||
return(Perp); }
|
||||
|
||||
void UpdateMinMax(Vec2 &Min, Vec2 &Max)
|
||||
{
|
||||
if (x<Min.x) Min.x=x; else if (x>Max.x) Max.x=x;
|
||||
if (y<Min.y) Min.y=y; else if (y>Max.y) Max.y=y;
|
||||
}
|
||||
|
||||
void Print() const
|
||||
{ printf("(%.3f, %.3f)\n",x, y); }
|
||||
|
||||
static Vec2 ZERO;
|
||||
};
|
||||
|
||||
typedef Vec2<float> Vec2f;
|
||||
typedef Vec2<double> Vec2d;
|
||||
|
||||
template<class Type> Vec2<Type> Vec2<Type>::ZERO = Vec2<Type>(0,0);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
244
simgear/scene/sky/clouds3d/vec3f.hpp
Normal file
244
simgear/scene/sky/clouds3d/vec3f.hpp
Normal file
@@ -0,0 +1,244 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// File : vec3f.hpp
|
||||
//-----------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//==========================================================================
|
||||
// Vec3.hpp : 3d vector class template. Works for any integer or real type.
|
||||
//==========================================================================
|
||||
|
||||
#ifndef VEC3_H
|
||||
#define VEC3_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* @class Vec3
|
||||
* @brief A templated 3-vector class
|
||||
*
|
||||
* Everybody in graphics has to write their own basic 3-vector class.
|
||||
* And we're no exception. This one uses templates, so that with one
|
||||
* definition of the class you can have a 3-vector of floats or doubles
|
||||
* depending on how precise you are, or you can make 3-vectors of ints
|
||||
* or unsigned char, handy for representing colors.
|
||||
*
|
||||
* A couple of typedefs for common instatiations are provided by
|
||||
* default: Vec3f, and Vec3d, the float and double versions,
|
||||
* respectively.
|
||||
*
|
||||
*/
|
||||
template<class Type>
|
||||
class Vec3
|
||||
{
|
||||
public:
|
||||
Type x, y, z; ///< The storage for the three components of the vector
|
||||
|
||||
/// Default constructor.
|
||||
/// Note: does \em not initialize x, y, and z!
|
||||
Vec3 (void)
|
||||
{};
|
||||
/// Three component constructor
|
||||
Vec3 (const Type X, const Type Y, const Type Z)
|
||||
{ x=X; y=Y; z=Z; };
|
||||
/// Copy constructor
|
||||
Vec3 (const Vec3& v)
|
||||
{ x=v.x; y=v.y; z=v.z; };
|
||||
/// Construct from array
|
||||
Vec3 (const Type v[3])
|
||||
{ x=v[0]; y=v[1]; z=v[2]; };
|
||||
/// Set from components
|
||||
void Set (const Type X, const Type Y, const Type Z)
|
||||
{ x=X; y=Y; z=Z; }
|
||||
/// Set from array
|
||||
void Set (const Type v[3])
|
||||
{ x=v[0]; y=v[1]; z=v[2]; };
|
||||
|
||||
operator Type*() /// Type * CONVERSION
|
||||
{ return (Type *)&x; }
|
||||
operator const Type*() const /// CONST Type * CONVERSION
|
||||
{ return &x; }
|
||||
|
||||
bool operator == (const Vec3& A) const /// COMPARISON (==)
|
||||
{ return (x==A.x && y==A.y && z==A.z); }
|
||||
bool operator != (const Vec3& A) const /// COMPARISON (!=)
|
||||
{ return (x!=A.x || y!=A.y || z!=A.z); }
|
||||
|
||||
Vec3& operator = (const Vec3& A) /// ASSIGNMENT (=)
|
||||
{ x=A.x; y=A.y; z=A.z;
|
||||
return(*this); };
|
||||
Vec3 operator + (const Vec3& A) const /// ADDITION (+)
|
||||
{ Vec3 Sum(x+A.x, y+A.y, z+A.z);
|
||||
return(Sum); };
|
||||
Vec3 operator - (const Vec3& A) const /// SUBTRACTION (-)
|
||||
{ Vec3 Diff(x-A.x, y-A.y, z-A.z);
|
||||
return(Diff); };
|
||||
Type operator * (const Vec3& A) const /// DOT-PRODUCT (*)
|
||||
{ Type DotProd = x*A.x+y*A.y+z*A.z;
|
||||
return(DotProd); };
|
||||
Vec3 operator / (const Vec3& A) const /// CROSS-PRODUCT (/)
|
||||
{ Vec3 CrossProd(y*A.z-z*A.y, z*A.x-x*A.z, x*A.y-y*A.x);
|
||||
return(CrossProd); };
|
||||
Vec3 operator ^ (const Vec3& A) const /// ALSO CROSS-PRODUCT (^)
|
||||
{ Vec3 CrossProd(y*A.z-z*A.y, z*A.x-x*A.z, x*A.y-y*A.x);
|
||||
return(CrossProd); };
|
||||
Vec3 operator * (const Type s) const /// MULTIPLY BY SCALAR V*s (*)
|
||||
{ Vec3 Scaled(x*s, y*s, z*s);
|
||||
return(Scaled); };
|
||||
Vec3 operator / (const Type s) const /// DIVIDE BY SCALAR (/)
|
||||
{ Vec3 Scaled(x/s, y/s, z/s);
|
||||
return(Scaled); };
|
||||
Vec3 operator & (const Vec3& A) const /// COMPONENT MULTIPLY (&)
|
||||
{ Vec3 CompMult(x*A.x, y*A.y, z*A.z);
|
||||
return(CompMult); }
|
||||
|
||||
friend inline Vec3 operator *(Type s, const Vec3& v) /// SCALAR MULT s*V
|
||||
{ return Vec3(v.x*s, v.y*s, v.z*s); }
|
||||
|
||||
Vec3& operator += (const Vec3& A) /// ACCUMULATED VECTOR ADDITION (+=)
|
||||
{ x+=A.x; y+=A.y; z+=A.z;
|
||||
return *this;}
|
||||
Vec3& operator -= (const Vec3& A) /// ACCUMULATED VECTOR SUBTRACTION (-=)
|
||||
{ x-=A.x; y-=A.y; z-=A.z;
|
||||
return *this; }
|
||||
Vec3& operator *= (const Type s) /// ACCUMULATED SCALAR MULT (*=)
|
||||
{ x*=s; y*=s; z*=s;
|
||||
return *this; }
|
||||
Vec3& operator /= (const Type s) /// ACCUMULATED SCALAR DIV (/=)
|
||||
{ x/=s; y/=s; z/=s;
|
||||
return *this; }
|
||||
Vec3& operator &= (const Vec3& A) /// ACCUMULATED COMPONENT MULTIPLY (&=)
|
||||
{ x*=A.x; y*=A.y; z*=A.z; return *this; }
|
||||
Vec3 operator - (void) const /// NEGATION (-)
|
||||
{ Vec3 Negated(-x, -y, -z);
|
||||
return(Negated); };
|
||||
|
||||
/*
|
||||
const Type& operator [] (const int i) const // ALLOWS VECTOR ACCESS AS AN ARRAY.
|
||||
{ return( (i==0)?x:((i==1)?y:z) ); };
|
||||
Type & operator [] (const int i)
|
||||
{ return( (i==0)?x:((i==1)?y:z) ); };
|
||||
*/
|
||||
|
||||
Type Length (void) const /// LENGTH OF VECTOR
|
||||
{ return ((Type)sqrt(x*x+y*y+z*z)); };
|
||||
Type LengthSqr (void) const /// LENGTH OF VECTOR (SQUARED)
|
||||
{ return (x*x+y*y+z*z); };
|
||||
Vec3& Normalize (void) /// NORMALIZE VECTOR
|
||||
{ Type L = Length(); // CALCULATE LENGTH
|
||||
if (L>0) { x/=L; y/=L; z/=L; } // DIV COMPONENTS BY LENGTH
|
||||
return *this;
|
||||
};
|
||||
|
||||
/// Returns the 'star' matrix for a vector
|
||||
/** This is the skew-symmetric matrix \b A such that
|
||||
* \b A \b v == \p this x \b v
|
||||
* (the cross-product of \p this and \b v), for any vector \b v.
|
||||
* The matrix looks like this given vector (x,y,z):
|
||||
* @verbatim
|
||||
| 0 -z y|
|
||||
| z 0 -x|
|
||||
|-y x 0|
|
||||
@endverbatim
|
||||
*
|
||||
* Return format is just an array in row-major (OpenGL/Fortran) order.
|
||||
* That is [0, -z, y, z, 0, -x, -y, x, 0].
|
||||
*/
|
||||
Type* Star() const {
|
||||
Type s[] = ( 0, -z, y,
|
||||
z, 0, -x,
|
||||
-y, x, 0);
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Update \p Min and \p Max to enclose \p this
|
||||
/** A very handy routine for working with min-max or axis aligned
|
||||
* bounding boxes.
|
||||
*/
|
||||
void UpdateMinMax(Vec3 &Min, Vec3 &Max) const
|
||||
{
|
||||
if (x<Min.x) Min.x=x; else if (x>Max.x) Max.x=x;
|
||||
if (y<Min.y) Min.y=y; else if (y>Max.y) Max.y=y;
|
||||
if (z<Min.z) Min.z=z; else if (z>Max.z) Max.z=z;
|
||||
}
|
||||
|
||||
/// Construct an orthonormal basis from \p this
|
||||
/** Compute two unit vectors \p U and \p V that are orthogonal
|
||||
* to this vector and to each other. Note that \p *this need
|
||||
* not be a unit vector.
|
||||
*
|
||||
* The algorithm works as follows:
|
||||
* Find smallest component of L (this), zero it,
|
||||
* negate one of the other two and swap them. Then normalize.
|
||||
* Ex. if x1 is the smallest, assign (x2,y2,z2):=(0,z1,-y1)
|
||||
* Clearly now v1 dot v2 = x1*0 + y1*z1 + z1*-y1 = 0;
|
||||
* Zeroing out the smallest means that the magnitude of
|
||||
* the remaining vector will be as big as possible so that
|
||||
* when we normalize, we are safe from dividing by anything
|
||||
* close to zero (unless *this was near 0 magnitude to
|
||||
* begin with, in which case lack of precision can't be avoided)
|
||||
*/
|
||||
void CompleteOrthonormalBasis(Vec3 &U, Vec3 &V) const
|
||||
{
|
||||
U = *this;
|
||||
unsigned char s[3] = {0, 1, 2};
|
||||
unsigned char tmpa;
|
||||
U.x = U.x < 0 ? -U.x : -U.x;
|
||||
U.y = U.y < 0 ? -U.y : -U.y;
|
||||
U.z = U.z < 0 ? -U.z : -U.z;
|
||||
if ( U[0] > U[1] )
|
||||
{
|
||||
tmpa = s[0];
|
||||
s[0] = s[1];
|
||||
s[1] = tmpa;
|
||||
}
|
||||
// xy min in s[0] now.
|
||||
if ( U[s[0]] > U[2] ) {
|
||||
tmpa = s[2];
|
||||
s[2] = s[0];
|
||||
s[0] = tmpa;
|
||||
}
|
||||
// xyz min in s[0] now
|
||||
U = *this;
|
||||
U[s[0]] = 0;
|
||||
|
||||
// Voila U is now perpendicular to *this
|
||||
U.Normalize();
|
||||
|
||||
// And so it's easy to find a v that is too, with cross product.
|
||||
V = *this ^ U;
|
||||
// Or by removing components projected onto other two...
|
||||
// I think the cross product may be cheaper
|
||||
// V = something - V * (*this.Normalize() + U);
|
||||
|
||||
V.Normalize(); // wouldn't be necessary if we knew *this were normalized
|
||||
}
|
||||
|
||||
/// Dump the vector to \c stdout in a pretty way
|
||||
void Print() const
|
||||
{ printf("(%.3f, %.3f, %.3f)\n",x, y, z); }
|
||||
|
||||
/// This is a handy way to get the zero vector just use Vec3<Type>::ZERO
|
||||
static Vec3 ZERO;
|
||||
};
|
||||
|
||||
typedef Vec3<float> Vec3f;
|
||||
typedef Vec3<double> Vec3d;
|
||||
|
||||
template<class Type> Vec3<Type> Vec3<Type>::ZERO = Vec3<Type>(0,0,0);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
95
simgear/scene/sky/clouds3d/vec3fv.cpp
Normal file
95
simgear/scene/sky/clouds3d/vec3fv.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : vec3fv.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// vec3fv.cpp
|
||||
//============================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
void Set3fv(float v[3], float x, float y, float z)
|
||||
{
|
||||
v[0]=x;
|
||||
v[1]=y;
|
||||
v[2]=z;
|
||||
}
|
||||
|
||||
void Copy3fv(float A[3], const float B[3]) // A=B
|
||||
{
|
||||
A[0]=B[0];
|
||||
A[1]=B[1];
|
||||
A[2]=B[2];
|
||||
}
|
||||
|
||||
void ScalarMult3fv(float c[3], const float a[3], float s) // c=a*s
|
||||
{
|
||||
c[0] = a[0] * s;
|
||||
c[1] = a[1] * s;
|
||||
c[2] = a[2] * s;
|
||||
}
|
||||
|
||||
void ScalarDiv3fv(float v[3], float s)
|
||||
{
|
||||
v[0] /= s;
|
||||
v[1] /= s;
|
||||
v[2] /= s;
|
||||
}
|
||||
|
||||
void Add3fv(float c[3], const float a[3], const float b[3]) // c = a + b
|
||||
{
|
||||
c[0] = a[0] + b[0];
|
||||
c[1] = a[1] + b[1];
|
||||
c[2] = a[2] + b[2];
|
||||
}
|
||||
|
||||
void Subtract3fv(float c[3], const float a[3], const float b[3]) // c = a - b
|
||||
{
|
||||
c[0] = a[0] - b[0];
|
||||
c[1] = a[1] - b[1];
|
||||
c[2] = a[2] - b[2];
|
||||
}
|
||||
|
||||
void Negate3fv(float a[3], const float b[3]) // a = -b
|
||||
{
|
||||
a[0] = -b[0];
|
||||
a[1] = -b[1];
|
||||
a[2] = -b[2];
|
||||
}
|
||||
|
||||
float Length3fv(const float v[3])
|
||||
{
|
||||
return( (float)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) );
|
||||
}
|
||||
|
||||
void Normalize3fv(float v[3])
|
||||
{
|
||||
float l = Length3fv(v);
|
||||
v[0] /= l;
|
||||
v[1] /= l;
|
||||
v[2] /= l;
|
||||
}
|
||||
|
||||
float DotProd3fv(const float a[3], const float b[3])
|
||||
{
|
||||
return( a[0]*b[0] + a[1]*b[1] + a[2]*b[2] );
|
||||
}
|
||||
|
||||
void CrossProd3fv(float* C, const float* A, const float* B) // C = A X B
|
||||
{
|
||||
Set3fv(C, A[1]*B[2]-A[2]*B[1], A[2]*B[0]-A[0]*B[2], A[0]*B[1]-A[1]*B[0]);
|
||||
}
|
||||
34
simgear/scene/sky/clouds3d/vec3fv.hpp
Normal file
34
simgear/scene/sky/clouds3d/vec3fv.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : vec3fv.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//============================================================================
|
||||
// vec3fv.hpp
|
||||
//============================================================================
|
||||
|
||||
void Set3fv(float v[3], float x, float y, float z);
|
||||
void Copy3fv(float A[3], const float B[3]); // A=B
|
||||
|
||||
void ScalarMult3fv(float c[3], const float a[3], float s);
|
||||
void ScalarDiv3fv(float v[3], float s);
|
||||
void Add3fv(float c[3], const float a[3], const float b[3]); // c = a + b
|
||||
void Subtract3fv(float c[3], const float a[3], const float b[3]); // c = a - b
|
||||
void Negate3fv(float a[3], const float b[3]); // a = -b
|
||||
|
||||
float Length3fv(const float v[3]);
|
||||
void Normalize3fv(float v[3]);
|
||||
float DotProd3fv(const float a[3], const float b[3]);
|
||||
void CrossProd3fv(float* C, const float* A, const float* B); // C = A X B
|
||||
136
simgear/scene/sky/clouds3d/vec4f.hpp
Normal file
136
simgear/scene/sky/clouds3d/vec4f.hpp
Normal file
@@ -0,0 +1,136 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// File : vec4f.hpp
|
||||
//-----------------------------------------------------------------------------
|
||||
// GLVU : Copyright 1997 - 2002
|
||||
// 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 University of North Carolina at Chapel Hill makes no representations
|
||||
// about the suitability of this software for any purpose. It is provided
|
||||
// "as is" without express or implied warranty.
|
||||
|
||||
//==========================================================================
|
||||
// vec4.hpp : 4d vector class template. Works for any integer or real type.
|
||||
//==========================================================================
|
||||
|
||||
#ifndef VEC4_H
|
||||
#define VEC4_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
template <class Type>
|
||||
class Vec4
|
||||
{
|
||||
public:
|
||||
Type x, y, z, w;
|
||||
|
||||
Vec4 (void)
|
||||
{};
|
||||
Vec4 (const Type X, const Type Y, const Type Z, const Type W)
|
||||
{ x=X; y=Y; z=Z; w=W; };
|
||||
Vec4 (const Vec4& v)
|
||||
{ x=v.x; y=v.y; z=v.z; w=v.w; };
|
||||
Vec4 (const Type v[4])
|
||||
{ x=v[0]; y=v[1]; z=v[2]; w=v[3]; };
|
||||
void Set (const Type X, const Type Y, const Type Z, const Type W)
|
||||
{ x=X; y=Y; z=Z; w=W; }
|
||||
void Set (const Type v[4])
|
||||
{ x=v[0]; y=v[1]; z=v[2]; w=v[3]; };
|
||||
|
||||
operator Type*() // Type * CONVERSION
|
||||
{ return (Type *)&x; }
|
||||
operator const Type*() const // CONST Type * CONVERSION
|
||||
{ return &x; }
|
||||
|
||||
Vec4& operator = (const Vec4& A) // ASSIGNMENT (=)
|
||||
{ x=A.x; y=A.y; z=A.z; w=A.w;
|
||||
return(*this); };
|
||||
|
||||
bool operator == (const Vec4& A) const // COMPARISON (==)
|
||||
{ return (x==A.x && y==A.y &&
|
||||
z==A.z && w==A.w); }
|
||||
bool operator != (const Vec4& A) const // COMPARISON (!=)
|
||||
{ return (x!=A.x || y!=A.y ||
|
||||
z!=A.z || w!=A.w); }
|
||||
|
||||
Vec4 operator + (const Vec4& A) const // ADDITION (+)
|
||||
{ Vec4 Sum(x+A.x, y+A.y, z+A.z, w+A.w);
|
||||
return(Sum); };
|
||||
Vec4 operator - (const Vec4& A) const // SUBTRACTION (-)
|
||||
{ Vec4 Diff(x-A.x, y-A.y, z-A.z, w-A.w);
|
||||
return(Diff); };
|
||||
Type operator * (const Vec4& A) const // DOT-PRODUCT (*)
|
||||
{ Type DotProd = x*A.x+y*A.y+z*A.z+w*A.w;
|
||||
return(DotProd); };
|
||||
Vec4 operator * (const Type s) const // MULTIPLY BY SCALAR (*)
|
||||
{ Vec4 Scaled(x*s, y*s, z*s, w*s);
|
||||
return(Scaled); };
|
||||
Vec4 operator / (const Type s) const // DIVIDE BY SCALAR (/)
|
||||
{ Vec4 Scaled(x/s, y/s, z/s, w/s);
|
||||
return(Scaled); };
|
||||
Vec4 operator & (const Vec4& A) const // COMPONENT MULTIPLY (&)
|
||||
{ Vec4 CompMult(x*A.x, y*A.y, z*A.z, w*A.w);
|
||||
return(CompMult); }
|
||||
|
||||
friend inline Vec4 operator *(Type s, const Vec4& v) // SCALAR MULT s*V
|
||||
{ return Vec4(v.x*s, v.y*s, v.z*s, v.w*s); }
|
||||
|
||||
Vec4& operator += (const Vec4& A) // ACCUMULATED VECTOR ADDITION (+=)
|
||||
{ x+=A.x; y+=A.y; z+=A.z; w+=A.w;
|
||||
return *this; }
|
||||
Vec4& operator -= (const Vec4& A) // ACCUMULATED VECTOR SUBTRCT (-=)
|
||||
{ x-=A.x; y-=A.y; z-=A.z; w-=A.w;
|
||||
return *this; }
|
||||
Vec4& operator *= (const Type s) // ACCUMULATED SCALAR MULT (*=)
|
||||
{ x*=s; y*=s; z*=s; w*=s;
|
||||
return *this; }
|
||||
Vec4& operator /= (const Type s) // ACCUMULATED SCALAR DIV (/=)
|
||||
{ x/=s; y/=s; z/=s; w/=s;
|
||||
return *this; }
|
||||
Vec4& operator &= (const Vec4& A) // ACCUMULATED COMPONENT MULTIPLY (&=)
|
||||
{ x*=A.x; y*=A.y; z*=A.z; w*=A.w; return *this; }
|
||||
Vec4 operator - (void) const // NEGATION (-)
|
||||
{ Vec4 Negated(-x, -y, -z, -w);
|
||||
return(Negated); };
|
||||
|
||||
/*
|
||||
const Type& operator [] (const int i) const // ALLOWS VECTOR ACCESS AS AN ARRAY.
|
||||
{ return( (i==0)?x:((i==1)?y:((i==2)?z:w)) ); };
|
||||
Type & operator [] (const int i)
|
||||
{ return( (i==0)?x:((i==1)?y:((i==2)?z:w)) ); };
|
||||
*/
|
||||
|
||||
Type Length (void) const // LENGTH OF VECTOR
|
||||
{ return ((Type)sqrt(x*x+y*y+z*z+w*w)); };
|
||||
Type LengthSqr (void) const // LENGTH OF VECTOR (SQUARED)
|
||||
{ return (x*x+y*y+z*z+w*w); };
|
||||
Vec4& Normalize (void) // NORMALIZE VECTOR
|
||||
{ Type L = Length(); // CALCULATE LENGTH
|
||||
if (L>0) { x/=L; y/=L; z/=L; w/=L; }
|
||||
return *this;
|
||||
}; // DIV COMPONENTS BY LENGTH
|
||||
|
||||
void Wdiv(void)
|
||||
{ x/=w; y/=w; z/=w; w=1; }
|
||||
|
||||
void Print() const
|
||||
{ printf("(%.3f, %.3f, %.3f, %.3f)\n",x, y, z, w); }
|
||||
|
||||
static Vec4 ZERO;
|
||||
};
|
||||
|
||||
typedef Vec4<float> Vec4f;
|
||||
typedef Vec4<double> Vec4d;
|
||||
|
||||
template<class Type> Vec4<Type> Vec4<Type>::ZERO = Vec4<Type>(0,0,0,0);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user