Compare commits

..

43 Commits

Author SHA1 Message Date
curt
16bd8cef38 Updated for 0.3.1 2002-12-04 19:47:57 +00:00
curt
f2567f9af4 Fixes for 0.3.1 release. 2002-12-04 19:46:12 +00:00
curt
c363758449 Updated for 0.3.0 release. 2002-12-03 18:27:04 +00:00
curt
dfdeb8be9b Updated version number 2002-12-03 18:19:41 +00:00
curt
d1c8f60ca9 #include <simgear_config.h> as necessary. 2002-12-03 13:13:16 +00:00
curt
2fb961c922 NOMINMAX fix ... 2002-12-02 22:12:22 +00:00
david
2e17b28994 Includes patch from Erik Hofman. 2002-11-17 11:07:40 +00:00
david
c3f558b034 Cygwin patch from Patrick Staehlin:
To compile the development CVS version of FlightGear(0.9.0) i had to
apply some small changes to SimGear and FlightGear.

The changes need probably some additional ifdefs for other platforms but
since my linux-hd crashed i can't verify that.
2002-11-17 00:42:17 +00:00
david
65ce1a04b2 MS patch from Norm Vine to fix min/max macro defs. 2002-11-17 00:34:40 +00:00
david
3af4a19f76 Allow 'include' attribute on root PropertyList element. 2002-11-11 14:40:16 +00:00
david
5178f69f18 Simplified the command-manager interface. 2002-10-26 01:18:03 +00:00
curt
52e2005b3e Erik Hofman: fix an Irix build problem. 2002-10-24 13:59:33 +00:00
david
94fa51e3f7 Change int to GLenum for portability. 2002-10-18 20:25:21 +00:00
curt
590547e12d John W:
Attached is the new, improved SkyCloud.cpp. Tested on west coast @ KSFO and
east @ KJFK. Don't have any southern hemisphere or other airports to test
against, but you might give it a go and see what happens

Probably a good idea to add some user options to set cloud altitude, startup
position, etc, but for now this should suffice.
2002-10-04 16:44:23 +00:00
curt
c6832d2513 Fixes from Mark Harris. 2002-10-03 19:00:01 +00:00
curt
1fd63c30e9 Fix a texture state problem that caused clouds to occasionally flash all white. 2002-10-03 18:44:34 +00:00
curt
f08ae9f2ea John Wojnaroski:
Attached are the new files to transform the cloud field for local lat/lon.
2002-10-03 02:52:55 +00:00
curt
5c61e97358 ref() the cloud states before use so that if we are dyanmically creating and
deleting cloud layers we don't inadvertantly delete a cloud state.
2002-10-02 16:03:25 +00:00
curt
87e38e2617 Fix a tyop. 2002-09-22 03:42:26 +00:00
curt
92e1856caa Did I forget to commit John's loader patch?
Ran dos2unix on extgl.*
Include <simgear_config.h> from extgl.h so it properly picks up the WIN32
symbol.
2002-09-20 18:10:28 +00:00
curt
20c099b7ef Added extgl.c and extgl.h 2002-09-19 02:30:52 +00:00
curt
7eb74c7e2a Tweaks to build system following removal of interpreter subdir. 2002-09-18 20:38:40 +00:00
david
8d63c300e2 Removed simgear/interpreter directory; most likely we will use the new
PSL interpreted language in plib.
2002-09-18 20:27:17 +00:00
curt
01ccdd3ae1 Erik Hofman:
This patch fixes and STL problem, and adds (compile time) support for
architextures that don't support multitexturing.
2002-09-18 19:41:52 +00:00
curt
ab074726df Removed unnecessary files. 2002-09-18 18:47:47 +00:00
curt
ed26458a24 Norman's most recent 3d clouds code tweaks. 2002-09-18 14:24:19 +00:00
curt
fcf1d34e55 Latest changes from John. 2002-09-17 16:08:00 +00:00
curt
19f99ea273 Build with other simgear header files from source tree, not those that are
installed.
2002-09-17 01:16:18 +00:00
curt
fe5bb76def Latest changes from John Wojnaroski. 2002-09-16 14:55:31 +00:00
david
7ecf508453 Rolled Norm's change back out; update needs to be called earlier. 2002-09-16 13:13:49 +00:00
david
83e6e44eab Patches from Norm Vine to get clouds working (and add some debugging
information).
2002-09-16 02:26:20 +00:00
david
69a93342c0 Ignore generated files. 2002-09-15 10:42:54 +00:00
curt
e17338622a Change the header install directory.
Clean up a couple warnings.
2002-09-15 04:32:28 +00:00
david
a67fd7ea99 Added autom4te.cache. 2002-09-14 16:06:22 +00:00
david
cf2b8afbe9 Added stamp-h1. 2002-09-14 16:05:58 +00:00
david
a1e7761384 Removed /usr/local/include (as with plib). 2002-09-14 16:05:41 +00:00
david
d068915b42 Added newlines and did other clean-ups to eliminate errors and
minimize warnings compiling with g++ 3.2.
2002-09-14 16:03:39 +00:00
curt
adeb0d48fc Upgrade the version number. 2002-09-13 23:19:14 +00:00
curt
55c89ea865 Added simgear/sky/clouds3d to the build system. 2002-09-13 22:51:40 +00:00
curt
8bd07e358f Tweak lib name. 2002-09-13 20:36:19 +00:00
curt
01113e82f3 Initial revision. 2002-09-13 20:29:04 +00:00
curt
6d79582890 Initial revision 2002-09-07 02:58:19 +00:00
curt
2ae3c89406 For version 0.2.0 2002-09-07 01:45:46 +00:00
141 changed files with 20873 additions and 12193 deletions

View File

@@ -2,6 +2,7 @@ Makefile
Makefile.in
SimGear.spec
aclocal.m4
autom4te.cache
config.cache
config.log
config.status

View File

@@ -22,7 +22,7 @@ PROJECT_NAME = SimGear
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 0.0.19pre2
PROJECT_NUMBER = 0.3.1
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

View File

@@ -1,7 +1,6 @@
EXTRA_DIST = \
acinclude.m4 \
autogen.sh \
mksymlinks.sh \
README.MSVC \
README.metakit \
README.zlib \

16
NEWS
View File

@@ -1,3 +1,19 @@
New in 0.3.1
* December 4, 2002
* Fix a major packaging blunder with several missing files.
New in 0.3.0
* December 3, 2002
* removed interpreter subdir
* NOMINAX fix for Cygwin/gcc-3.2
* Added some prototype 3d clouds based on Mark Harris's demos.
* Simplified the command manager interface
* Allow an "include" attribute on root PropertyList element.
New in 0.2.0
* September 6, 2002

File diff suppressed because it is too large Load Diff

1
TODO Normal file
View File

@@ -0,0 +1 @@
03/25/2001 - Resolve location of Sky dome implimentation documentation.

View File

@@ -10,7 +10,7 @@ AC_CONFIG_SRCDIR([simgear/bucket/newbucket.cxx])
AC_PREREQ(2.52)
dnl Initialize the automake stuff
AM_INIT_AUTOMAKE(SimGear, 0.2.0)
AM_INIT_AUTOMAKE(SimGear, 0.3.1)
dnl Specify KAI C++ compiler and flags.
dnl Borrowed with slight modification from blitz distribution.
@@ -113,7 +113,7 @@ AM_CONDITIONAL(IS_CYGWIN, test "x$is_cygwin" = "xyes")
if test "x$HOSTTYPE" != "xmacintosh" -a "x$is_mingw" != "xyes"; then
dnl extra library and include directories
EXTRA_DIRS="/usr/local /usr/X11R6"
EXTRA_DIRS="/usr/X11R6"
if test -d /opt/X11R6 ; then
EXTRA_DIRS="$EXTRA_DIRS /opt/X11R6"
@@ -167,6 +167,8 @@ fi
dnl check for OpenGL related libraries
AM_CONDITIONAL(EXTGL_NEEDED, test "x$ac_cv_header_windows_h" = "xyes")
if test "x$HOSTTYPE" = "xmacintosh" ; then
dnl Macintosh OSX
LIBS="$LIBS -framework OpenGL -framework GLUT"
@@ -214,6 +216,7 @@ else
echo Win32 specific hacks...
AC_DEFINE([WIN32], 1, [Define for Win32 platforms])
AC_DEFINE([NOMINMAX], 1, [Define for Win32 platforms])
dnl just define these to true and hope for the best
ac_cv_lib_glut_glutGetModifiers="yes"
@@ -361,7 +364,6 @@ AC_CONFIG_FILES([ \
simgear/bucket/Makefile \
simgear/debug/Makefile \
simgear/ephemeris/Makefile \
simgear/interpreter/Makefile \
simgear/io/Makefile \
simgear/magvar/Makefile \
simgear/math/Makefile \
@@ -371,6 +373,7 @@ AC_CONFIG_FILES([ \
simgear/screen/Makefile \
simgear/serial/Makefile \
simgear/sky/Makefile \
simgear/sky/clouds3d/Makefile \
simgear/threads/Makefile \
simgear/timing/Makefile \
simgear/xgl/Makefile \

View File

@@ -1,42 +0,0 @@
#! /bin/sh
echo ""
echo "running $0 to rebuild simgear include links"
# toast the old directory
rm -rf src/simgear
mkdir src/simgear
mkdir src/simgear/bucket
mkdir src/simgear/debug
mkdir src/simgear/math
mkdir src/simgear/misc
mkdir src/simgear/screen
mkdir src/simgear/serial
mkdir src/simgear/xgl
mkdir src/simgear/zlib
# build new links
ln -s ../include/compiler.h src/simgear/compiler.h
ln -s ../include/constants.h src/simgear/constants.h
ln -s ../include/fg_traits.hxx src/simgear/fg_traits.hxx
ln -s ../include/fg_zlib.h src/simgear/fg_zlib.h
ln -s ../include/version.h src/simgear/version.h
ln -s ../../bucket/newbucket.hxx src/simgear/bucket/newbucket.hxx
ln -s ../../debug/debug_types.h src/simgear/debug/debug_types.h
ln -s ../../debug/logstream.hxx src/simgear/debug/logstream.hxx
ln -s ../../math/fg_memory.h src/simgear/math/fg_memory.h
ln -s ../../math/fg_types.hxx src/simgear/math/fg_types.hxx
ln -s ../../math/point3d.hxx src/simgear/math/point3d.hxx
ln -s ../../math/polar3d.hxx src/simgear/math/polar3d.hxx
ln -s ../../misc/fgpath.hxx src/simgear/misc/fgpath.hxx
ln -s ../../misc/fgstream.hxx src/simgear/misc/fgstream.hxx
ln -s ../../misc/zfstream.hxx src/simgear/misc/zfstream.hxx
ln -s ../../xgl/xgl.h src/simgear/xgl/xgl.h
ln -s ../../zlib/zlib.h src/simgear/zlib/zlib.h
ln -s ../../zlib/zconf.h src/simgear/zlib/zconf.h

View File

@@ -4,4 +4,5 @@ simgear_config.h
simgear_config.h.in
stamp-h
stamp-h.in
stamp-h1
version.h

View File

@@ -30,4 +30,4 @@ SUBDIRS = \
timing \
xgl
DIST_SUBDIRS = $(SUBDIRS) interpreter
DIST_SUBDIRS = $(SUBDIRS)

View File

@@ -24,6 +24,10 @@
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <math.h>
#include <simgear/misc/sg_path.hxx>

View File

@@ -141,7 +141,6 @@
# define STL_STDEXCEPT <stdexcept>
# define STL_STRING <string>
# define STL_STRSTREAM <strstream>
# else
# error Time to upgrade. GNU compilers < 2.7 not supported
# endif

View File

@@ -1,33 +0,0 @@
includedir = @includedir@/js
lib_LIBRARIES = libsginterp.a
include_HEADERS = \
interpreter.hxx
libsginterp_a_SOURCES = \
interpreter.cxx interpreter.hxx \
ixlib_javascript.hh \
js_array.cc \
js_expression.cc \
js_interpreter.cc \
js_value.cc \
js_declaration.cc \
js_instruction.cc \
js_library.cc \
lex.javascript.cc ixlib_token_lex.hh ixlib_token_javascript.hh \
scanner.cc ixlib_scanner.hh ixlib_scanjs.hh \
exbase.cc \
numeric.cc ixlib_numeric.hh \
numconv.cc ixlib_numconv.hh \
re.cc ixlib_re.hh ixlib_re_impl.hh \
exgen.cc ixlib_exgen.hh \
string.cc ixlib_string.hh \
ixlib_base.hh \
ixlib_exbase.hh \
ixlib_garbage.hh \
ixlib_i18n.hh \
ixlib_js_internals.hh \
ixlib_random.hh
INCLUDES = -I$(top_srcdir)

View File

@@ -1,77 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Exception handling
// ----------------------------------------------------------------------------
// (c) Copyright 1996 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <cstdio>
#include <cstring>
#include <ixlib_exbase.hh>
using namespace ixion;
// Description forms ----------------------------------------------------------
#define T_DESCRIPTION1 "[%s%04X] %s"
#define T_DESCRIPTION2 "[%s%04X] %s <%s>"
#define T_DESCRIPTION3 "[%s%04X] %s <%s,%d>"
#define T_DESCRIPTION1I "[%s%04X] %s (%s)"
#define T_DESCRIPTION2I "[%s%04X] %s (%s) <%s>"
#define T_DESCRIPTION3I "[%s%04X] %s (%s) <%s,%d>"
// base_exception -------------------------------------------------------------
char base_exception::RenderBuffer[EX_INFOMAX+1+100];
base_exception::base_exception(TErrorCode error,char const *info,char *module,
TIndex line,char *category)
: Error(error),Module(module),Line(line),Category(category) {
HasInfo = (info!=NULL);
if (info) {
if (strlen(info)>EX_INFOMAX) {
strncpy(Info,info,EX_INFOMAX);
Info[EX_INFOMAX] = '\0';
}
else strcpy(Info,info);
}
}
char const *base_exception::what() const throw () {
if (HasInfo) {
if (Module) {
if (Line)
sprintf(RenderBuffer,T_DESCRIPTION3I,Category,Error,getText(),Info,Module,Line);
else
sprintf(RenderBuffer,T_DESCRIPTION2I,Category,Error,getText(),Info,Module);
}
else
sprintf(RenderBuffer,T_DESCRIPTION1I,Category,Error,getText(),Info);
}
else {
if (Module) {
if (Line)
sprintf(RenderBuffer,T_DESCRIPTION3,Category,Error,getText(),Module,Line);
else
sprintf(RenderBuffer,T_DESCRIPTION2,Category,Error,getText(),Module);
}
else
sprintf(RenderBuffer,T_DESCRIPTION1,Category,Error,getText());
}
return RenderBuffer;
}

View File

@@ -1,46 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Generic exceptions
// ----------------------------------------------------------------------------
// (c) Copyright 1996 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include "ixlib_i18n.hh"
#include <ixlib_exgen.hh>
#include <ixlib_numconv.hh>
using namespace ixion;
static char *(PlainText[]) = {
N_("Unable to evaluate expression"),
N_("Function not yet implemented"),
N_("General error"),
N_("NULL pointer encountered"),
N_("Invalid parameter"),
N_("Index out of range"),
N_("Buffer overrun"),
N_("Buffer underrun"),
N_("Item not found"),
N_("Invalid operation"),
N_("Dimension mismatch"),
N_("Operation cancelled"),
N_("Unable to operate on empty set"),
N_("Unable to remove GC entry"),
N_("Unable to protect non-freeable entry")
};
// generic_exception ----------------------------------------------------------
char const *generic_exception::getText() const {
return _(PlainText[Error]);
}

View File

@@ -1,9 +0,0 @@
#include "interpreter.hxx"
SGInterpreter::SGInterpreter ()
{
}
SGInterpreter::~SGInterpreter ()
{
}

View File

@@ -1,13 +0,0 @@
#ifndef __INTERPRETER_HXX
#define __INTERPRETER_HXX 1
class SGInterpreter
{
public:
SGInterpreter ();
virtual ~SGInterpreter ();
};
#endif

View File

@@ -1,107 +0,0 @@
/* ----------------------------------------------------------------------------
Description : iXiONmedia library base declarations
----------------------------------------------------------------------------
(c) Copyright 1996 by iXiONmedia, all rights reserved.
----------------------------------------------------------------------------
This header must be C-safe for autoconf purposes.
*/
#ifndef IXLIB_BASE
#define IXLIB_BASE
#undef HAVE_CONFIG_H
#ifdef HAVE_CONFIG_H
#include <ixlib_config.hh>
#undef PACKAGE
#undef VERSION
#endif
#ifdef __cplusplus
namespace ixion {
extern "C" {
#endif
/* Aliases --------------------------------------------------------------------
*/
const double Pi = 3.141592653589793285;
const double Euler = 2.718281828;
const double Gravity = 9.8065; // m/s^2
const double UniGravity = 6.673e-11; // m^3/kg s^2
const double Epsilon0 = 8.8542e-12; // F/m
const double Mu0 = 1.2566e-6; // H/m
const double LightSpeed = 2.9972e8; // m/s
const double Planck = 6.6261e-34; // Js
/* STL Helper macro -----------------------------------------------------------
*/
#define FOREACH(VAR,LIST,LISTTYPE) \
for (LISTTYPE::iterator VAR = (LIST).begin(),last = (LIST).end();VAR != last;VAR++)
#define FOREACH_CONST(VAR,LIST,LISTTYPE) \
for (LISTTYPE::const_iterator VAR = (LIST).begin(),last = (LIST).end();VAR != last;VAR++)
/* Nomenclature typedefs ------------------------------------------------------
*/
typedef unsigned char TUnsigned8;
typedef unsigned short TUnsigned16;
typedef unsigned long TUnsigned32;
typedef unsigned long long TUnsigned64;
typedef signed char TSigned8;
typedef signed short TSigned16;
typedef signed long TSigned32;
typedef signed long long TSigned64;
typedef TSigned8 TDelta8;
typedef TSigned16 TDelta16;
typedef TSigned32 TDelta32;
typedef TSigned64 TDelta64;
typedef signed TDelta;
typedef TUnsigned8 TSize8;
typedef TUnsigned16 TSize16;
typedef TUnsigned32 TSize32;
typedef TUnsigned64 TSize64;
typedef unsigned TSize;
typedef TUnsigned8 TIndex8;
typedef TUnsigned16 TIndex16;
typedef TUnsigned32 TIndex32;
typedef TUnsigned64 TIndex64;
typedef unsigned TIndex;
typedef TUnsigned8 TByte;
int ixlibGetMajorVersion();
int ixlibGetMinorVersion();
int ixlibGetMicroVersion();
void ixlibInitI18n();
#ifdef __cplusplus
}
}
#endif
#endif

View File

@@ -1,72 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Exception handling
// ----------------------------------------------------------------------------
// (c) Copyright 1996 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_EXBASE
#define IXLIB_EXBASE
#include <stdexcept>
#include <ixlib_base.hh>
// constants ------------------------------------------------------------------
#define EX_INFOMAX 255
// throw macro ----------------------------------------------------------------
#define EX_THROW(TYPE,CODE)\
throw ::ixion::TYPE##_exception(CODE,NULL,__FILE__,__LINE__);
#define EX_THROWINFO(TYPE,CODE,INFO)\
throw ::ixion::TYPE##_exception(CODE,(char const *) INFO,__FILE__,__LINE__);
#define EX_CATCHCODE(TYPE,CODE,HANDLER)\
catch (TYPE##_exception &ex) { \
if (ex.Error != CODE) throw; \
HANDLER \
}
#define EX_CONVERT(TYPE,CODE,DESTTYPE,DESTCODE)\
catch (TYPE##_exception &ex) { \
if (ex.Error != CODE) throw; \
throw DESTTYPE##_exception(DESTCODE,ex.Info,__FILE__,__LINE__); \
}
// xBaseException -------------------------------------------------------------
namespace ixion {
typedef unsigned int TErrorCode;
struct base_exception : public std::exception {
TErrorCode Error;
char *Module;
TIndex Line;
char *Category;
bool HasInfo;
char Info[EX_INFOMAX+1];
static char RenderBuffer[EX_INFOMAX+1+100];
base_exception(TErrorCode error,char const *info = NULL,char *module = NULL,
TIndex line = 0,char *category = NULL);
char const *what() const throw ();
virtual const char *getText() const = 0;
};
}
#endif

View File

@@ -1,67 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Generic exceptions
// ----------------------------------------------------------------------------
// (c) Copyright 1996 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_EXGEN
#define IXLIB_EXGEN
#include <ixlib_exbase.hh>
// Error codes ----------------------------------------------------------------
#define EC_CANNOTEVALUATE 0
#define EC_NOTYETIMPLEMENTED 1
#define EC_ERROR 2
#define EC_NULLPOINTER 3
#define EC_INVALIDPAR 4
#define EC_INDEX 5
#define EC_BUFFEROVERFLOW 6
#define EC_BUFFERUNDERFLOW 7
#define EC_ITEMNOTFOUND 8
#define EC_INVALIDOP 9
#define EC_DIMENSIONMISMATCH 10
#define EC_CANCELLED 11
#define EC_EMPTYSET 12
#define EC_CANNOTREMOVEFROMGC 13
#define EC_REMAININGREF 14
#define ECMEM_GENERAL 0
// Throw macro ----------------------------------------------------------------
#define EXGEN_THROW(CODE)\
EX_THROW(generic,CODE)
#define EXGEN_THROWINFO(CODE,INFO)\
EX_THROWINFO(generic,CODE,INFO)
#define EXGEN_NYI\
EXGEN_THROW(EC_NOTYETIMPLEMENTED)
namespace ixion {
// generic_exception ----------------------------------------------------------
struct generic_exception : public base_exception {
generic_exception(TErrorCode error,char const *info = NULL,char *module = NULL,
TIndex line = 0)
: base_exception(error,info,module,line,"GEN") {
}
virtual char const *getText() const;
};
}
#endif

View File

@@ -1,491 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Garbage collection
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_GARBAGE
#define IXLIB_GARBAGE
#include <memory>
#include <ixlib_exgen.hh>
#include <ixlib_base.hh>
namespace ixion {
template<class T>
class delete_deallocator {
public:
void operator()(T const *instance) {
delete instance;
}
};
template<class T>
class delete_array_deallocator {
public:
void operator()(T const *instance) {
delete[] instance;
}
};
template<class T,class Deallocator = delete_deallocator<T> >
class reference_manager;
template<class T>
class ref_base {
protected:
T *Instance;
public:
ref_base(T *instance = NULL)
: Instance(instance) {
}
ref_base(ref_base const &src)
: Instance(src.Instance) {
}
// comparison
bool operator==(ref_base const &op2) const {
return Instance == op2.Instance;
}
// smart pointer nitty-gritty
T &operator*() const {
return *Instance;
}
T *operator->() const {
return Instance;
}
T *operator+(TIndex index) const {
return Instance + index;
}
T &operator[](TIndex index) const {
return Instance[index];
}
// methods
T *get() const {
return Instance;
}
};
template<class T,class T_Managed = T>
class ref;
template<class T,class T_Managed = T>
class no_free_ref;
template<class T_Managed>
class reference_manager_keeper {
public:
// *** FIXME should be private, but cannot be
// (partial specializations cannot be declared friends)
static reference_manager<T_Managed> Manager;
};
/**
An object that acts like a reference-counted pointer to an object.
The corresponding reference_manager is identified implicitly through
static references.
Example:
<code>
IXLIB_GARBAGE_DECLARE_MANAGER(int)
int main() {
ref<int> my_int = new int(5);
*my_int = 17;
ref<int> another_int = my_int;
*another_int = 12;
*my_int == 12; // true
}
</code>
*/
template<class T,class T_Managed>
class ref : public ref_base<T> {
public:
// we have to have an explicit copy constructor, otherwise the
// compiler generates one, which is *ahem* - fatal
ref(ref const &src)
: ref_base<T>(src) {
reference_manager_keeper<T_Managed>::Manager.addReference(Instance);
}
template<class T2>
ref(ref<T2,T_Managed> const &src)
: ref_base<T>(src.get()) {
reference_manager_keeper<T_Managed>::Manager.addReference(Instance);
}
template<class T2>
ref(no_free_ref<T2,T_Managed> const &src)
: ref_base<T>(src.get()) {
reference_manager_keeper<T_Managed>::Manager.addReference(Instance);
}
ref(T *instance = NULL)
: ref_base<T>(instance) {
reference_manager_keeper<T_Managed>::Manager.addReference(Instance);
}
~ref() {
reference_manager_keeper<T_Managed>::Manager.freeReference(Instance);
}
ref &operator=(ref const &src) {
set(src.get());
return *this;
}
ref &operator=(T *ptr) {
set(ptr);
return *this;
}
// methods
void release() {
reference_manager_keeper<T_Managed>::Manager.freeReference(Instance);
Instance = NULL;
}
void set(T *instance) {
if (instance == Instance) return;
reference_manager_keeper<T_Managed>::Manager.freeReference(Instance);
Instance = instance;
reference_manager_keeper<T_Managed>::Manager.addReference(Instance);
}
T *releaseFromGCArena() {
T *oldinst = Instance;
reference_manager_keeper<T_Managed>::Manager.forgetReference(Instance);
Instance = NULL;
return oldinst;
}
};
/**
An object that acts like a reference-counted pointer to an object.
However, the referenced object is not freed if the no_free_ref
is the last reference to the object to go out of scope.
This is useful to pass objects allocated e.g. on the stack along
inside ref's, while making sure they aren't freed.
(which would most probably lead to disaster)
no_free_ref's are mostly a hack, but there are situations where you cannot
avoid them. But even so, you should try not to use them where possible.
The corresponding reference_manager is identified implicitly through
static references.
*/
template<class T,class T_Managed>
class no_free_ref : public ref_base<T>{
public:
// we have to have an explicit copy constructor, otherwise the
// compiler generates one, which is *ahem* - fatal
no_free_ref(no_free_ref const &src)
: ref_base<T>(src) {
reference_manager_keeper<T_Managed>::Manager.addNoFreeReference(Instance);
}
template<class T2>
no_free_ref(ref<T2,T_Managed> const &src)
: ref_base<T>(src.get()) {
reference_manager_keeper<T_Managed>::Manager.addNoFreeReference(Instance);
}
template<class T2>
no_free_ref(no_free_ref<T2,T_Managed> const &src)
: ref_base<T>(src.get()) {
reference_manager_keeper<T_Managed>::Manager.addNoFreeReference(Instance);
}
no_free_ref(T *instance = NULL)
: ref_base<T>(instance) {
reference_manager_keeper<T_Managed>::Manager.addNoFreeReference(Instance);
}
~no_free_ref() {
reference_manager_keeper<T_Managed>::Manager.removeNoFreeReference(Instance);
}
// assignment
no_free_ref &operator=(no_free_ref const &src) {
set(src.get());
return *this;
}
no_free_ref &operator=(T *ptr) {
set(ptr);
return *this;
}
// methods
void release() {
reference_manager_keeper<T_Managed>::Manager.removeNoFreeReference(Instance);
Instance = NULL;
}
void set(T *instance) {
if (instance == Instance) return;
reference_manager_keeper<T_Managed>::Manager.removeNoFreeReference(Instance);
Instance = instance;
reference_manager_keeper<T_Managed>::Manager.addNoFreeReference(Instance);
}
T *releaseFromGCArena() {
T *oldinst = Instance;
reference_manager_keeper<T_Managed>::Manager.forgetReference(Instance);
Instance = NULL;
return oldinst;
}
};
/**
An object that acts like a reference-counted pointer to an object.
The corresponding reference_manager is identified explicitly.
*/
template<class T>
class dynamic_ref : public ref_base<T> {
protected:
reference_manager<T> &Manager;
public:
dynamic_ref(dynamic_ref const &src)
: ref_base<T>(src),Manager(src.Manager) {
Manager.addReference(Instance);
}
dynamic_ref(reference_manager<T> &mgr,T *instance = NULL)
: ref_base<T>(instance),Manager(mgr) {
Manager.addReference(Instance);
}
~dynamic_ref() {
Manager.freeReference(Instance);
}
// assignment
dynamic_ref &operator=(dynamic_ref const &src) {
set(src.get());
return *this;
}
dynamic_ref &operator=(T *ptr) {
set(ptr);
return *this;
}
// methods
void release() {
Manager.freeReference(Instance);
Instance = NULL;
}
void set(T *instance) {
if (instance == Instance) return;
Manager.freeReference(Instance);
Instance = instance;
Manager.addReference(Instance);
}
T *releaseFromGCArena() {
T *oldinst = Instance;
Manager.forgetReference(Instance);
Instance = NULL;
return oldinst;
}
};
/**
An object that acts like a reference-counted pointer to an object.
However, the referenced object is not freed if the no_free_ref
is the last reference to the object to go out of scope.
This is useful to pass objects allocated e.g. on the stack along
inside ref's, while making sure they aren't freed.
(which would most probably lead to disaster)
no_free_ref's are mostly a hack, but there are situations where you cannot
avoid them. But even so, you should try not to use them where possible.
The corresponding reference_manager is identified explicitly.
*/
template<class T>
class no_free_dynamic_ref : public ref_base<T> {
protected:
reference_manager<T> &Manager;
public:
no_free_dynamic_ref(no_free_dynamic_ref const &src)
: ref_base<T>(src),Manager(src.Manager) {
Manager.addNoFreeReference(Instance);
}
no_free_dynamic_ref(reference_manager<T> &mgr,T *instance = NULL)
: ref_base<T>(instance),Manager(mgr) {
Manager.addNoFreeReference(Instance);
}
~no_free_dynamic_ref() {
Manager.removeNoFreeReference(Instance);
}
// assignment
no_free_dynamic_ref &operator=(no_free_dynamic_ref const &src) {
set(src.get());
return *this;
}
no_free_dynamic_ref &operator=(T *ptr) {
set(ptr);
return *this;
}
// methods
void release() {
Manager.removeNoFreeReference(Instance);
Instance = NULL;
}
void set(T *instance) {
if (instance == Instance) return;
Manager.removeNoFreeReference(Instance);
Instance = instance;
Manager.addNoFreeReference(Instance);
}
T *releaseFromGCArena() {
T *oldinst = Instance;
Manager.forgetReference(Instance);
Instance = NULL;
return oldinst;
}
};
template<class T,class Deallocator>
class reference_manager {
protected:
struct instance_data {
T const *Instance;
TSize ReferenceCount,NoFreeReferenceCount;
instance_data *Next,*Previous;
};
class pointer_hash {
public:
};
typedef unsigned hash_value;
static hash_value const HASH_MAX = 0x3ff;
instance_data *Instances[HASH_MAX+1];
Deallocator Dealloc;
public:
reference_manager(Deallocator const &dealloc = Deallocator())
: Dealloc(dealloc) {
for (hash_value hv = 0;hv <= HASH_MAX;hv++)
Instances[hv] = NULL;
}
// *** FIXME should be
// protected:
// but cannot because partial specializations cannot be declared friends
void addReference(T const *instance) {
if (!instance) return;
instance_data *data = getHashEntry(instance);
data->ReferenceCount++;
}
void freeReference(T const *instance) {
if (!instance) return;
instance_data *data = getHashEntry(instance);
if (--data->ReferenceCount == 0 && data->NoFreeReferenceCount == 0) {
removeHashEntry(data);
Dealloc(instance);
}
}
void addNoFreeReference(T const *instance) {
if (!instance) return;
instance_data *data = getHashEntry(instance);
data->NoFreeReferenceCount++;
}
void removeNoFreeReference(T const *instance) {
if (!instance) return;
instance_data *data = getHashEntry(instance);
if (--data->NoFreeReferenceCount == 0) {
if (data->ReferenceCount != 0)
EXGEN_THROW(EC_REMAININGREF)
removeHashEntry(data);
}
}
void forgetReference(T const *instance) {
if (!instance) return;
instance_data *data = getHashEntry(instance);
if (data->ReferenceCount != 1)
EXGEN_THROW(EC_CANNOTREMOVEFROMGC)
removeHashEntry(data);
}
private:
hash_value hash(T const *ptr) const {
unsigned u = reinterpret_cast<unsigned>(ptr);
return (u ^ (u >> 8) ^ (u >> 16) ^ (u >> 24)) & HASH_MAX;
}
instance_data *getHashEntry(T const *instance) {
instance_data *data = Instances[hash(instance)];
while (data) {
if (data->Instance == instance) return data;
data = data->Next;
}
// not found, add new at front
instance_data *link = Instances[hash(instance)];
data = new instance_data;
data->Instance = instance;
data->ReferenceCount = 0;
data->NoFreeReferenceCount = 0;
data->Previous = NULL;
data->Next = link;
if (link) link->Previous = data;
Instances[hash(instance)] = data;
return data;
}
void removeHashEntry(instance_data *data) {
instance_data *prev = data->Previous;
if (prev) {
prev->Next = data->Next;
if (data->Next) data->Next->Previous = prev;
delete data;
}
else {
Instances[hash(data->Instance)] = data->Next;
if (data->Next) data->Next->Previous = NULL;
delete data;
}
}
};
#define IXLIB_GARBAGE_DECLARE_MANAGER(TYPE) \
ixion::reference_manager<TYPE> ixion::reference_manager_keeper<TYPE>::Manager;
}
#endif

View File

@@ -1,23 +0,0 @@
// ----------------------------------------------------------------------------
// Description : ixlib internationalization wrapper
// ----------------------------------------------------------------------------
// (c) Copyright 2001 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_I18N
#include <string>
#include <libintl.h>
#define _(String) gettext(String)
#define N_(String) (String)
#endif

View File

@@ -1,380 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Javascript interpreter
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_JAVASCRIPT
#define IXLIB_JAVASCRIPT
#include <vector>
#if __GNUC__ < 3
#include <hash_map>
#else
#include <ext/hash_map>
#endif
#include <ixlib_string.hh>
#include <ixlib_exbase.hh>
#include <ixlib_garbage.hh>
#include <ixlib_scanner.hh>
// Error codes ----------------------------------------------------------------
#define ECJS_UNTERMINATED_COMMENT 0
#define ECJS_CANNOT_CONVERT 1
#define ECJS_INVALID_OPERATION 2
#define ECJS_UNEXPECTED 3
#define ECJS_UNEXPECTED_EOF 4
#define ECJS_CANNOT_MODIFY_RVALUE 5
#define ECJS_UNKNOWN_IDENTIFIER 6
#define ECJS_UNKNOWN_OPERATOR 7
#define ECJS_INVALID_NON_LOCAL_EXIT 8
#define ECJS_INVALID_NUMBER_OF_ARGUMENTS 9
#define ECJS_INVALID_TOKEN 10
#define ECJS_CANNOT_REDECLARE 11
#define ECJS_DOUBLE_CONSTRUCTION 12
#define ECJS_NO_SUPERCLASS 13
#define ECJS_DIVISION_BY_ZERO 14
// helpful macros -------------------------------------------------------------
#define IXLIB_JS_ASSERT_PARAMETERS(NAME,ARGMIN,ARGMAX) \
if (parameters.size() < ARGMIN || parameters.size() > ARGMAX) \
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,NAME)
#define IXLIB_JS_IF_METHOD(NAME,ARGMIN,ARGMAX) \
if (identifier == NAME) \
if (parameters.size() < ARGMIN || parameters.size() > ARGMAX) \
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,NAME) \
else
#define IXLIB_JS_DECLARE_FUNCTION(NAME) \
namespace { \
class NAME : public value { \
public: \
value_type getType() const { \
return VT_FUNCTION; \
} \
ixion::ref<ixion::javascript::value> call(parameter_list const &parameters); \
}; \
} \
ixion::ref<ixion::javascript::value> NAME::call(parameter_list const &parameters)
#define IXLIB_JS_CONVERT_PARAMETERS_0 \
// Exception throw macros -----------------------------------------------------
#define EXJS_THROW(CODE)\
EX_THROW(javascript,CODE)
#define EXJS_THROWINFO(CODE,INFO)\
EX_THROWINFO(javascript,CODE,INFO)
#define EXJS_THROW_NO_LOCATION(CODE)\
EX_THROW(no_location_javascript,CODE)
#define EXJS_THROWINFO_NO_LOCATION(CODE,INFO)\
EX_THROWINFO(no_location_javascript,CODE,INFO)
#define EXJS_THROWINFOLOCATION(CODE,INFO,LOCATION)\
throw ixion::javascript_exception(CODE,LOCATION,INFO,__FILE__,__LINE__);
#define EXJS_THROWINFOTOKEN(CODE,INFO,TOKEN)\
EXJS_THROWINFOLOCATION(CODE,INFO,code_location(TOKEN))
#define EXJS_THROWINFOEXPRESSION(CODE,INFO,EXPR)\
EXJS_THROWINFOLOCATION(CODE,INFO,(EXPR).getCodeLocation())
namespace ixion {
namespace javascript {
struct code_location;
}
// exceptions ---------------------------------------------------------------
struct no_location_javascript_exception : public base_exception {
no_location_javascript_exception(TErrorCode error,char const *info = NULL,char *module = NULL,
TIndex line = 0)
: base_exception(error,info,module,line,"JS") {
}
virtual char *getText() const;
};
struct javascript_exception : public base_exception {
javascript_exception(TErrorCode error,char const *info = NULL,char *module = NULL,
TIndex line = 0)
: base_exception(error,info,module,line,"JS") {
}
javascript_exception(TErrorCode error,javascript::code_location const &loc,char const *info = 0,char *module = NULL,
TIndex line = 0);
javascript_exception(no_location_javascript_exception const &half_ex,javascript::code_location const &loc);
virtual char *getText() const;
};
// javascript ---------------------------------------------------------------
/**
This code tries to be an implementation of ECMAScript 4, as available at
http://www.mozilla.org/js/language/
Note that ES4 is still in the process of standardization.
It is meant to behave like an ES4 interpreter in strict mode, none
of the backward-compatible braindead-isms like newline semicolon
insertion and other stuff will ever be implemented.
This is the list of its shortcomings:
<ul>
<li> exceptions
<li> namespaces,packages
<li> constness
<li> Number/String constructor and class methods
<li> real regexp's
<li> the methods listed in FIXME's (js_library.cc js_value.cc)
<li> cannot cross-assign predefined methods [won't be]
<li> Grammatical semicolon insertion [won't be]
<li> type declaration [won't be]
</ul>
Be advised that a javascript value that is passed to you through the
interpreter, e.g. as a call parameter, may not be of the type that
you expect. For example, in "var x = 4; f(x);", what comes in as
the parameter x into f is a wrapper value that adds assign()ability
to a value that is wrapped inside. The advised solution to get the
object that you expect is to call eliminateWrappers() on the potentially
wrapped value.
*/
namespace javascript {
class value;
class list_scope;
struct context {
ref<list_scope,value> DeclarationScope;
ref<value> LookupScope;
context(ref<list_scope,value> scope);
context(ref<value> scope);
context(ref<list_scope,value> decl_scope,ref<value> lookup_scope);
};
class expression;
class value {
public:
enum operator_id {
// unary, modifying
OP_PRE_INCREMENT,OP_POST_INCREMENT,
OP_PRE_DECREMENT,OP_POST_DECREMENT,
// unary, non-modifying
OP_UNARY_PLUS,OP_UNARY_MINUS,
OP_LOG_NOT,OP_BIN_NOT,
// binary, modifying
OP_PLUS_ASSIGN,OP_MINUS_ASSIGN,
OP_MUTLIPLY_ASSIGN,OP_DIVIDE_ASSIGN,OP_MODULO_ASSIGN,
OP_BIT_AND_ASSIGN,OP_BIT_OR_ASSIGN,OP_BIT_XOR_ASSIGN,
OP_LEFT_SHIFT_ASSIGN,OP_RIGHT_SHIFT_ASSIGN,
// binary, non-modifying
OP_PLUS,OP_MINUS,
OP_MULTIPLY,OP_DIVIDE,OP_MODULO,
OP_BIT_AND,OP_BIT_OR,OP_BIT_XOR,
OP_LEFT_SHIFT,OP_RIGHT_SHIFT,
OP_LOGICAL_OR,OP_LOGICAL_AND,
OP_EQUAL,OP_NOT_EQUAL,OP_IDENTICAL,OP_NOT_IDENTICAL,
OP_LESS_EQUAL,OP_GREATER_EQUAL,OP_LESS,OP_GREATER,
// special
OP_ASSIGN,
};
enum value_type {
VT_UNDEFINED,VT_NULL,
VT_INTEGER,VT_FLOATING_POINT,VT_STRING,
VT_FUNCTION,VT_OBJECT,VT_BUILTIN,VT_HOST,
VT_SCOPE,VT_BOUND_METHOD,VT_TYPE
};
typedef std::vector<ref<value> > parameter_list;
virtual ~value() {
}
virtual value_type getType() const = 0;
virtual std::string toString() const;
virtual int toInt() const;
virtual double toFloat() const;
virtual bool toBoolean() const;
// toString is meant as a type conversion, whereas stringify
// is for debuggers and the like
virtual std::string stringify() const;
virtual ref<value> eliminateWrappers();
virtual ref<value> duplicate();
virtual ref<value> lookup(std::string const &identifier);
virtual ref<value> subscript(value const &index);
virtual ref<value> call(parameter_list const &parameters);
virtual ref<value> callAsMethod(ref<value> instance,parameter_list const &parameters);
virtual ref<value> construct(parameter_list const &parameters);
virtual ref<value> assign(ref<value> op2);
virtual ref<value> operatorUnary(operator_id op) const;
virtual ref<value> operatorBinary(operator_id op,ref<value> op2) const;
virtual ref<value> operatorBinaryShortcut(operator_id op,expression const &op2,context const &ctx) const;
virtual ref<value> operatorUnaryModifying(operator_id op);
virtual ref<value> operatorBinaryModifying(operator_id op,ref<value> op2);
static operator_id token2operator(scanner::token const &token,bool unary = false,bool prefix = false);
static std::string operator2string(operator_id op);
static std::string valueType2string(value_type vt);
};
// obviously, any value can have methods, but with this neat little
// interface implementing methods has just become easier.
class value_with_methods : public value {
class bound_method : public value {
std::string Identifier;
ref<value_with_methods,value> Parent;
public:
bound_method(std::string const &identifier,ref<value_with_methods,value> parent);
value_type getType() const {
return VT_BOUND_METHOD;
}
ref<value> duplicate();
ref<value> call(parameter_list const &parameters);
};
public:
ref<value> lookup(std::string const &identifier);
virtual ref<value> callMethod(std::string const &identifier,parameter_list const &parameters) = 0;
};
// obviously, any value can already represent a scope ("lookup" member!).
// the list_scope class is an explicit scope that can "swallow"
// (=unite with) other scopes and keeps a list of registered members
class list_scope : public value {
protected:
typedef std::hash_map<std::string,ref<value>,string_hash> member_map;
typedef std::vector<ref<value> > swallowed_list;
member_map MemberMap;
swallowed_list SwallowedList;
public:
value_type getType() const {
return VT_SCOPE;
}
ref<value> lookup(std::string const &identifier);
void unite(ref<value> scope);
void separate(ref<value> scope);
void clearScopes();
bool hasMember(std::string const &name) const;
void addMember(std::string const &name,ref<value> member);
void removeMember(std::string const &name);
void clearMembers();
void clear();
};
class js_array : public value_with_methods {
private:
typedef value_with_methods super;
protected:
typedef std::vector<ref<value> > value_array;
value_array Array;
public:
js_array() {
}
js_array(TSize size);
js_array(value_array::const_iterator first,value_array::const_iterator last)
: Array(first,last) {
}
js_array(js_array const &src)
: Array(src.Array) {
}
value_type getType() const {
return VT_BUILTIN;
}
std::string stringify() const;
ref<value> duplicate();
ref<value> lookup(std::string const &identifier);
ref<value> subscript(value const &index);
ref<value> callMethod(std::string const &identifier,parameter_list const &parameters);
TSize size() const {
return Array.size();
}
void resize(TSize size);
ref<value> &operator[](TIndex idx);
void push_back(ref<value> val);
};
class expression;
ref<value> makeUndefined();
ref<value> makeNull();
ref<value> makeValue(signed long val);
ref<value> makeConstant(signed long val);
ref<value> makeValue(signed int val);
ref<value> makeConstant(signed int val);
ref<value> makeValue(unsigned long val);
ref<value> makeConstant(unsigned long val);
ref<value> makeValue(unsigned int val);
ref<value> makeConstant(unsigned int val);
ref<value> makeValue(double val);
ref<value> makeConstant(double val);
ref<value> makeValue(std::string const &val);
ref<value> makeConstant(std::string const &val);
ref<value> makeArray(TSize size = 0);
ref<value> makeLValue(ref<value> target);
ref<value> wrapConstant(ref<value> val);
class interpreter {
public:
ref<list_scope,value> RootScope;
public:
interpreter();
~interpreter();
ref<expression> parse(std::string const &str);
ref<expression> parse(std::istream &istr);
ref<value> execute(std::string const &str);
ref<value> execute(std::istream &istr);
ref<value> execute(ref<expression> expr);
private:
ref<value> evaluateCatchExits(ref<expression> expr);
};
void addGlobal(interpreter &ip);
void addMath(interpreter &ip);
void addStandardLibrary(interpreter &ip);
}
}
#endif

View File

@@ -1,760 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Javascript interpreter
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_JS_INTERNALS
#define IXLIB_JS_INTERNALS
#include <ixlib_javascript.hh>
using namespace std;
namespace ixion {
namespace javascript {
struct code_location {
TIndex Line;
code_location(scanner::token &tok);
explicit code_location(TIndex line);
string stringify() const;
};
struct return_exception {
ref<value> ReturnValue;
code_location Location;
return_exception(ref<value> retval,code_location const &loc)
: ReturnValue(retval),Location(loc) {
}
};
struct break_exception {
bool HasLabel;
string Label;
code_location Location;
break_exception(bool has_label,string const &label,code_location const &loc)
: HasLabel(has_label),Label(label),Location(loc) {
}
};
struct continue_exception {
bool HasLabel;
string Label;
code_location Location;
continue_exception(bool has_label,string const &label,code_location const &loc)
: HasLabel(has_label),Label(label),Location(loc) {
}
};
// values -----------------------------------------------------------------
class null : public value {
private:
typedef value super;
public:
value_type getType() const;
bool toBoolean() const;
ref<value> duplicate();
};
class const_floating_point : public value_with_methods {
private:
typedef value_with_methods super;
protected:
double Value;
public:
const_floating_point(double value);
value_type getType() const;
int toInt() const;
double toFloat() const;
bool toBoolean() const;
string toString() const;
ref<value> duplicate();
ref<value> callMethod(string const &identifier,parameter_list const &parameters);
ref<value> operatorUnary(operator_id op) const;
ref<value> operatorBinary(operator_id op,ref<value> op2) const;
};
class floating_point : public const_floating_point {
private:
typedef const_floating_point super;
public:
floating_point(double value);
ref<value> operatorUnaryModifying(operator_id op);
ref<value> operatorBinaryModifying(operator_id op,ref<value> op2);
};
class const_integer : public value_with_methods {
private:
typedef value_with_methods super;
protected:
long Value;
public:
const_integer(long value);
value_type getType() const;
int toInt() const;
double toFloat() const;
bool toBoolean() const;
string toString() const;
ref<value> duplicate();
ref<value> callMethod(string const &identifier,parameter_list const &parameters);
ref<value> operatorUnary(operator_id op) const;
ref<value> operatorBinary(operator_id op,ref<value> op2) const;
};
class integer : public const_integer {
private:
typedef const_integer super;
public:
integer(long value);
ref<value> operatorUnaryModifying(operator_id op);
ref<value> operatorBinaryModifying(operator_id op,ref<value> op2);
};
class js_string : public value_with_methods {
private:
typedef value_with_methods super;
protected:
string Value;
public:
js_string(string const &value);
value_type getType() const;
string toString() const;
bool toBoolean() const;
string stringify() const;
ref<value> duplicate();
ref<value> lookup(string const &identifier);
ref<value> callMethod(string const &identifier,parameter_list const &parameters);
ref<value> operatorBinary(operator_id op,ref<value> op2) const;
ref<value> operatorBinaryModifying(operator_id op,ref<value> op2);
};
class lvalue : public value {
protected:
ref<value> Reference;
public:
lvalue(ref<value> ref);
value_type getType() const;
string toString() const;
int toInt() const;
double toFloat() const;
bool toBoolean() const;
string stringify() const;
ref<value> eliminateWrappers();
ref<value> duplicate();
ref<value> lookup(string const &identifier);
ref<value> subscript(value const &index);
ref<value> call(parameter_list const &parameters);
ref<value> callAsMethod(ref<value> instance,parameter_list const &parameters);
ref<value> construct(parameter_list const &parameters);
ref<value> assign(ref<value> op2);
ref<value> operatorUnary(operator_id op) const;
ref<value> operatorBinary(operator_id op,ref<value> op2) const;
ref<value> operatorBinaryShortcut(operator_id op,expression const &op2,context const &ctx) const;
ref<value> operatorUnaryModifying(operator_id op);
ref<value> operatorBinaryModifying(operator_id op,ref<value> op2);
};
class constant_wrapper : public value {
protected:
ref<value> Constant;
public:
constant_wrapper(ref<value> val);
value_type getType() const;
string toString() const;
int toInt() const;
double toFloat() const;
bool toBoolean() const;
string stringify() const;
ref<value> eliminateWrappers();
ref<value> duplicate();
ref<value> lookup(string const &identifier);
ref<value> subscript(value const &index);
ref<value> call(parameter_list const &parameters) const;
ref<value> callAsMethod(ref<value> instance,parameter_list const &parameters);
ref<value> construct(parameter_list const &parameters);
ref<value> assign(ref<value> value);
ref<value> operatorUnary(operator_id op) const;
ref<value> operatorBinary(operator_id op,ref<value> op2) const;
ref<value> operatorBinaryShortcut(operator_id op,expression const &op2,context const &ctx) const;
ref<value> operatorUnaryModifying(operator_id op);
ref<value> operatorBinaryModifying(operator_id op,ref<value> op2);
};
class callable_with_parameters : public value {
public:
typedef vector<string> parameter_name_list;
protected:
parameter_name_list ParameterNameList;
public:
callable_with_parameters(parameter_name_list const &pnames);
void addParametersTo(list_scope &scope,parameter_list const &parameters) const;
static ref<value> evaluateBody(expression &body,context const &ctx);
};
class function : public callable_with_parameters {
typedef callable_with_parameters super;
ref<expression> Body;
ref<value> LexicalScope;
public:
function(parameter_name_list const &pnames,ref<expression> body,ref<value> lex_scope);
value_type getType() const{
return VT_FUNCTION;
}
ref<value> duplicate();
ref<value> call(parameter_list const &parameters);
};
class method : public callable_with_parameters {
typedef callable_with_parameters super;
ref<expression> Body;
ref<value> LexicalScope;
public:
method(parameter_name_list const &pnames,ref<expression> body,ref<value> lex_scope);
value_type getType() const{
return VT_FUNCTION;
}
ref<value> duplicate();
ref<value> callAsMethod(ref<value> instance,parameter_list const &parameters);
};
class constructor : public callable_with_parameters {
typedef callable_with_parameters super;
ref<expression> Body;
ref<value> LexicalScope;
public:
constructor(parameter_name_list const &pnames,ref<expression> body,ref<value> lex_scope);
value_type getType() const{
return VT_FUNCTION;
}
ref<value> duplicate();
ref<value> callAsMethod(ref<value> instance,parameter_list const &parameters);
};
class js_class : public value {
class super_instance_during_construction : public value {
// this object constructs the superclass
// a) if it is called, by calling the super constructor
// with the aprropriate parameters
// b) implicitly with no super constructor arguments,
// if the super object is referenced explicitly
ref<value> SuperClass;
ref<value> SuperClassInstance;
public:
super_instance_during_construction(ref<value> super_class);
value_type getType() const {
return VT_OBJECT;
}
ref<value> call(parameter_list const &parameters);
ref<value> lookup(string const &identifier);
ref<value> getSuperClassInstance();
};
typedef vector<ref<expression> > declaration_list;
ref<value> LexicalScope;
ref<value> SuperClass;
ref<value> Constructor;
ref<value> StaticMethodScope;
ref<value> MethodScope;
ref<value> StaticVariableScope;
declaration_list VariableList;
public:
js_class(ref<value> lex_scope,ref<value> super_class,ref<value> constructor,
ref<value> static_method_scope,ref<value> method_scope,
ref<value> static_variable_scope,declaration_list const &variable_list);
value_type getType() const {
return VT_TYPE;
}
ref<value> duplicate();
ref<value> lookup(string const &identifier);
ref<value> lookupLocal(string const &identifier);
ref<value> construct(parameter_list const &parameters);
};
class js_class_instance : public value {
class bound_method : public value {
ref<value> Instance;
ref<value> Method;
public:
bound_method(ref<value> instance,ref<value> method);
value_type getType() const {
return VT_BOUND_METHOD;
}
ref<value> call(parameter_list const &parameters);
};
ref<value> SuperClassInstance;
ref<js_class,value> Class;
ref<value> MethodScope;
ref<value> VariableScope;
public:
js_class_instance(ref<js_class,value> cls,ref<value> method_scope,
ref<value> variable_scope);
void setSuperClassInstance(ref<value> super_class_instance);
value_type getType() const {
return VT_OBJECT;
}
ref<value> duplicate();
ref<value> lookup(string const &identifier);
};
class js_array_constructor : public value {
public:
value_type getType() const {
return VT_TYPE;
}
ref<value> duplicate();
ref<value> construct(parameter_list const &parameters);
};
// expressions ----------------------------------------------------------
class expression {
code_location Location;
public:
expression(code_location const &loc);
virtual ~expression();
virtual ref<value> evaluate(context const &ctx) const = 0;
code_location const &getCodeLocation() const {
return Location;
}
};
class constant : public expression {
ref<value> Value;
public:
constant(ref<value> val,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class unary_operator : public expression {
value::operator_id Operator;
ref<expression> Operand;
public:
unary_operator(value::operator_id opt,ref<expression> opn,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class modifying_unary_operator : public expression {
value::operator_id Operator;
ref<expression> Operand;
public:
modifying_unary_operator(value::operator_id opt,ref<expression> opn,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class binary_operator : public expression {
value::operator_id Operator;
ref<expression> Operand1;
ref<expression> Operand2;
public:
binary_operator(value::operator_id opt,ref<expression> opn1,ref<expression> opn2,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class binary_shortcut_operator : public expression {
value::operator_id Operator;
ref<expression> Operand1;
ref<expression> Operand2;
public:
binary_shortcut_operator(value::operator_id opt,ref<expression> opn1,ref<expression> opn2,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class modifying_binary_operator : public expression {
value::operator_id Operator;
ref<expression> Operand1;
ref<expression> Operand2;
public:
modifying_binary_operator(value::operator_id opt,ref<expression> opn1,ref<expression> opn2,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class ternary_operator : public expression {
ref<expression> Operand1;
ref<expression> Operand2;
ref<expression> Operand3;
public:
ternary_operator(ref<expression> opn1,ref<expression> opn2,ref<expression> opn3,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class subscript_operation : public expression {
ref<expression> Operand1;
ref<expression> Operand2;
public:
subscript_operation(ref<expression> opn1,ref<expression> opn2,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class lookup_operation : public expression {
ref<expression> Operand;
string Identifier;
public:
lookup_operation(string const &id,code_location const &loc);
lookup_operation(ref<expression> opn,string const &id,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class assignment : public expression {
ref<expression> Operand1;
ref<expression> Operand2;
public:
assignment(ref<expression> opn1,ref<expression> opn2,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class basic_call : public expression {
public:
typedef vector<ref<expression> > parameter_expression_list;
typedef vector<ref<value> > parameter_value_list;
private:
parameter_expression_list ParameterExpressionList;
public:
basic_call(parameter_expression_list const &pexps,code_location const &loc);
void makeParameterValueList(context const &ctx,parameter_value_list &pvalues) const;
};
class function_call : public basic_call {
typedef basic_call super;
ref<expression> Function;
public:
function_call(ref<expression> fun,parameter_expression_list const &pexps,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class construction : public basic_call {
typedef basic_call super;
ref<expression> Class;
public:
construction(ref<expression> cls,parameter_expression_list const &pexps,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
// declarations -----------------------------------------------------------
class variable_declaration : public expression {
protected:
string Identifier;
ref<expression> DefaultValue;
public:
variable_declaration(string const &id,ref<expression> def_value,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class constant_declaration : public expression {
protected:
string Identifier;
ref<expression> DefaultValue;
public:
constant_declaration(string const &id,ref<expression> def_value,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class function_declaration : public expression {
public:
typedef function::parameter_name_list parameter_name_list;
private:
string Identifier;
parameter_name_list ParameterNameList;
ref<expression> Body;
public:
function_declaration(string const &id,parameter_name_list const &pnames,
ref<expression> body,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class method_declaration : public expression {
public:
typedef method::parameter_name_list parameter_name_list;
private:
string Identifier;
parameter_name_list ParameterNameList;
ref<expression> Body;
public:
method_declaration(string const &id,parameter_name_list const &pnames,
ref<expression> body,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class constructor_declaration : public expression {
public:
typedef method::parameter_name_list parameter_name_list;
private:
parameter_name_list ParameterNameList;
ref<expression> Body;
public:
constructor_declaration(parameter_name_list const &pnames,
ref<expression> body,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_class_declaration : public expression {
typedef vector<ref<expression> > declaration_list;
string Identifier;
ref<expression> SuperClass;
ref<expression> ConstructorDeclaration;
declaration_list StaticMethodList;
declaration_list MethodList;
declaration_list StaticVariableList;
declaration_list VariableList;
public:
js_class_declaration(string const &id,ref<expression> superclass,
code_location const &loc);
ref<value> evaluate(context const &ctx) const;
void setConstructor(ref<expression> decl);
void addStaticMethod(ref<expression> decl);
void addMethod(ref<expression> decl);
void addStaticVariable(ref<expression> decl);
void addVariable(ref<expression> decl);
};
// instructions ---------------------------------------------------------
class instruction_list : public expression {
typedef vector<ref<expression> > expression_list;
expression_list ExpressionList;
public:
instruction_list(code_location const &loc)
: expression(loc) {
}
ref<value> evaluate(context const &ctx) const;
void add(ref<expression> expr);
};
class scoped_instruction_list : public instruction_list {
public:
scoped_instruction_list(code_location const &loc)
: instruction_list(loc) {
}
ref<value> evaluate(context const &ctx) const;
};
class js_if : public expression {
ref<expression> Conditional;
ref<expression> IfExpression;
ref<expression> IfNotExpression;
public:
js_if(ref<expression> cond,ref<expression> ifex,ref<expression> ifnotex,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_while : public expression {
ref<expression> Conditional;
ref<expression> LoopExpression;
bool HasLabel;
string Label;
public:
js_while(ref<expression> cond,ref<expression> loopex,code_location const &loc);
js_while(ref<expression> cond,ref<expression> loopex,string const &Label,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_do_while : public expression {
ref<expression> Conditional;
ref<expression> LoopExpression;
bool HasLabel;
string Label;
public:
js_do_while(ref<expression> cond,ref<expression> loopex,code_location const &loc);
js_do_while(ref<expression> cond,ref<expression> loopex,string const &Label,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_for : public expression {
ref<expression> Initialization;
ref<expression> Conditional;
ref<expression> Update;
ref<expression> LoopExpression;
bool HasLabel;
string Label;
public:
js_for(ref<expression> init,ref<expression> cond,ref<expression> update,ref<expression> loop,code_location const &loc);
js_for(ref<expression> init,ref<expression> cond,ref<expression> update,ref<expression> loop,string const &label,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_for_in : public expression {
ref<expression> Iterator;
ref<expression> Array;
ref<expression> LoopExpression;
bool HasLabel;
string Label;
public:
js_for_in(ref<expression> iter,ref<expression> array,ref<expression> loop,code_location const &loc);
js_for_in(ref<expression> iter,ref<expression> array,ref<expression> loop,string const &label,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_return : public expression {
ref<expression> ReturnValue;
public:
js_return(ref<expression> retval,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_break : public expression {
bool HasLabel;
string Label;
public:
js_break(code_location const &loc);
js_break(string const &label,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_continue : public expression {
bool HasLabel;
string Label;
public:
js_continue(code_location const &loc);
js_continue(string const &label,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class break_label : public expression {
string Label;
ref<expression> Expression;
public:
break_label(string const &label,ref<expression> expr,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
};
class js_switch : public expression {
bool HasLabel;
string Label;
ref<expression> Discriminant;
struct case_label {
ref<expression> DiscriminantValue;
ref<expression> Expression;
};
typedef vector<case_label> case_list;
case_list CaseList;
public:
js_switch(ref<expression> discriminant,code_location const &loc);
js_switch(ref<expression> discriminant,string const &label,code_location const &loc);
ref<value> evaluate(context const &ctx) const;
void addCase(ref<expression> dvalue,ref<expression> expr);
};
}
}
#endif

View File

@@ -1,62 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Numeric conversions
// ----------------------------------------------------------------------------
// (c) Copyright 1999 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_NUMCONV
#define IXLIB_NUMCONV
#include <ixlib_base.hh>
#include <ixlib_string.hh>
// Macros ---------------------------------------------------------------------
#define IXLIB_NUMCHARS "0123456789ABCDEF"
// Functions ------------------------------------------------------------------
namespace ixion {
std::string float2dec(double value);
std::string float2dec(double value,unsigned int precision);
std::string unsigned2base(unsigned long value,char digits = 0,char radix = 10);
inline std::string unsigned2dec(unsigned long value,char digits = 0)
{ return unsigned2base(value,digits,10); }
inline std::string unsigned2hex(unsigned long value,char digits = 0)
{ return unsigned2base(value,digits,16); }
inline std::string unsigned2bin(unsigned long value,char digits = 0)
{ return unsigned2base(value,digits,2); }
inline std::string unsigned2oct(unsigned long value,char digits = 0)
{ return unsigned2base(value,digits,8); }
std::string signed2base(signed long value,char digits = 0,char radix = 10);
inline std::string signed2dec(signed long value,char digits = 0)
{ return signed2base(value,digits,10); }
inline std::string signed2hex(signed long value,char digits = 0)
{ return signed2base(value,digits,16); }
inline std::string signed2bin(signed long value,char digits = 0)
{ return signed2base(value,digits,2); }
inline std::string signed2oct(signed long value,char digits = 0)
{ return signed2base(value,digits,8); }
std::string bytes2dec(TSize bytes);
unsigned long evalNumeral(std::string const &numeral,unsigned radix = 10);
double evalFloat(std::string const &numeral);
unsigned long evalUnsigned(std::string const &numeral,unsigned default_base = 10);
signed long evalSigned(std::string const &numeral,unsigned default_base = 10);
}
#endif

View File

@@ -1,127 +0,0 @@
// ----------------------------------------------------------------------------
// Description : numeric / order processing
// ----------------------------------------------------------------------------
// (c) Copyright 1996 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_NUMERIC
#define IXLIB_NUMERIC
#include <cstring>
#include <ixlib_base.hh>
#include <ixlib_exgen.hh>
// Macros ---------------------------------------------------------------------
#ifdef _GNUC_
#define NUM_MIN(a,b) ( (a)<?(b) )
#define NUM_MAX(a,b) ( (a)>?(b) )
#define NUM_ABS(a) ( (a)<0 ? (-(a)) : (a) )
#else
#define NUM_MIN(a,b) ( (a)<(b) ? (a) : (b) )
#define NUM_MAX(a,b) ( (a)>(b) ? (a) : (b) )
#define NUM_ABS(a) ( (a)<0 ? (-(a)) : (a) )
#endif
#define NUM_LIMIT(lower,value,upper) \
( NUM_MAX(lower,NUM_MIN(upper,vallue)) )
#define NUM_INBOUND(lower,value,upper) \
(((lower) <= (value)) && ((value) <= (upper)))
#define NUM_OVERLAP(a1,a2,b1,b2) \
((((a1)<=(b1))&&((a2)>(b1)))||(((a1)<(b2))&&((a2)>(b2)))||(((a1)>=(b1))&&((a2)<=(b2))))
#define NUM_CIRCLEINC(index,size) \
( ((index)+1) >= (size) ? 0 : ((index)+1) )
#define NUM_CIRCLEDIST(head,tail,size) \
( (head)<(tail) ? ((head)+(size)-(tail)) : ((head)-(tail)) )
// Primitive inlines ---------------------------------------------------------
namespace ixion {
inline signed short sgn(signed long value);
inline bool getBit(unsigned long value,char bit);
inline TUnsigned8 hiByte(TUnsigned16 value);
inline TUnsigned16 hiWord(TUnsigned32 value);
inline TUnsigned8 loByte(TUnsigned16 value);
inline TUnsigned16 loWord(TUnsigned32 value);
inline TUnsigned16 makeWord(TUnsigned8 hi,TUnsigned8 lo);
inline TUnsigned32 makeDWord(TUnsigned16 hi,TUnsigned16 lo);
// BCD encoding ---------------------------------------------------------------
unsigned long unsigned2BCD(unsigned long value);
unsigned long BCD2unsigned(unsigned long value);
// Primitive inlines ---------------------------------------------------------
inline signed short ixion::sgn(signed long value) {
return (value<0) ? -1 : ( (value>0) ? 1 : 0);
}
inline bool ixion::getBit(unsigned long value,char bit) {
return (value >> bit) & 1;
}
inline TUnsigned8 ixion::hiByte(TUnsigned16 value) {
return value >> 8;
}
inline TUnsigned16 ixion::hiWord(TUnsigned32 value) {
return value >> 16;
}
inline TUnsigned8 ixion::loByte(TUnsigned16 value) {
return value & 0xff;
}
inline TUnsigned16 ixion::loWord(TUnsigned32 value) {
return value & 0xffff;
}
inline TUnsigned16 ixion::makeWord(TUnsigned8 hi,TUnsigned8 lo) {
return (TUnsigned16) hi << 8 | lo;
}
inline TUnsigned32 ixion::makeDWord(TUnsigned16 hi,TUnsigned16 lo) {
return (TUnsigned32) hi << 16 | lo;
}
}
#endif

View File

@@ -1,82 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Random numbers
// ----------------------------------------------------------------------------
// (c) Copyright 1996 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_RANDOM
#define IXLIB_RANDOM
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <ixlib_base.hh>
#include <ixlib_numeric.hh>
namespace ixion {
class float_random {
double Seed;
public:
float_random()
: Seed(1)
{ }
void init() {
double current_time = time(NULL);
Seed = current_time*sin(current_time);
}
void init(double seed)
{ Seed = NUM_ABS(seed); }
/// Generate one random number in the interval [0,max).
double operator()(double max = 1) {
// normalize
while (Seed > 3) Seed = log(Seed);
Seed -= floor(Seed);
Seed = pow(Seed+Pi,8);
Seed -= floor(Seed);
return Seed*max;
}
};
class int_random {
float_random Generator;
public:
int_random()
{ }
void init()
{ Generator.init(); }
void init(unsigned seed)
{ Generator.init(seed); }
/// Generate one random number in the interval [0,max).
unsigned operator()(unsigned max = 32768) {
unsigned num = rng8() + (rng8() << 7) + (rng8() << 14) + (rng8() << 21) + (rng8() << 28);
return num % max;
}
private:
TUnsigned8 rng8() {
return (TUnsigned8) (Generator()*256);
}
};
}
#endif

View File

@@ -1,493 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Regular expressions string object
// ----------------------------------------------------------------------------
// (c) Copyright 1998 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_RE
#define IXLIB_RE
#include <vector>
#include <memory>
#include <ixlib_exgen.hh>
#include <ixlib_string.hh>
// Regex exceptions -----------------------------------------------------------
#define ECRE_INVQUANTIFIER 0
#define ECRE_UNBALBACKREF 1
#define ECRE_INVESCAPE 2
#define ECRE_INVBACKREF 3
#define ECRE_UNTERMCLASS 4
#define ECRE_NOPATTERN 5
namespace ixion {
class regex_exception : public base_exception {
public:
regex_exception(TErrorCode error,char const *info = NULL,char *module = NULL,TIndex line = 0);
virtual char *getText() const;
};
}
// Regex token macros ---------------------------------------------------------
#define XSTRRE_LITERAL '\\'
#define XSTRRE_BACKREF '\\'
#define XSTRRE_ESCAPESEQ '\\'
#define XSTRRE_ANYCHAR '.'
#define XSTRRE_START '^'
#define XSTRRE_END '$'
#define XSTRRE_ALTERNATIVE '|'
#define XSTRRE_CLASSSTART '['
#define XSTRRE_CLASSNEG '^'
#define XSTRRE_CLASSRANGE '-'
#define XSTRRE_CLASSSTOP ']'
#define XSTRRE_BACKREFSTART '('
#define XSTRRE_BACKREFSTOP ')'
#define XSTRREQ_0PLUS '*'
#define XSTRREQ_1PLUS '+'
#define XSTRREQ_01 '?'
#define XSTRREQ_START '{'
#define XSTRREQ_RANGE ','
#define XSTRREQ_STOP '}'
#define XSTRREQ_NONGREEDY '?'
namespace ixion {
/**
A class implementing a generic regular expression matcher not only for strings.
If you are looking for a usual regular expresion parser, look at
ixion::regex_string.
If you query anything about the last match, and that last match did
never happen, behavior is undefined.
*/
template<class T>
class regex {
protected:
// various helper classes -----------------------------------------------
class backref_stack {
private:
struct backref_entry {
enum { OPEN,CLOSE } Type;
TIndex Index;
};
typedef std::vector<backref_entry> internal_stack;
internal_stack Stack;
public:
typedef TSize rewind_info;
void open(TIndex index);
void close(TIndex index);
rewind_info getRewindInfo() const;
void rewind(rewind_info ri);
void clear();
TSize size();
T get(TIndex number,T const &candidate) const;
};
// matchers -------------------------------------------------------------
class matcher {
protected:
matcher *Next;
bool OwnNext;
TSize MatchLength;
public:
matcher();
virtual ~matcher();
virtual matcher *duplicate() const = 0;
TSize getMatchLength() const {
return MatchLength;
}
TSize subsequentMatchLength() const;
virtual TSize minimumMatchLength() const = 0;
TSize minimumSubsequentMatchLength() const;
matcher *getNext() const {
return Next;
}
virtual void setNext(matcher *next,bool ownnext = true) {
Next = next;
OwnNext = ownnext;
}
// this routine must set the MatchLength member correctly.
virtual bool match(backref_stack &brstack,T const &candidate,TIndex at)
= 0;
protected:
bool matchNext(backref_stack &brstack,T const &candidate,TIndex at) const {
return Next ? Next->match(brstack,candidate,at) : true;
}
void copy(matcher const *src);
};
class quantifier : public matcher {
private:
typedef matcher super;
bool Greedy,MaxValid;
TSize MinCount,MaxCount;
matcher *Quantified;
struct backtrack_stack_entry {
TIndex Index;
backref_stack::rewind_info RewindInfo;
};
public:
quantifier()
: Quantified(NULL) {
}
quantifier(bool greedy,TSize mincount);
quantifier(bool greedy,TSize mincount,TSize maxcount);
~quantifier();
matcher *duplicate() const;
TSize minimumMatchLength() const;
void setQuantified(matcher *quantified) {
Quantified = quantified;
}
bool match(backref_stack &brstack,T const &candidate,TIndex at);
protected:
void copy(quantifier const *src);
};
class sequence_matcher : public matcher {
T MatchStr;
public:
sequence_matcher(T const &matchstr);
matcher *duplicate() const;
TSize minimumMatchLength() const {
return MatchStr.size();
}
bool match(backref_stack &brstack,T const &candidate,TIndex at);
};
class any_matcher : public matcher {
public:
any_matcher() {
MatchLength = 1;
}
matcher *duplicate() const;
TSize minimumMatchLength() const {
return 1;
}
bool match(backref_stack &brstack,T const &candidate,TIndex at) {
return at < candidate.size() && matchNext(brstack,candidate,at+1);
}
};
class start_matcher : public matcher {
public:
start_matcher() {
MatchLength = 0;
}
matcher *duplicate() const;
TSize minimumMatchLength() const {
return 0;
}
bool match(backref_stack &brstack,T const &candidate,TIndex at);
};
class end_matcher : public matcher {
public:
end_matcher() {
MatchLength = 0;
}
matcher *duplicate() const;
TSize minimumMatchLength() const {
return 0;
}
bool match(backref_stack &brstack,T const &candidate,TIndex at);
};
class backref_open_matcher : public matcher {
public:
backref_open_matcher() {
MatchLength = 0;
}
matcher *duplicate() const;
TSize minimumMatchLength() const {
return 0;
}
bool match(backref_stack &brstack,T const &candidate,TIndex at);
};
class backref_close_matcher : public matcher {
public:
backref_close_matcher() {
MatchLength = 0;
}
matcher *duplicate() const;
TSize minimumMatchLength() const {
return 0;
}
bool match(backref_stack &brstack,T const &candidate,TIndex at);
};
class alternative_matcher : public matcher {
// The connector serves two purposes:
// a) be a null-matcher that re-unites the different alternate token
// sequences
// b) make the end of each sequence identifiable to be able to compute
// the match length
class connector : public matcher {
public:
matcher *duplicate() const {
return NULL;
}
TSize minimumMatchLength() const {
return 0;
}
bool match(backref_stack &brstack,T const &candidate,TIndex at);
};
typedef matcher super;
typedef std::vector<matcher *> alt_list;
alt_list AltList;
connector Connector;
public:
~alternative_matcher();
matcher *duplicate() const;
TSize minimumMatchLength() const;
void setNext(matcher *next,bool ownnext = true);
void addAlternative(matcher *alternative);
bool match(backref_stack &brstack,T const &candidate,TIndex at);
protected:
void copy(alternative_matcher const *src);
};
class backref_matcher : public matcher {
TIndex Backref;
public:
backref_matcher(TIndex backref);
matcher *duplicate() const;
TSize minimumMatchLength() const {
return 0;
}
bool match(backref_stack &brstack,T const &candidate,TIndex at);
};
// instance data --------------------------------------------------------
std::auto_ptr<matcher> ParsedRegex;
backref_stack BackrefStack;
T LastCandidate;
TIndex MatchIndex;
TSize MatchLength;
public:
// interface ------------------------------------------------------------
regex();
regex(regex const &src);
regex &operator=(regex const &src);
bool match(T const &candidate,TIndex from = 0);
bool matchAt(T const &candidate,TIndex at = 0);
// Queries pertaining to the last match
TIndex getMatchIndex() {
return MatchIndex;
}
TSize getMatchLength() {
return MatchLength;
}
std::string getMatch() {
return T(LastCandidate.begin()+MatchIndex,
LastCandidate.begin()+MatchIndex+MatchLength);
}
TSize countBackrefs() {
return BackrefStack.size();
}
T getBackref(TIndex index) {
return BackrefStack.get(index,LastCandidate);
}
};
/**
A regular expression parser and matcher.
Backref numbering starts at \0.
ReplaceAll does not set the MatchIndex/MatchGlobal members.
What is there is compatible with perl5. (See man perlre or
http://www.cpan.org/doc/manual/html/pod/perlre.html)
However, not everything is there. Here's what's missing:
<ul>
<li> \Q-\E,\b,\B,\A,\Z,\z
<li> discerning between line and string
<li> (?#comments)
<li> (?:clustering)
<li> (?=positive lookahead assumptions)
<li> (?!negative lookahead assumptions
<li> (?<=positive lookbehind assumptions)
<li> (?<!negative lookbehind assumptions
<li> (?>independent substrings)
<li> modifiers such as "case independent"
</ul>
as well as all the stuff involving perl code, naturally.
None of these is actually hard to hack in. If you want them,
pester me or try for yourself (and submit patches!)
*/
class regex_string : public regex<std::string> {
private:
class class_matcher : public regex<std::string>::matcher {
private:
typedef regex<std::string>::matcher super;
static TSize const CharValues = 256;
bool Set[CharValues];
bool Negated;
public:
class_matcher();
class_matcher(std::string const &cls);
matcher *duplicate() const;
TSize minimumMatchLength() const {
return 1;
}
bool match(backref_stack &brstack,std::string const &candidate,TIndex at);
private:
void expandClass(std::string const &cls);
protected:
void copy(class_matcher const *src);
};
class special_class_matcher : public regex<std::string>::matcher {
public:
enum type { DIGIT,NONDIGIT,ALNUM,NONALNUM,SPACE,NONSPACE };
private:
type Type;
public:
special_class_matcher(type tp);
matcher *duplicate() const;
TSize minimumMatchLength() const {
return 1;
}
bool match(backref_stack &brstack,std::string const &candidate,TIndex at);
};
public:
regex_string() {
}
regex_string(std::string const &str) {
parse(str);
}
regex_string(char const *s) {
parse(s);
}
void parse(std::string const &expr);
std::string replaceAll(std::string const &candidate,std::string const &replacement,
TIndex from = 0);
private:
regex<std::string>::matcher *parseRegex(std::string const &expr);
quantifier *parseQuantifier(std::string const &expr,TIndex &at);
bool isGreedy(std::string const &expr,TIndex &at);
};
}
#endif

View File

@@ -1,652 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Regular expressions string object.
// ----------------------------------------------------------------------------
// (c) Copyright 1998 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <stack>
#include <cctype>
#include "ixlib_i18n.hh"
#include <ixlib_exgen.hh>
#include <ixlib_numeric.hh>
#include <ixlib_numconv.hh>
#include <ixlib_re.hh>
// regex::backref_stack -------------------------------------------------------
template<class T>
void ixion::regex<T>::backref_stack::open(TIndex index) {
backref_entry entry = { backref_entry::OPEN,index };
Stack.push_back(entry);
}
template<class T>
void ixion::regex<T>::backref_stack::close(TIndex index) {
backref_entry entry = { backref_entry::CLOSE,index };
Stack.push_back(entry);
}
template<class T>
ixion::regex<T>::backref_stack::rewind_info
ixion::regex<T>::backref_stack::getRewindInfo() const {
return Stack.size();
}
template<class T>
void ixion::regex<T>::backref_stack::rewind(rewind_info ri) {
Stack.erase(Stack.begin()+ri,Stack.end());
}
template<class T>
void ixion::regex<T>::backref_stack::clear() {
Stack.clear();
}
template<class T>
ixion::TSize ixion::regex<T>::backref_stack::size() {
TSize result = 0;
FOREACH_CONST(first,Stack,internal_stack)
if (first->Type == backref_entry::OPEN) result++;
return result;
}
template<class T>
T ixion::regex<T>::backref_stack::get(TIndex number,T const &candidate) const {
TIndex level = 0,next_index = 0;
TIndex start;
TIndex startlevel;
internal_stack::const_iterator first = Stack.begin(),last = Stack.end();
while (first != last) {
if (first->Type == backref_entry::OPEN) {
if (number == next_index) {
start = first->Index;
startlevel = level;
level++;
break;
}
next_index++;
level++;
}
if (first->Type == backref_entry::CLOSE)
level--;
first++;
}
if (first == last)
EX_THROW(regex,ECRE_INVBACKREF)
first++;
while (first != last) {
if (first->Type == backref_entry::OPEN)
level++;
if (first->Type == backref_entry::CLOSE) {
level--;
if (startlevel == level)
return candidate.substr(start,first->Index - start);
}
first++;
}
EX_THROW(regex,ECRE_UNBALBACKREF)
}
// regex::matcher -------------------------------------------------------------
template<class T>
ixion::regex<T>::matcher::matcher()
: Next(NULL) {
}
template<class T>
ixion::regex<T>::matcher::~matcher() {
if (Next && OwnNext)
delete Next;
}
template<class T>
ixion::TSize ixion::regex<T>::matcher::subsequentMatchLength() const {
TSize totalml = 0;
matcher const *object = this;
while (object) {
totalml += object->MatchLength;
object = object->Next;
}
return totalml;
}
template<class T>
ixion::TSize ixion::regex<T>::matcher::minimumSubsequentMatchLength() const {
TSize totalml = 0;
matcher const *object = this;
while (object) {
totalml += object->minimumMatchLength();
object = object->Next;
}
return totalml;
}
template<class T>
void ixion::regex<T>::matcher::copy(matcher const *src) {
if (src->Next && src->OwnNext)
setNext(src->Next->duplicate(),src->OwnNext);
else
setNext(NULL);
}
// regex::quantifier ----------------------------------------------------------
template<class T>
ixion::regex<T>::quantifier::quantifier(bool greedy,TSize mincount)
: Greedy(greedy),MaxValid(false),MinCount(mincount) {
}
template<class T>
ixion::regex<T>::quantifier::quantifier(bool greedy,TSize mincount,TSize maxcount)
: Greedy(greedy),MaxValid(true),MinCount(mincount),MaxCount(maxcount) {
}
template<class T>
ixion::regex<T>::quantifier::~quantifier() {
if (Quantified)
delete Quantified;
}
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::quantifier::duplicate() const {
quantifier *dupe = new quantifier();
dupe->copy(this);
return dupe;
}
template<class T>
ixion::TSize ixion::regex<T>::quantifier::minimumMatchLength() const {
if (Quantified)
return MinCount * Quantified->minimumMatchLength();
else
return 0;
}
template<class T>
bool ixion::regex<T>::quantifier::match(backref_stack &brstack,T const &candidate,TIndex at) {
// this routine does speculative matching, so it must pay close attention
// to rewind the backref stack appropriately.
// NB: matchNext does the rewinding automatically, whereas speculative
// matches of the quantified portion must be rewound.
// There should be at least one character in each match, we'd
// run to Baghdad otherwise.
if (!Quantified)
return matchNext(brstack,candidate,at);
// calculate accurate maximum match count
TSize quant_min = Quantified->minimumSubsequentMatchLength();
if (quant_min == 0) quant_min = 1;
TSize max_count = candidate.size() - at;
if (Next) max_count -= Next->minimumSubsequentMatchLength();
max_count = max_count/quant_min + 1;
if (MaxValid) max_count = NUM_MIN(max_count,MaxCount);
// check that at least MinCount matches take place (non-speculative)
TIndex idx = at;
for (TSize c = 1;c <= MinCount;c++)
if (Quantified->match(brstack,candidate,idx))
idx += Quantified->subsequentMatchLength();
else
return false;
// determine number of remaining matches
TSize remcount = max_count-MinCount;
// test for the remaining matches in a way that depends on Greedy flag
if (Greedy) {
// try to gobble up as many matches of quantified part as possible
// (speculative)
std::stack<backtrack_stack_entry> successful_indices;
{ backtrack_stack_entry entry = { idx,brstack.getRewindInfo() };
successful_indices.push(entry);
}
while (Quantified->match(brstack,candidate,idx) && successful_indices.size()-1 < remcount) {
idx += Quantified->subsequentMatchLength();
backtrack_stack_entry entry = { idx,brstack.getRewindInfo() };
successful_indices.push(entry);
}
// backtrack until rest of sequence also matches
while (successful_indices.size() && !matchNext(brstack,candidate,successful_indices.top().Index)) {
brstack.rewind(successful_indices.top().RewindInfo);
successful_indices.pop();
}
if (successful_indices.size()) {
MatchLength = successful_indices.top().Index - at;
return true;
}
else return false;
}
else {
for (TSize c = 0;c <= remcount;c++) {
if (matchNext(brstack,candidate,idx)) {
MatchLength = idx-at;
return true;
}
// following part runs once too much, effectively:
// if c == remcount, idx may be increased, but the search fails anyway
// => no problem
if (Quantified->match(brstack,candidate,idx))
idx += Quantified->subsequentMatchLength();
else
return false;
}
return false;
}
}
template<class T>
void ixion::regex<T>::quantifier::copy(quantifier const *src) {
super::copy(src);
Greedy = src->Greedy;
MaxValid = src->MaxValid;
MinCount = src->MinCount;
MaxCount = src->MaxCount;
Quantified = src->Quantified->duplicate();
}
// regex::sequence_matcher ------------------------------------------------------
template<class T>
ixion::regex<T>::sequence_matcher::sequence_matcher(T const &matchstr)
: MatchStr(matchstr) {
MatchLength = MatchStr.size();
}
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::sequence_matcher::duplicate() const {
sequence_matcher *dupe = new sequence_matcher(MatchStr);
dupe->copy(this);
return dupe;
}
template<class T>
bool ixion::regex<T>::sequence_matcher::match(backref_stack &brstack,T const &candidate,TIndex at) {
if (at+MatchStr.size() > candidate.size()) return false;
return (T(candidate.begin()+at,candidate.begin()+at+MatchStr.size()) == MatchStr) &&
matchNext(brstack,candidate,at+MatchStr.size());
}
// regex::any_matcher ---------------------------------------------------------
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::any_matcher::duplicate() const {
any_matcher *dupe = new any_matcher();
dupe->copy(this);
return dupe;
}
// regex::start_matcher ---------------------------------------------------------
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::start_matcher::duplicate() const {
start_matcher *dupe = new start_matcher();
dupe->copy(this);
return dupe;
}
template<class T>
bool ixion::regex<T>::start_matcher::match(backref_stack &brstack,T const &candidate,TIndex at) {
return (at == 0) && matchNext(brstack,candidate,at);
}
// regex::end_matcher ---------------------------------------------------------
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::end_matcher::duplicate() const {
end_matcher *dupe = new end_matcher();
dupe->copy(this);
return dupe;
}
template<class T>
bool ixion::regex<T>::end_matcher::match(backref_stack &brstack,T const &candidate,TIndex at) {
return (at == candidate.size()) && matchNext(brstack,candidate,at);
}
// regex::backref_open_matcher ------------------------------------------------
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::backref_open_matcher::duplicate() const {
backref_open_matcher *dupe = new backref_open_matcher();
dupe->copy(this);
return dupe;
}
template<class T>
bool ixion::regex<T>::backref_open_matcher::match(backref_stack &brstack,T const &candidate,TIndex at) {
backref_stack::rewind_info ri = brstack.getRewindInfo();
brstack.open(at);
bool result = matchNext(brstack,candidate,at);
if (!result)
brstack.rewind(ri);
return result;
}
// regex::backref_close_matcher -----------------------------------------------
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::backref_close_matcher::duplicate() const {
backref_close_matcher *dupe = new backref_close_matcher();
dupe->copy(this);
return dupe;
}
template<class T>
bool ixion::regex<T>::backref_close_matcher::match(backref_stack &brstack,T const &candidate,TIndex at) {
backref_stack::rewind_info ri = brstack.getRewindInfo();
brstack.close(at);
bool result = matchNext(brstack,candidate,at);
if (!result)
brstack.rewind(ri);
return result;
}
// regex::alternative_matcher::connector --------------------------------------
template<class T>
bool ixion::regex<T>::alternative_matcher::connector::match(backref_stack &brstack,T const &candidate,TIndex at) {
return matchNext(brstack,candidate,at);
}
// regex::alternative_matcher -------------------------------------------------
template<class T>
ixion::regex<T>::alternative_matcher::~alternative_matcher() {
while (AltList.size()) {
delete AltList.back();
AltList.pop_back();
}
}
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::alternative_matcher::duplicate() const {
alternative_matcher *dupe = new alternative_matcher();
dupe->copy(this);
return dupe;
}
template<class T>
ixion::TSize ixion::regex<T>::alternative_matcher::minimumMatchLength() const {
TSize result = 0;
bool is_first = true;
FOREACH_CONST(first,AltList,alt_list)
if (is_first) {
result = (*first)->minimumMatchLength();
is_first = true;
}
else {
TSize current = (*first)->minimumMatchLength();
if (current < result) result = current;
}
return result;
}
template<class T>
void ixion::regex<T>::alternative_matcher::setNext(matcher *next,bool ownnext = true) {
matcher::setNext(next);
Connector.setNext(next,false);
}
template<class T>
void ixion::regex<T>::alternative_matcher::addAlternative(matcher *alternative) {
AltList.push_back(alternative);
matcher *searchlast = alternative,*last = NULL;
while (searchlast) {
last = searchlast;
searchlast = searchlast->getNext();
}
last->setNext(&Connector,false);
}
template<class T>
bool ixion::regex<T>::alternative_matcher::match(backref_stack &brstack,T const &candidate,TIndex at) {
std::vector<matcher *>::iterator first = AltList.begin(),last = AltList.end();
while (first != last) {
if ((*first)->match(brstack,candidate,at)) {
MatchLength = 0;
matcher const *object = *first;
while (object != &Connector) {
MatchLength += object->getMatchLength();
object = object->getNext();
}
return true;
}
first++;
}
return false;
}
template<class T>
void ixion::regex<T>::alternative_matcher::copy(alternative_matcher const *src) {
super::copy(src);
Connector.setNext(Next,false);
FOREACH_CONST(first,src->AltList,alt_list)
addAlternative((*first)->duplicate());
}
// regex::backref_matcher -----------------------------------------------------
template<class T>
ixion::regex<T>::backref_matcher::backref_matcher(TIndex backref)
: Backref(backref) {
}
template<class T>
ixion::regex<T>::matcher *ixion::regex<T>::backref_matcher::duplicate() const {
backref_matcher *dupe = new backref_matcher(Backref);
dupe->copy(this);
return dupe;
}
template<class T>
bool ixion::regex<T>::backref_matcher::match(backref_stack &brstack,T const &candidate,TIndex at) {
T matchstr = brstack.get(Backref,candidate);
MatchLength = matchstr.size();
if (at+matchstr.size() > candidate.size()) return false;
return (T(candidate.begin()+at,candidate.begin()+at+matchstr.size()) == matchstr) &&
matchNext(brstack,candidate,at+matchstr.size());
}
// regex ----------------------------------------------------------------------
template<class T>
ixion::regex<T>::regex()
: MatchIndex(0),MatchLength(0) {
}
template<class T>
ixion::regex<T>::regex(regex const &src)
: ParsedRegex(src.ParsedRegex->duplicate()),
MatchIndex(0),MatchLength(0) {
}
template<class T>
ixion::regex<T> &ixion::regex<T>::operator=(regex const &src) {
std::auto_ptr<matcher> regex_copy(src.ParsedRegex->duplicate());
ParsedRegex = regex_copy;
return *this;
}
template<class T>
bool ixion::regex<T>::match(T const &candidate,TIndex from) {
LastCandidate = candidate;
BackrefStack.clear();
if (ParsedRegex.get() == NULL)
EX_THROW(regex,ECRE_NOPATTERN)
for (TIndex index = from;index < candidate.size();index++)
if (ParsedRegex->match(BackrefStack,candidate,index)) {
MatchIndex = index;
MatchLength = ParsedRegex->subsequentMatchLength();
return true;
}
return false;
}
template<class T>
bool ixion::regex<T>::matchAt(T const &candidate,TIndex at) {
LastCandidate = candidate;
BackrefStack.clear();
if (ParsedRegex.get() == NULL)
EX_THROW(regex,ECRE_NOPATTERN)
if (ParsedRegex->match(BackrefStack,candidate,at)) {
MatchIndex = at;
MatchLength = ParsedRegex->subsequentMatchLength();
return true;
}
return false;
}

View File

@@ -1,24 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Javascript scanner
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_SCANJS
#define IXLIB_SCANJS
#undef yyFlexLexer
#define yyFlexLexer jsFlexLexer
#include <FlexLexer.h>
#undef yyFlexLexer
#endif

View File

@@ -1,75 +0,0 @@
// ----------------------------------------------------------------------------
// Description : scanner wrapper for FlexLexer
// ----------------------------------------------------------------------------
// (c) Copyright 1999 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_SCANNER
#define IXLIB_SCANNER
#include <ixlib_base.hh>
#include <ixlib_exbase.hh>
#include <vector>
#include <ixlib_string.hh>
class FlexLexer;
// possible errors during execution -------------------------------------------
#define ECSCAN_UNKNOWN_TOKEN 0
#define ECSCAN_EOF 1
// scanner_exception ----------------------------------------------------------
namespace ixion {
struct scanner_exception : public base_exception {
scanner_exception(TErrorCode const error,TIndex const line,std::string const &info);
virtual char *getText() const;
};
// scanner --------------------------------------------------------------------
class scanner {
public:
typedef unsigned token_type;
struct token {
token_type Type;
TIndex Line;
std::string Text;
};
typedef std::vector<token> token_list;
typedef std::vector<token>::iterator token_iterator;
scanner(FlexLexer &lexer);
token_list scan();
protected:
FlexLexer &Lexer;
token CurrentToken;
token getNextToken();
bool reachedEOF() const;
};
}
#endif

View File

@@ -1,64 +0,0 @@
// ----------------------------------------------------------------------------
// Description : String crunching tools
// ----------------------------------------------------------------------------
// (c) Copyright 1999 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_STRING
#define IXLIB_STRING
#include <string>
#include <ixlib_base.hh>
#include <ixlib_exgen.hh>
namespace ixion {
template<class InputIterator>
inline std::string concat(InputIterator first,InputIterator last,std::string const &sep = " ") {
std::string str;
while (first != last) {
if (str.size()) str += sep;
str += *first++;
}
return str;
}
std::string findReplace(std::string const &target,std::string const &src,std::string const &dest);
std::string findReplace(std::string const &target,char* src,char *dest);
std::string findReplace(std::string const &target,char src,char dest);
std::string upper(std::string const &original);
std::string lower(std::string const &original);
std::string removeLeading(std::string const &original,char ch = ' ');
std::string removeTrailing(std::string const &original,char ch = ' ');
std::string removeLeadingTrailing(std::string const &original,char ch = ' ');
std::string parseCEscapes(std::string const &original);
TSize getMaxBase64DecodedSize(TSize encoded);
// data must provide enough space for the maximal size determined by the
// above function
TSize base64decode(TByte *data,std::string const &base64);
void base64encode(std::string &base64,TByte const *data,TSize size);
class string_hash {
public:
unsigned long operator()(std::string const &str) const;
};
}
#endif

View File

@@ -1,85 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Token definitions for Javascript scanner
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_TOKEN_JAVASCRIPT
#define IXLIB_TOKEN_JAVASCRIPT
#include <ixlib_token_lex.hh>
// keywords
#define TT_JS_THIS (TT_USER + 0)
#define TT_JS_FUNCTION (TT_USER + 1)
#define TT_JS_VAR (TT_USER + 2)
#define TT_JS_NULL (TT_USER + 3)
#define TT_JS_IF (TT_USER + 4)
#define TT_JS_WHILE (TT_USER + 5)
#define TT_JS_DO (TT_USER + 6)
#define TT_JS_ELSE (TT_USER + 7)
#define TT_JS_FOR (TT_USER + 8)
#define TT_JS_RETURN (TT_USER + 9)
#define TT_JS_SWITCH (TT_USER + 10)
#define TT_JS_CASE (TT_USER + 11)
#define TT_JS_CONTINUE (TT_USER + 12)
#define TT_JS_BREAK (TT_USER + 13)
#define TT_JS_DEFAULT (TT_USER + 14)
#define TT_JS_IN (TT_USER + 15)
#define TT_JS_CONST (TT_USER + 16)
#define TT_JS_CLASS (TT_USER + 17)
#define TT_JS_EXTENDS (TT_USER + 18)
#define TT_JS_NAMESPACE (TT_USER + 19)
#define TT_JS_STATIC (TT_USER + 20)
#define TT_JS_CONSTRUCTOR (TT_USER + 21)
// operators
#define TT_JS_NEW (TT_USER + 1024)
#define TT_JS_PLUS_ASSIGN (TT_USER + 1025)
#define TT_JS_MINUS_ASSIGN (TT_USER + 1026)
#define TT_JS_MULTIPLY_ASSIGN (TT_USER + 1027)
#define TT_JS_DIVIDE_ASSIGN (TT_USER + 1028)
#define TT_JS_MODULO_ASSIGN (TT_USER + 1029)
#define TT_JS_BIT_XOR_ASSIGN (TT_USER + 1030)
#define TT_JS_BIT_AND_ASSIGN (TT_USER + 1031)
#define TT_JS_BIT_OR_ASSIGN (TT_USER + 1032)
#define TT_JS_LEFT_SHIFT (TT_USER + 1033)
#define TT_JS_RIGHT_SHIFT (TT_USER + 1034)
#define TT_JS_LEFT_SHIFT_ASSIGN (TT_USER + 1035)
#define TT_JS_RIGHT_SHIFT_ASSIGN (TT_USER + 1036)
#define TT_JS_EQUAL (TT_USER + 1037)
#define TT_JS_NOT_EQUAL (TT_USER + 1038)
#define TT_JS_LESS_EQUAL (TT_USER + 1039)
#define TT_JS_GREATER_EQUAL (TT_USER + 1040)
#define TT_JS_LOGICAL_AND (TT_USER + 1041)
#define TT_JS_LOGICAL_OR (TT_USER + 1042)
#define TT_JS_INCREMENT (TT_USER + 1043)
#define TT_JS_DECREMENT (TT_USER + 1044)
#define TT_JS_IDENTICAL (TT_USER + 1045)
#define TT_JS_NOT_IDENTICAL (TT_USER + 1046)
// literals
#define TT_JS_LIT_INT (TT_USER + 2048)
#define TT_JS_LIT_FLOAT (TT_USER + 2049)
#define TT_JS_LIT_STRING (TT_USER + 2050)
#define TT_JS_LIT_TRUE (TT_USER + 2051)
#define TT_JS_LIT_FALSE (TT_USER + 2052)
#define TT_JS_LIT_UNDEFINED (TT_USER + 2053)
// identifier
#define TT_JS_IDENTIFIER (TT_USER + 3072)
#endif

View File

@@ -1,25 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Basic definitions
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#ifndef IXLIB_TOKENLEX
#define IXLIB_TOKENLEX
// Basic token types
#define TT_EOF 1024
#define TT_UNKNOWN 1025
#define TT_WHITESPACE 1026
#define TT_USER 2048
#endif

View File

@@ -1,201 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Javascript interpreter
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <ixlib_js_internals.hh>
using namespace ixion;
using namespace javascript;
// js_array -------------------------------------------------------------------
js_array::
js_array(TSize size) {
Array.resize(size);
ref<value> null = javascript::makeNull();
for (TIndex i = 0;i < size;i++)
Array[i] = makeLValue(null);
}
string js_array::stringify() const {
value_array::const_iterator first = Array.begin(),last = Array.end();
string result = "{ ";
bool at_first = true;
while (first != last) {
if (!at_first) result += ',';
else at_first = false;
result += (*first)->stringify();
first++;
}
return result + " }";
}
ref<javascript::value>
js_array::
duplicate() {
ref<value> result = new js_array(*this);
return result;
}
ref<javascript::value>
js_array::
lookup(string const &identifier) {
if (identifier == "length") return javascript::makeConstant(Array.size());
return super::lookup(identifier);
}
ref<javascript::value>
js_array::
subscript(value const &index) {
TIndex idx = index.toInt();
return operator[](idx);
}
ref<javascript::value>
js_array::
callMethod(string const &id,parameter_list const &parameters) {
if (id == "pop" && parameters.size() == 0) {
if (Array.size() == 0) return javascript::makeNull();
else {
ref<value> back = Array.back();
Array.pop_back();
return back;
}
}
else if (id == "push") {
FOREACH_CONST(first,parameters,parameter_list) {
Array.push_back((*first)->duplicate());
}
return javascript::makeConstant(Array.size());
}
else if (id == "reverse" && parameters.size() == 0) {
reverse(Array.begin(),Array.end());
return this;
}
else if (id == "shift" && parameters.size() == 0) {
if (Array.size() == 0) return javascript::makeNull();
else {
ref<value> front = Array.front();
Array.erase(Array.begin());
return front;
}
}
else if (id == "slice" && parameters.size() == 2) {
value_array::const_iterator first = Array.begin() + parameters[0]->toInt();
value_array::const_iterator last = Array.begin() + parameters[1]->toInt();
auto_ptr<js_array> array(new js_array(first,last));
return array.release();
}
else if (id == "unshift") {
TIndex i = 0;
FOREACH_CONST(first,parameters,parameter_list) {
Array.insert(Array.begin() + i++,(*first)->duplicate());
}
return javascript::makeConstant(Array.size());
}
else if (id == "join" && parameters.size() == 1) {
string sep = parameters[0]->toString();
string result;
for( TIndex i = 0; i < Array.size(); ++i ) {
if (i != 0)
result += sep;
result += Array[i]->toString();
}
return javascript::makeValue(result);
}
// *** FIXME: implement splice and sort
EXJS_THROWINFO(ECJS_UNKNOWN_IDENTIFIER,("Array."+id).c_str())
}
void js_array::resize(TSize size) {
if (size >= Array.size()) {
TSize prevsize = Array.size();
Array.resize(size);
ref<value> null = javascript::makeNull();
for (TIndex i = prevsize;i < size;i++)
Array[i] = makeLValue(null);
}
}
ref<value> &js_array::operator[](TIndex idx) {
if (idx >= Array.size())
resize((Array.size()+1)*2);
return Array[idx];
}
void js_array::push_back(ref<value> val) {
Array.push_back(val);
}
// js_array_constructor -------------------------------------------------------
ref<javascript::value> js_array_constructor::duplicate() {
// array_constructor is not mutable
return this;
}
ref<javascript::value>
js_array_constructor::
construct(parameter_list const &parameters) {
if (parameters.size() == 0) return makeArray();
else if (parameters.size() == 1) return makeArray(parameters[0]->toInt());
else /* parameters.size() >= 2 */ {
auto_ptr<js_array> result(new js_array(parameters.size()));
TIndex i = 0;
FOREACH_CONST(first,parameters,parameter_list) {
(*result)[i++] = (*first)->duplicate();
}
return result.release();
}
}

View File

@@ -1,216 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Javascript interpreter
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <ixlib_js_internals.hh>
#include <ixlib_token_javascript.hh>
#define EXJS_ADD_CODE_LOCATION \
catch (no_location_javascript_exception &half) { \
throw javascript_exception(half,getCodeLocation()); \
}
using namespace ixion;
using namespace javascript;
// variable_declaration -------------------------------------------------------
variable_declaration::variable_declaration(string const &id,ref<expression> def_value,code_location const &loc)
: expression(loc),Identifier(id),DefaultValue(def_value) {
}
ref<value> variable_declaration::evaluate(context const &ctx) const {
try {
ref<value> def;
if (DefaultValue.get() != NULL) def = DefaultValue->evaluate(ctx)->eliminateWrappers()->duplicate();
else def = makeNull();
ref<value> lv = makeLValue(def);
ctx.DeclarationScope->addMember(Identifier,lv);
return lv;
}
EXJS_ADD_CODE_LOCATION
}
// constant_declaration -------------------------------------------------------
constant_declaration::constant_declaration(string const &id,ref<expression> def_value,code_location const &loc)
: expression(loc),Identifier(id),DefaultValue(def_value) {
}
ref<value> constant_declaration::evaluate(context const &ctx) const {
try {
ref<value> def;
if (DefaultValue.get() != NULL) def = DefaultValue->evaluate(ctx)->eliminateWrappers()->duplicate();
else def = makeNull();
ref<value> cns = wrapConstant(def);
ctx.DeclarationScope->addMember(Identifier,cns);
return cns;
}
EXJS_ADD_CODE_LOCATION
}
// function_declaration -------------------------------------------------------
function_declaration::
function_declaration(string const &id,parameter_name_list const &pnames,
ref<expression> body,code_location const &loc)
: expression(loc),Identifier(id),ParameterNameList(pnames),Body(body) {
}
ref<value> function_declaration::evaluate(context const &ctx) const {
try {
ref<value> fun = new function(ParameterNameList,Body,ctx.LookupScope);
ctx.DeclarationScope->addMember(Identifier,fun);
return ref<value>(NULL);
}
EXJS_ADD_CODE_LOCATION
}
// method_declaration ---------------------------------------------------------
method_declaration::
method_declaration(string const &id,parameter_name_list const &pnames,
ref<expression> body,code_location const &loc)
: expression(loc),Identifier(id),ParameterNameList(pnames),Body(body) {
}
ref<value> method_declaration::evaluate(context const &ctx) const {
try {
ref<value> fun = new method(ParameterNameList,Body,ctx.LookupScope);
ctx.DeclarationScope->addMember(Identifier,fun);
return ref<value>(NULL);
}
EXJS_ADD_CODE_LOCATION
}
// constructor_declaration ---------------------------------------------------------
constructor_declaration::
constructor_declaration(parameter_name_list const &pnames,
ref<expression> body,code_location const &loc)
: expression(loc),ParameterNameList(pnames),Body(body) {
}
ref<value> constructor_declaration::evaluate(context const &ctx) const {
try {
ref<value> fun = new constructor(ParameterNameList,Body,ctx.LookupScope);
return fun;
}
EXJS_ADD_CODE_LOCATION
}
// js_class_declaration -------------------------------------------------------
js_class_declaration::js_class_declaration(string const &id,ref<expression> superclass,code_location const &loc)
: expression(loc),Identifier(id),SuperClass(superclass) {
}
ref<value> js_class_declaration::evaluate(context const &ctx) const {
try {
ref<list_scope,value> sml(new list_scope);
ref<list_scope,value> ml(new list_scope);
ref<list_scope,value> svl(new list_scope);
ref<value> sc;
if (SuperClass.get())
sc = SuperClass->evaluate(ctx);
ref<value> constructor;
if (ConstructorDeclaration.get())
constructor = ConstructorDeclaration->evaluate(ctx);
ref<value> cls(new js_class(ctx.LookupScope,sc,constructor,sml,ml,svl,VariableList));
ref<list_scope,value> static_scope(new list_scope);
static_scope->unite(ctx.LookupScope);
static_scope->unite(cls);
FOREACH_CONST(first,StaticMethodList,declaration_list)
(*first)->evaluate(context(sml,static_scope));
FOREACH_CONST(first,MethodList,declaration_list)
(*first)->evaluate(context(ml,ctx.LookupScope));
FOREACH_CONST(first,StaticVariableList,declaration_list)
(*first)->evaluate(context(svl,static_scope));
ctx.DeclarationScope->addMember(Identifier,cls);
return cls;
}
EXJS_ADD_CODE_LOCATION
}
void js_class_declaration::setConstructor(ref<expression> decl) {
ConstructorDeclaration = decl;
}
void js_class_declaration::addStaticMethod(ref<expression> decl) {
StaticMethodList.push_back(decl);
}
void js_class_declaration::addMethod(ref<expression> decl) {
MethodList.push_back(decl);
}
void js_class_declaration::addStaticVariable(ref<expression> decl) {
StaticVariableList.push_back(decl);
}
void js_class_declaration::addVariable(ref<expression> decl) {
VariableList.push_back(decl);
}

View File

@@ -1,310 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Javascript interpreter
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <ixlib_js_internals.hh>
#include <ixlib_token_javascript.hh>
#define EXJS_ADD_CODE_LOCATION \
catch (no_location_javascript_exception &half) { \
throw javascript_exception(half,getCodeLocation()); \
}
using namespace ixion;
using namespace javascript;
// expression -----------------------------------------------------------------
expression::expression(code_location const &loc)
: Location(loc) {
}
expression::~expression() {
}
// constant -------------------------------------------------------------------
constant::constant(ref<value> val,code_location const &loc)
: expression(loc),Value(val) {
}
ref<value>
constant::
evaluate(context const &ctx) const {
return Value;
}
// unary_operator -------------------------------------------------
unary_operator::unary_operator(value::operator_id opt,ref<expression> opn,code_location const &loc)
: expression(loc),Operator(opt),Operand(opn) {
}
ref<value>
unary_operator::
evaluate(context const &ctx) const {
try {
return Operand->evaluate(ctx)->operatorUnary(Operator);
}
EXJS_ADD_CODE_LOCATION
}
// modifying_unary_operator ---------------------------------------------------
modifying_unary_operator::
modifying_unary_operator(value::operator_id opt,ref<expression> opn,code_location const &loc)
: expression(loc),Operator(opt),Operand(opn) {
}
ref<value>
modifying_unary_operator::
evaluate(context const &ctx) const {
try {
return Operand->evaluate(ctx)->operatorUnaryModifying(Operator);
}
EXJS_ADD_CODE_LOCATION
}
// binary_operator ------------------------------------------------------------
binary_operator::binary_operator(value::operator_id opt,ref<expression> opn1,ref<expression> opn2,code_location const &loc)
: expression(loc),Operator(opt),Operand1(opn1),Operand2(opn2) {
}
ref<value> binary_operator::evaluate(context const &ctx) const {
try {
return Operand1->evaluate(ctx)->operatorBinary(Operator,Operand2->evaluate(ctx));
}
EXJS_ADD_CODE_LOCATION
}
// binary_shortcut_operator ---------------------------------------------------
binary_shortcut_operator::binary_shortcut_operator(value::operator_id opt,ref<expression> opn1,ref<expression> opn2,code_location const &loc)
: expression(loc),Operator(opt),Operand1(opn1),Operand2(opn2) {
}
ref<value> binary_shortcut_operator::evaluate(context const &ctx) const {
try {
return Operand1->evaluate(ctx)->operatorBinaryShortcut(Operator,*Operand2,ctx);
}
EXJS_ADD_CODE_LOCATION
}
// modifying_binary_operator --------------------------------------
modifying_binary_operator::
modifying_binary_operator(value::operator_id opt,ref<expression> opn1,ref<expression> opn2,code_location const &loc)
: expression(loc),Operator(opt),Operand1(opn1),Operand2(opn2) {
}
ref<value>
modifying_binary_operator::
evaluate(context const &ctx) const {
try {
return Operand1->evaluate(ctx)->operatorBinaryModifying(Operator,Operand2->evaluate(ctx));
}
EXJS_ADD_CODE_LOCATION
}
// ternary_operator -----------------------------------------------------------
ternary_operator::
ternary_operator(ref<expression> opn1,ref<expression> opn2,ref<expression> opn3,code_location const &loc)
: expression(loc),Operand1(opn1),Operand2(opn2),Operand3(opn3) {
}
ref<value>
ternary_operator::
evaluate(context const &ctx) const {
try {
if (Operand1->evaluate(ctx)->toBoolean())
return Operand2->evaluate(ctx);
else
return Operand3->evaluate(ctx);
}
EXJS_ADD_CODE_LOCATION
}
// subscript_operation --------------------------------------------------------
subscript_operation::subscript_operation(ref<expression> opn1,ref<expression> opn2,code_location const &loc)
: expression(loc),Operand1(opn1),Operand2(opn2) {
}
ref<value> subscript_operation::evaluate(context const &ctx) const {
try {
ref<value> op2 = Operand2->evaluate(ctx);
return Operand1->evaluate(ctx)->subscript(*op2);
}
EXJS_ADD_CODE_LOCATION
}
// lookup_operation -----------------------------------------------------------
lookup_operation::lookup_operation(string const &id,code_location const &loc)
: expression(loc),Identifier(id) {
}
lookup_operation::lookup_operation(ref<expression> opn,string const &id,code_location const &loc)
: expression(loc),Operand(opn),Identifier(id) {
}
ref<value> lookup_operation::evaluate(context const &ctx) const {
try {
ref<value> scope(ctx.LookupScope);
if (Operand.get() != NULL)
scope = Operand->evaluate(ctx);
return scope->lookup(Identifier);
}
EXJS_ADD_CODE_LOCATION
}
// assignment -----------------------------------------------------------------
assignment::
assignment(ref<expression> opn1,ref<expression> opn2,code_location const &loc)
: expression(loc),Operand1(opn1),Operand2(opn2) {
}
ref<value>
assignment::evaluate(context const &ctx) const {
try {
return Operand1->evaluate(ctx)->assign(Operand2->evaluate(ctx)->eliminateWrappers()->duplicate());
}
EXJS_ADD_CODE_LOCATION
}
// basic_call -----------------------------------------------------------------
basic_call::basic_call(parameter_expression_list const &pexps,code_location const &loc)
: expression(loc),ParameterExpressionList(pexps) {
}
void basic_call::makeParameterValueList(context const &ctx,parameter_value_list &pvalues) const {
FOREACH_CONST(first,ParameterExpressionList,parameter_expression_list) {
pvalues.push_back((*first)->evaluate(ctx));
}
}
// function_call --------------------------------------------------------------
function_call::function_call(ref<expression> fun,parameter_expression_list const &pexps,code_location const &loc)
: super(pexps,loc),Function(fun) {
}
ref<value> function_call::evaluate(context const &ctx) const {
try {
ref<value> func_value = Function->evaluate(ctx);
value::parameter_list pvalues;
makeParameterValueList(ctx,pvalues);
ref<value> result = func_value->call(pvalues);
if (result.get() == NULL) return makeNull();
else return result;
}
EXJS_ADD_CODE_LOCATION
}
// construction ---------------------------------------------------------------
construction::construction(ref<expression> cls,parameter_expression_list const &pexps,code_location const &loc)
: super(pexps,loc),Class(cls) {
}
ref<value> construction::evaluate(context const &ctx) const {
try {
ref<value> class_value = Class->evaluate(ctx);
value::parameter_list pvalues;
makeParameterValueList(ctx,pvalues);
return class_value->construct(pvalues);
}
EXJS_ADD_CODE_LOCATION
}

View File

@@ -1,413 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Javascript interpreter
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <ixlib_js_internals.hh>
#include <ixlib_token_javascript.hh>
using namespace ixion;
using namespace javascript;
// instruction_list -----------------------------------------------------------
ref<value>
instruction_list::evaluate(context const &ctx) const {
ref<value> result;
FOREACH_CONST(first,ExpressionList,expression_list)
result = (*first)->evaluate(ctx);
return result;
}
void instruction_list::add(ref<expression> expr) {
ExpressionList.push_back(expr);
}
// scoped_instruction_list ----------------------------------------
ref<value> scoped_instruction_list::evaluate(context const &ctx) const {
ref<list_scope,value> scope = new list_scope;
scope->unite(ctx.LookupScope);
ref<value> result = instruction_list::evaluate(context(scope));
if (result.get()) return result->duplicate();
return ref<value>(NULL);
// ATTENTION: this is a scope cancellation point.
}
// js_if ----------------------------------------------------------------------
js_if::js_if(ref<expression> cond,ref<expression> ifex,ref<expression> ifnotex,code_location const &loc)
: expression(loc),Conditional(cond),IfExpression(ifex),IfNotExpression(ifnotex) {
}
ref<value> js_if::evaluate(context const &ctx) const {
if (Conditional->evaluate(ctx)->toBoolean())
return IfExpression->evaluate(ctx);
else
if (IfNotExpression.get())
return IfNotExpression->evaluate(ctx);
else
return ref<value>(NULL);
}
// js_while -------------------------------------------------------------------
js_while::js_while(ref<expression> cond,ref<expression> loopex,code_location const &loc)
: expression(loc),Conditional(cond),LoopExpression(loopex),HasLabel(false) {
}
js_while::js_while(ref<expression> cond,ref<expression> loopex,string const &label,code_location const &loc)
: expression(loc),Conditional(cond),LoopExpression(loopex),HasLabel(true),Label(label) {
}
ref<value> js_while::evaluate(context const &ctx) const {
ref<value> result;
while (Conditional->evaluate(ctx)->toBoolean()) {
try {
result = LoopExpression->evaluate(ctx);
}
catch (break_exception &be) {
if (!be.HasLabel || (HasLabel && be.HasLabel && be.Label == Label))
break;
else throw;
}
catch (continue_exception &ce) {
if (!ce.HasLabel || (HasLabel && ce.HasLabel && ce.Label == Label))
continue;
else throw;
}
}
return result;
}
// js_do_while ----------------------------------------------------------------
js_do_while::js_do_while(ref<expression> cond,ref<expression> loopex,code_location const &loc)
: expression(loc),Conditional(cond),LoopExpression(loopex),HasLabel(false) {
}
js_do_while::js_do_while(ref<expression> cond,ref<expression> loopex,string const &label,code_location const &loc)
: expression(loc),Conditional(cond),LoopExpression(loopex),HasLabel(true),Label(label) {
}
ref<value> js_do_while::evaluate(context const &ctx) const {
ref<value> result;
do {
try {
result = LoopExpression->evaluate(ctx);
}
catch (break_exception &be) {
if (!be.HasLabel || (HasLabel && be.HasLabel && be.Label == Label))
break;
else throw;
}
catch (continue_exception &ce) {
if (!ce.HasLabel || (HasLabel && ce.HasLabel && ce.Label == Label))
continue;
else throw;
}
} while (Conditional->evaluate(ctx)->toBoolean());
return result;
}
// js_for ---------------------------------------------------------------------
js_for::js_for(ref<expression> init,ref<expression> cond,ref<expression> update,ref<expression> loop,code_location const &loc)
: expression(loc),Initialization(init),Conditional(cond),Update(update),
LoopExpression(loop),HasLabel(false) {
}
js_for::js_for(ref<expression> init,ref<expression> cond,ref<expression> update,ref<expression> loop,string const &label,code_location const &loc)
: expression(loc),Initialization(init),Conditional(cond),Update(update),LoopExpression(loop),
HasLabel(true),Label(label) {
}
ref<value> js_for::evaluate(context const &ctx) const {
ref<list_scope,value> scope = new list_scope;
scope->unite(ctx.LookupScope);
context inner_context(scope);
ref<value> result;
for (Initialization->evaluate(inner_context);Conditional->evaluate(inner_context)->toBoolean();
Update->evaluate(inner_context)) {
try {
result = LoopExpression->evaluate(inner_context);
}
catch (break_exception &be) {
if (!be.HasLabel || (HasLabel && be.HasLabel && be.Label == Label))
break;
else throw;
}
catch (continue_exception &ce) {
if (!ce.HasLabel || (HasLabel && ce.HasLabel && ce.Label == Label))
continue;
else throw;
}
}
return result;
}
// js_for_in ------------------------------------------------------------------
js_for_in::js_for_in(ref<expression> iter,ref<expression> array,ref<expression> loop,code_location const &loc)
: expression(loc),Iterator(iter),Array(array),LoopExpression(loop),HasLabel(false) {
}
js_for_in::js_for_in(ref<expression> iter,ref<expression> array,ref<expression> loop,string const &label,code_location const &loc)
: expression(loc),Iterator(iter),Array(array),LoopExpression(loop),
HasLabel(true),Label(label) {
}
ref<value> js_for_in::evaluate(context const &ctx) const {
ref<list_scope,value> scope = new list_scope;
scope->unite(ctx.LookupScope);
context inner_context(scope);
ref<value> result;
ref<value> iterator = Iterator->evaluate(inner_context);
ref<value> array = Array->evaluate(inner_context);
TSize size = array->lookup("length")->toInt();
for (TIndex i = 0;i < size;i++) {
try {
iterator->assign(array->subscript(*makeConstant(i)));
result = LoopExpression->evaluate(inner_context);
}
catch (break_exception &be) {
if (!be.HasLabel || (HasLabel && be.HasLabel && be.Label == Label))
break;
else throw;
}
catch (continue_exception &ce) {
if (!ce.HasLabel || (HasLabel && ce.HasLabel && ce.Label == Label))
continue;
else throw;
}
}
if (result.get()) return result->duplicate();
return ref<value>(NULL);
// ATTENTION: this is a scope cancellation point.
}
// js_return ------------------------------------------------------------------
js_return::js_return(ref<expression> retval,code_location const &loc)
: expression(loc),ReturnValue(retval) {
}
ref<value> js_return::evaluate(context const &ctx) const {
ref<value> retval;
if (ReturnValue.get())
retval = ReturnValue->evaluate(ctx);
throw return_exception(retval,getCodeLocation());
}
// js_break -------------------------------------------------------------------
js_break::js_break(code_location const &loc)
: expression(loc),HasLabel(false) {
}
js_break::js_break(string const &label,code_location const &loc)
: expression(loc),HasLabel(true),Label(label) {
}
ref<value> js_break::evaluate(context const &ctx) const {
throw break_exception(HasLabel,Label,getCodeLocation());
}
// js_continue ----------------------------------------------------------------
js_continue::js_continue(code_location const &loc)
: expression(loc),HasLabel(false) {
}
js_continue::js_continue(string const &label,code_location const &loc)
: expression(loc),HasLabel(true),Label(label) {
}
ref<value> js_continue::evaluate(context const &ctx) const {
throw continue_exception(HasLabel,Label,getCodeLocation());
}
// break_label ----------------------------------------------------------------
break_label::break_label(string const &label,ref<expression> expr,code_location const &loc)
: expression(loc),Label(label),Expression(expr) {
}
ref<value>
break_label::evaluate(context const &ctx) const {
try {
return Expression->evaluate(ctx);
}
catch (break_exception &be) {
if (be.HasLabel && be.Label == Label) return ref<value>(NULL);
else throw;
}
}
// js_switch -----------------------------------------------------------------
js_switch::js_switch(ref<expression> discriminant,code_location const &loc)
: expression(loc),HasLabel(false),Discriminant(discriminant) {
}
js_switch::js_switch(ref<expression> discriminant,string const &label,code_location const &loc)
: expression(loc),HasLabel(true),Label(label),Discriminant(discriminant) {
}
ref<value>
js_switch::
evaluate(context const &ctx) const {
ref<list_scope,value> scope = new list_scope;
scope->unite(ctx.LookupScope);
context inner_context(scope);
ref<value> discr = Discriminant->evaluate(inner_context);
case_list::const_iterator expr,def;
bool expr_found = false,def_found = false;
FOREACH_CONST(first,CaseList,case_list) {
if (first->DiscriminantValue.get()) {
if (first->DiscriminantValue->evaluate(inner_context)->
operatorBinary(value::OP_EQUAL,Discriminant->evaluate(inner_context))->toBoolean()) {
expr = first;
expr_found = true;
break;
}
}
else {
if (!def_found) {
def = first;
def_found = true;
}
}
}
try {
case_list::const_iterator exec,last = CaseList.end();
if (expr_found)
exec = expr;
else if (def_found)
exec = def;
else
return ref<value>(NULL);
ref<value> result;
while (exec != last) {
result = exec->Expression->evaluate(inner_context);
exec++;
}
if (result.get()) return result->duplicate();
return ref<value>(NULL);
}
catch (break_exception &be) {
if (!be.HasLabel || (HasLabel && be.HasLabel && be.Label == Label))
return ref<value>(NULL);
else
throw;
}
// ATTENTION: this is a scope cancellation point.
}
void js_switch::addCase(ref<expression> dvalue,ref<expression> expr) {
case_label cl;
cl.DiscriminantValue = dvalue;
cl.Expression = expr;
CaseList.push_back(cl);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,259 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Javascript interpreter library
// ----------------------------------------------------------------------------
// (c) Copyright 2000 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include <ixlib_js_internals.hh>
#include <ixlib_numconv.hh>
#include <ixlib_random.hh>
using namespace ixion;
using namespace javascript;
namespace {
class eval : public value {
protected:
interpreter &Interpreter;
public:
value_type getType() const {
return VT_FUNCTION;
}
eval(interpreter &interpreter)
: Interpreter(interpreter) {
}
ref<value> call(parameter_list const &parameters);
};
class Math : public value_with_methods {
private:
typedef value_with_methods super;
protected:
float_random RNG;
public:
value_type getType() const {
return VT_BUILTIN;
}
ref<value> duplicate() const;
ref<value> lookup(string const &identifier);
ref<value> callMethod(string const &identifier,parameter_list const &parameters);
};
}
// eval -----------------------------------------------------------------------
ref<value>
eval::
call(parameter_list const &parameters) {
if (parameters.size() != 1) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"eval")
}
if (parameters[0]->getType() != VT_STRING) return parameters[0];
return Interpreter.execute(parameters[0]->toString());
}
// parseInt -------------------------------------------------------------------
IXLIB_JS_DECLARE_FUNCTION(parseInt) {
if (parameters.size() != 1 && parameters.size() != 2) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"parseInt")
}
unsigned radix = 10;
if (parameters.size() == 2)
radix = parameters[1]->toInt();
return makeConstant(evalSigned(parameters[0]->toString(),radix));
}
// parseFloat -----------------------------------------------------------------
IXLIB_JS_DECLARE_FUNCTION(parseFloat) {
if (parameters.size() != 1) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"parseFloat")
}
return makeConstant(evalFloat(parameters[0]->toString()));
}
// isNaN ----------------------------------------------------------------------
#ifdef ADVANCED_MATH_AVAILABLE
IXLIB_JS_DECLARE_FUNCTION(isNaN) {
if (parameters.size() != 1) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"isNaN")
}
int classification = fpclassify(parameters[0]->toFloat());
return makeConstant(classification == FP_NAN);
}
#endif
// isFinite -------------------------------------------------------------------
#ifdef ADVANCED_MATH_AVAILABLE
IXLIB_JS_DECLARE_FUNCTION(isFinite) {
if (parameters.size() != 1) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"isFinite")
}
int classification = fpclassify(parameters[0]->toFloat());
return makeConstant(classification != FP_NAN && classification != FP_INFINITE);
}
#endif
// Math -----------------------------------------------------------------------
ref<value> Math::duplicate() const {
// Math is not mutable
return const_cast<Math *>(this);
}
ref<value> Math::lookup(string const &identifier) {
#define MATH_CONSTANT(NAME,VALUE) \
if (identifier == NAME) return makeConstant(VALUE);
MATH_CONSTANT("E",2.7182818284590452354)
MATH_CONSTANT("LN10",2.30258509299404568402)
MATH_CONSTANT("LN2",0.69314718055994530942)
MATH_CONSTANT("LOG2E",1.4426950408889634074)
MATH_CONSTANT("LOG10E,",0.43429448190325182765)
MATH_CONSTANT("PI",3.14159265358979323846)
MATH_CONSTANT("SQRT1_2",0.70710678118654752440)
MATH_CONSTANT("SQRT2",1.41421356237309504880)
return super::lookup(identifier);
}
ref<value> Math::callMethod(string const &identifier,parameter_list const &parameters) {
#define MATH_FUNCTION(NAME,C_NAME) \
if (identifier == NAME) { \
if (parameters.size() != 1) { \
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"Math." NAME) \
} \
return makeConstant(C_NAME(parameters[0]->toFloat())); \
}
MATH_FUNCTION("abs",NUM_ABS)
MATH_FUNCTION("acos",acos)
MATH_FUNCTION("asin",asin)
MATH_FUNCTION("atan",atan)
MATH_FUNCTION("ceil",ceil)
MATH_FUNCTION("cos",cos)
MATH_FUNCTION("exp",exp)
MATH_FUNCTION("floor",floor)
MATH_FUNCTION("log",log)
#ifdef ADVANCED_MATH_AVAILABLE
MATH_FUNCTION("round",round)
#endif
MATH_FUNCTION("sin",sin)
MATH_FUNCTION("sqrt",sqrt)
MATH_FUNCTION("tan",tan)
if (identifier == "atan2") {
if (parameters.size() != 2) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"Math.atan2")
}
return makeConstant(atan2(parameters[0]->toFloat(),parameters[1]->toFloat()));
}
if (identifier == "pow") {
if (parameters.size() != 2) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"Math.pow")
}
return makeConstant(pow(parameters[0]->toFloat(),parameters[1]->toFloat()));
}
if (identifier == "random") {
if (parameters.size() != 0) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"Math.random")
}
return makeConstant(RNG());
}
// *** FIXME this is non-compliant, but there is no equivalent standard function
if (identifier == "initRandom") {
if (parameters.size() >= 2) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,"Math.initRandom")
}
if (parameters.size() == 0)
RNG.init();
else if (parameters.size() == 1)
RNG.init(parameters[0]->toFloat());
return makeNull();
}
// *** FIXME: implement max, min
EXJS_THROWINFO(ECJS_UNKNOWN_IDENTIFIER,("Math." + identifier).c_str())
}
// external interface functions -----------------------------------------------
#define ADD_GLOBAL_OBJECT(NAME,TYPE) \
{ ref<value> x = new TYPE(); \
ip.RootScope->addMember(NAME,x); \
}
void javascript::addGlobal(interpreter &ip) {
ref<value> ev = new eval(ip);
ip.RootScope->addMember("eval",ev);
ADD_GLOBAL_OBJECT("parseInt",parseInt)
ADD_GLOBAL_OBJECT("parseFloat",parseFloat)
#ifdef ADVANCED_MATH_AVAILABLE
ADD_GLOBAL_OBJECT("isNaN",isNaN)
ADD_GLOBAL_OBJECT("isFinite",isFinite)
#endif
// *** FIXME hope this is portable
float zero = 0;
ip.RootScope->addMember("NaN",makeConstant(0.0/zero));
ip.RootScope->addMember("Infinity",makeConstant(1.0/zero));
ip.RootScope->addMember("undefined",makeUndefined());
}
void javascript::addMath(interpreter &ip) {
ADD_GLOBAL_OBJECT("Math",Math)
}
void javascript::addStandardLibrary(interpreter &ip) {
addGlobal(ip);
addMath(ip);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,168 +0,0 @@
/* -------- definitions ------- */
%option c++ yylineno noyywrap prefix="js" outfile="lex.javascript.cc" batch
%{
#include <ixlib_js_internals.hh>
#include <ixlib_token_javascript.hh>
using namespace ixion;
using namespace javascript;
%}
WHITESPACE [ \t\n\r]
DIGIT [0-9]
DIGIT_NZ [1-9]
DIGIT_OCT [0-7]
DIGIT_HEX [0-9a-fA-F]
DIGIT_SEQ {DIGIT}+
NONDIGIT [_a-zA-Z]
ID_COMPONENT [_a-zA-Z0-9]
ESCAPE_SIMPLE \\['"?\\abfnrtv]
ESCAPE_OCTAL \\{DIGIT_OCT}{1,3}
ESCAPE_HEX \\x{DIGIT_HEX}{1,2}
ESCAPE {ESCAPE_SIMPLE}|{ESCAPE_OCTAL}|{ESCAPE_HEX}
S_CHAR [^"\\\n]|{ESCAPE}
SIGN \+|\-
SIGNopt {SIGN}?
/* higher-level entities ------------------------------------------------------
*/
IDENTIFIER {NONDIGIT}{ID_COMPONENT}*
/* literals -------------------------------------------------------------------
*/
LIT_DECIMAL {DIGIT_NZ}{DIGIT}*
LIT_OCTAL 0{DIGIT_OCT}*
LIT_HEX 0[xX]{DIGIT_HEX}+
LIT_INT ({LIT_DECIMAL}|{LIT_OCTAL}|{LIT_HEX})
LIT_STRING \"{S_CHAR}*\"|\'{S_CHAR}*\'
LIT_FRACTION {DIGIT_SEQ}?\.{DIGIT_SEQ}|{DIGIT_SEQ}\.
LIT_EXPONENT [eE]{SIGNopt}{DIGIT_SEQ}
LIT_FLOAT {LIT_FRACTION}{LIT_EXPONENT}?|{DIGIT_SEQ}{LIT_EXPONENT}
/* Contexts -------------------------------------------------------------------
*/
%x Comment
%x LineComment
/* Rules ----------------------------------------------------------------------
*/
%%
\/\* BEGIN(Comment);
<Comment>\*\/ BEGIN(INITIAL);
<Comment><<EOF>> EXJS_THROW(ECJS_UNTERMINATED_COMMENT)
<Comment>. /* nothing */
<Comment>\n /* nothing */
\/\/ BEGIN(LineComment);
<LineComment>[\n\r]+ BEGIN(INITIAL);
<LineComment>. /* nothing */
<<EOF>> return TT_EOF;
\{ return '{';
\} return '}';
\; return ';';
\[ return '[';
\] return ']';
\( return '(';
\) return ')';
\? return '?';
\: return ':';
\+ return '+';
\- return '-';
\* return '*';
\/ return '/';
\% return '%';
\^ return '^';
\& return '&';
\| return '|';
\~ return '~';
\! return '!';
\= return '=';
\< return '<';
\> return '>';
\, return ',';
\. return '.';
\+\= return TT_JS_PLUS_ASSIGN;
\-\= return TT_JS_MINUS_ASSIGN;
\*\= return TT_JS_MULTIPLY_ASSIGN;
\/\= return TT_JS_DIVIDE_ASSIGN;
\%\= return TT_JS_MODULO_ASSIGN;
\^\= return TT_JS_BIT_XOR_ASSIGN;
\&\= return TT_JS_BIT_AND_ASSIGN;
\|\= return TT_JS_BIT_OR_ASSIGN;
\<\< return TT_JS_LEFT_SHIFT;
\>\> return TT_JS_RIGHT_SHIFT;
\<\<\= return TT_JS_LEFT_SHIFT_ASSIGN;
\>\>\= return TT_JS_RIGHT_SHIFT_ASSIGN;
\=\=\= return TT_JS_IDENTICAL;
\!\=\= return TT_JS_NOT_IDENTICAL;
\=\= return TT_JS_EQUAL;
\!\= return TT_JS_NOT_EQUAL;
\<\= return TT_JS_LESS_EQUAL;
\>\= return TT_JS_GREATER_EQUAL;
\&\& return TT_JS_LOGICAL_AND;
\|\| return TT_JS_LOGICAL_OR;
\+\+ return TT_JS_INCREMENT;
\-\- return TT_JS_DECREMENT;
new return TT_JS_NEW;
this return TT_JS_THIS;
function return TT_JS_FUNCTION;
var return TT_JS_VAR;
null return TT_JS_NULL;
if return TT_JS_IF;
while return TT_JS_WHILE;
do return TT_JS_DO;
else return TT_JS_ELSE;
for return TT_JS_FOR;
return return TT_JS_RETURN;
switch return TT_JS_SWITCH;
case return TT_JS_CASE;
continue return TT_JS_CONTINUE;
break return TT_JS_BREAK;
default return TT_JS_DEFAULT;
true return TT_JS_LIT_TRUE;
false return TT_JS_LIT_FALSE;
undefined return TT_JS_LIT_UNDEFINED;
in return TT_JS_IN;
const return TT_JS_CONST;
class return TT_JS_CLASS;
extends return TT_JS_EXTENDS;
namespace return TT_JS_NAMESPACE;
static return TT_JS_STATIC;
constructor return TT_JS_CONSTRUCTOR;
{LIT_INT} return TT_JS_LIT_INT;
{LIT_FLOAT} return TT_JS_LIT_FLOAT;
{LIT_STRING} return TT_JS_LIT_STRING;
{IDENTIFIER} return TT_JS_IDENTIFIER;
{WHITESPACE}+ /* nothing */
. EXJS_THROWINFOLOCATION(ECJS_INVALID_TOKEN,YYText(),code_location(lineno()))

View File

@@ -1,41 +0,0 @@
#include <ixlib_js_internals.hh>
#include <ixlib_exbase.hh>
#include <ixlib_javascript.hh>
#include <fstream>
using namespace ixion;
using namespace ixion::javascript;
IXLIB_JS_DECLARE_FUNCTION(write)
{
if (parameters.size() != 1) {
EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS, "write");
}
std::cout << parameters[0]->toString();
return makeConstant(parameters[0]->toString());
}
int main (int ac, char ** av) {
interpreter *jsint = new interpreter();
addStandardLibrary(*jsint);
ref<value> x = new write();
jsint->RootScope->addMember("write", x);
if (ac == 1) {
std::cerr << "Usage: " << av[0] << "<file+>" << std::endl;
exit(1);
}
for (int i = 1; i < ac; i++) {
std::ifstream input(av[i]);
try {
ref<value> result = jsint->execute(input);
std::cout << av[i] << " returned " << result->stringify() << std::endl;
} catch (base_exception &ex) {
std::cerr << ex.getText() << ex.what() << std::endl;
}
input.close();
}
delete jsint;
}

View File

@@ -1,144 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Numeric conversions
// ----------------------------------------------------------------------------
// (c) Copyright 1999 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <ixlib_exgen.hh>
#include <ixlib_numconv.hh>
#include <stdio.h>
using namespace std;
using namespace ixion;
// data objects --------------------------------------------------------------
static string numChars = IXLIB_NUMCHARS;
// exported subroutines -------------------------------------------------------
string ixion::float2dec(double value) {
char buf[255];
sprintf((char *)&buf,"%f",value);
return string(buf);
}
string ixion::float2dec(double value, unsigned int precision) {
char buf[255];
string cmd("%.");
cmd += unsigned2dec(precision) + "f";
sprintf((char *)&buf,cmd.c_str(),value);
return string(buf);
}
string ixion::unsigned2base(unsigned long value,char digits,char radix) {
string temp;
do {
temp = numChars[value % radix]+temp;
value /= radix;
if (digits) digits--;
} while (value || digits);
return temp;
}
string ixion::signed2base(signed long value,char digits,char radix) {
if (value < 0) return "-"+unsigned2base(-value,digits,radix);
else return unsigned2base(value,digits,radix);
}
string ixion::bytes2dec(TSize bytes) {
if (bytes>(TSize) 10*1024*1024)
return unsigned2dec(bytes / ((TSize) 1024*1024))+" MB";
if (bytes>(TSize) 10*1024)
return unsigned2dec(bytes / ((TSize) 1024))+" KB";
return unsigned2dec(bytes)+" Byte";
}
unsigned long ixion::evalNumeral(string const &numeral,unsigned radix) {
string numstr = upper(numeral);
if (numstr.size() == 0) return 0;
unsigned long value = 0, mulvalue = 1;
TIndex index = numstr.size()-1;
do {
string::size_type digvalue = numChars.find(numstr[index]);
if (digvalue == string::npos)
EXGEN_THROWINFO(EC_CANNOTEVALUATE,numstr.c_str())
value += mulvalue * digvalue;
mulvalue *= radix;
} while (index--);
return value;
}
double ixion::evalFloat(string const &numeral) {
double result;
int count = sscanf(numeral.c_str(), "%le", &result);
if (count == 0) EXGEN_THROWINFO(EC_CANNOTEVALUATE,numeral.c_str())
else return result;
}
unsigned long ixion::evalUnsigned(string const &numeral,unsigned default_base) {
if (numeral.size() == 0) return 0;
if (numeral.substr(0,2) == "0X" || numeral.substr(0,2) == "0x")
return evalNumeral(numeral.substr(2),0x10);
if (numeral.substr(0,1) == "$")
return evalNumeral(numeral.substr(1),0x10);
char lastchar = numeral[numeral.size()-1];
if (lastchar == 'H' || lastchar == 'h') return evalNumeral(numeral.substr(0,numeral.size()-1),0x10);
if (lastchar == 'B' || lastchar == 'b') return evalNumeral(numeral.substr(0,numeral.size()-1),2);
if (lastchar == 'D' || lastchar == 'd') return evalNumeral(numeral.substr(0,numeral.size()-1),10);
if (lastchar == 'O' || lastchar == 'o') return evalNumeral(numeral.substr(0,numeral.size()-1),8);
return evalNumeral(numeral,default_base);
}
signed long ixion::evalSigned(string const &numeral,unsigned default_base) {
if (numeral.size() == 0) return 0;
if (numeral[0] == '-')
return - (signed long) evalUnsigned(numeral.substr(1),default_base);
else {
if (numeral[0] == '+')
return evalUnsigned(numeral.substr(1),default_base);
else
return evalUnsigned(numeral,default_base);
}
}

View File

@@ -1,38 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Numeric / order processing
// ----------------------------------------------------------------------------
// (c) Copyright 1998 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <ixlib_numeric.hh>
// BCD encoding ---------------------------------------------------------------
unsigned long ixion::unsigned2BCD(unsigned long value)
{
unsigned long bcdvalue = 0,bcdshift = 0;
while (value) {
bcdvalue += (value % 10) << bcdshift;
bcdshift += 4;
value /= 10;
}
return bcdvalue;
}
unsigned long ixion::BCD2unsigned(unsigned long value)
{
unsigned long decvalue = 0;
for (unsigned long i = 1;value;i *= 10) {
decvalue += (value & 0xf) * i;
value >>= 4;
}
return decvalue;
}

View File

@@ -1,427 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Regular expressions string object.
// ----------------------------------------------------------------------------
// (c) Copyright 1998 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <stack>
#include <cctype>
#include "ixlib_i18n.hh"
#include <ixlib_exgen.hh>
#include <ixlib_numeric.hh>
#include <ixlib_numconv.hh>
#include <ixlib_re.hh>
#include <ixlib_re_impl.hh>
using namespace std;
using namespace ixion;
// Template instantiations ----------------------------------------------------
template regex<string>;
// Error texts ----------------------------------------------------------------
static char *RegexPlainText[] = {
N_("Invalid quantifier"),
N_("Unbalanced backreference"),
N_("Invalid escape sequence"),
N_("Invalid backreference"),
N_("Unterminated character class"),
N_("Unable to match without expression"),
};
// regex_exception ------------------------------------------------------------
regex_exception::regex_exception(TErrorCode error,
char const *info,char *module,TIndex line)
: base_exception(error,info,module,line,"RE") {
}
char *regex_exception::getText() const {
return _(RegexPlainText[Error]);
}
// regex_string::class_matcher ------------------------------------------------
regex_string::class_matcher::class_matcher()
: Negated(false) {
MatchLength = 1;
}
regex_string::class_matcher::class_matcher(string const &cls)
: Negated(false) {
MatchLength = 1;
if (cls.size() && cls[0] == XSTRRE_CLASSNEG) {
expandClass(cls.substr(1));
Negated = true;
}
else
expandClass(cls);
}
ixion::regex<string>::matcher *ixion::regex_string::class_matcher::duplicate() const {
class_matcher *dupe = new class_matcher();
dupe->copy(this);
return dupe;
}
bool regex_string::class_matcher::match(backref_stack &brstack,string const &candidate,TIndex at) {
if (at >= candidate.size()) return false;
bool result = Set[candidate[at]];
if (Negated) result = !result;
return result && matchNext(brstack,candidate,at+1);
}
void regex_string::class_matcher::expandClass(string const &cls) {
memset(&Set,0,sizeof(Set));
if (cls.size() == 0) return;
Set[cls[0]] = true;
char lastchar = cls[0];
for (TIndex index = 1;index < cls.size();index++) {
if ((cls[index] == XSTRRE_CLASSRANGE) && (index < cls.size()-1)) {
for (char ch = lastchar+1;ch < cls[index+1];ch++)
Set[ch] = true;
}
else Set[cls[index]] = true;
lastchar = cls[index];
}
}
void ixion::regex_string::class_matcher::copy(class_matcher const *src) {
super::copy(src);
for (TIndex i = 0;i < CharValues;i++)
Set[i] = src->Set[i];
Negated = src->Negated;
}
// regex_string::special_class_matcher ----------------------------------------
regex_string::special_class_matcher::special_class_matcher(type tp)
: Type(tp) {
MatchLength = 1;
}
ixion::regex<string>::matcher *ixion::regex_string::special_class_matcher::duplicate() const {
special_class_matcher *dupe = new special_class_matcher(Type);
dupe->copy(this);
return dupe;
}
bool regex_string::special_class_matcher::match(backref_stack &brstack,string const &candidate,TIndex at) {
if (at >= candidate.size()) return false;
enum type { DIGIT,NONDIGIT,ALNUM,NONALNUM,SPACE,NONSPACE };
bool result;
switch (Type) {
case DIGIT: result = isdigit(candidate[at]);
break;
case NONDIGIT: result = !isdigit(candidate[at]);
break;
case ALNUM: result = isalnum(candidate[at]);
break;
case NONALNUM: result = !isalnum(candidate[at]);
break;
case SPACE: result = isspace(candidate[at]);
break;
case NONSPACE: result = !isspace(candidate[at]);
break;
default:
EX_THROW(regex,ECRE_INVESCAPE)
}
return result && matchNext(brstack,candidate,at+1);
}
// regex_string ---------------------------------------------------------------
void regex_string::parse(string const &expr) {
auto_ptr<matcher> new_re(parseRegex(expr));
ParsedRegex = new_re;
}
string regex_string::replaceAll(string const &candidate,string const &replacement,TIndex from) {
string result;
string tempreplacement;
LastCandidate = candidate;
if (ParsedRegex.get() == NULL)
EX_THROW(regex,ECRE_NOPATTERN)
for (TIndex index = from;index < candidate.size();) {
BackrefStack.clear();
if (ParsedRegex->match(BackrefStack,candidate,index)) {
TIndex matchlength = ParsedRegex->subsequentMatchLength();
tempreplacement = replacement;
TSize backrefs = BackrefStack.size();
for (TIndex i = 0;i < backrefs;i++)
tempreplacement = findReplace(tempreplacement,XSTRRE_BACKREF+unsigned2dec(i),
BackrefStack.get(i,LastCandidate));
result += tempreplacement;
index += matchlength;
}
else result += candidate[index++];
}
return result;
}
regex_string::matcher *regex_string::parseRegex(string const &expr) {
if (!expr.size()) return NULL;
TIndex index = 0;
matcher *firstobject,*lastobject = NULL;
alternative_matcher *alternative = NULL;
while (index < expr.size()) {
matcher *object = NULL;
quantifier *quantifier = NULL;
bool quantified = true;
char ch;
// several objects may be inserted in one loop run
switch (expr[index++]) {
// case XSTRRE_BACKREF: (dupe)
// case XSTRRE_ESCAPESEQ: (dupe)
case XSTRRE_LITERAL: {
if (index >= expr.size()) EX_THROW(regex,ECRE_INVESCAPE)
ch = expr[index++];
if (isdigit(ch))
object = new backref_matcher(ch-'0');
else {
switch (ch) {
case 'd': object = new special_class_matcher(special_class_matcher::DIGIT);
break;
case 'D': object = new special_class_matcher(special_class_matcher::NONDIGIT);
break;
case 'w': object = new special_class_matcher(special_class_matcher::ALNUM);
break;
case 'W': object = new special_class_matcher(special_class_matcher::NONALNUM);
break;
case 's': object = new special_class_matcher(special_class_matcher::SPACE);
break;
case 'S': object = new special_class_matcher(special_class_matcher::NONSPACE);
break;
default: object = new sequence_matcher(string(1,ch));
}
}
break;
}
case XSTRRE_ANYCHAR:
object = new any_matcher;
break;
case XSTRRE_START:
quantified = false;
object = new start_matcher;
break;
case XSTRRE_END:
quantified = false;
object = new end_matcher;
break;
case XSTRRE_ALTERNATIVE: {
if (!alternative)
alternative = new alternative_matcher;
alternative->addAlternative(firstobject);
firstobject = NULL;
lastobject = NULL;
break;
}
case XSTRRE_CLASSSTART: {
TIndex classend = expr.find(XSTRRE_CLASSSTOP,index);
if (classend == string::npos)
EX_THROW(regex,ECRE_UNTERMCLASS)
object = new class_matcher(expr.substr(index,classend-index));
index = classend+1;
break;
}
case XSTRRE_BACKREFSTART: {
matcher *parsed;
TSize brlevel = 1;
for (TIndex searchstop = index;searchstop < expr.size();searchstop++) {
if ((expr[searchstop] == XSTRRE_BACKREFSTART) &&
(expr[searchstop-1] != XSTRRE_LITERAL))
brlevel++;
if ((expr[searchstop] == XSTRRE_BACKREFSTOP) &&
(expr[searchstop-1] != XSTRRE_LITERAL)) {
brlevel--;
if (brlevel == 0) {
parsed = parseRegex(expr.substr(index,searchstop-index));
if (!parsed) EX_THROW(regex,ECRE_INVBACKREF)
index = searchstop+1;
break;
}
}
}
if (!parsed) EX_THROW(regex,ECRE_UNBALBACKREF)
object = new backref_open_matcher;
object->setNext(parsed);
matcher *closer = new backref_close_matcher;
matcher *searchlast = parsed,*foundlast;
while (searchlast) {
foundlast = searchlast;
searchlast = searchlast->getNext();
}
foundlast->setNext(closer);
break;
}
case XSTRRE_BACKREFSTOP:
EX_THROW(regex,ECRE_UNBALBACKREF)
default:
object = new sequence_matcher(expr.substr(index-1,1));
break;
}
if (object) {
if (quantified) quantifier = parseQuantifier(expr,index);
if (quantifier) {
quantifier->setQuantified(object);
if (lastobject) lastobject->setNext(quantifier);
else firstobject = quantifier;
}
else {
if (lastobject) lastobject->setNext(object);
else firstobject = object;
}
}
// we need this for the alternative matcher, which also inserts
// its connector
matcher *searchlast = quantifier ? quantifier : object;
while (searchlast) {
lastobject = searchlast;
searchlast = searchlast->getNext();
}
}
if (alternative) {
alternative->addAlternative(firstobject);
return alternative;
}
else return firstobject;
}
regex_string::quantifier *regex_string::parseQuantifier(string const &expr,TIndex &at) {
quantifier *quant = NULL;
if (at == expr.size()) return NULL;
if (expr[at] == XSTRREQ_0PLUS) {
quant = new quantifier(isGreedy(expr,++at),0);
return quant;
}
if (expr[at] == XSTRREQ_1PLUS) {
quant = new quantifier(isGreedy(expr,++at),1);
return quant;
}
if (expr[at] == XSTRREQ_01) {
quant = new quantifier(isGreedy(expr,++at),0,1);
return quant;
}
if (expr[at] == XSTRREQ_START) {
TSize min,max;
at++;
TIndex endindex;
endindex = expr.find(XSTRREQ_STOP,at);
if (endindex == string::npos)
EXGEN_THROW(ECRE_INVQUANTIFIER)
string quantspec = expr.substr(at,endindex-at);
at = endindex+1;
try {
string::size_type rangeindex = quantspec.find(XSTRREQ_RANGE);
if (rangeindex == string::npos) {
min = evalUnsigned(quantspec);
quant = new quantifier(isGreedy(expr,at),min,min);
}
else if (rangeindex == quantspec.size()-1) {
min = evalUnsigned(quantspec.substr(0,rangeindex));
quant = new quantifier(isGreedy(expr,at),min);
}
else {
min = evalUnsigned(quantspec.substr(0,rangeindex));
max = evalUnsigned(quantspec.substr(rangeindex+1));
quant = new quantifier(isGreedy(expr,at),min,max);
}
return quant;
}
EX_CONVERT(generic,EC_CANNOTEVALUATE,regex,ECRE_INVQUANTIFIER)
}
return NULL;
}
bool regex_string::isGreedy(string const &expr,TIndex &at)
{
if (at == expr.size()) return true;
if (expr[at] == XSTRREQ_NONGREEDY) {
at++;
return false;
}
else return true;
}

View File

@@ -1,108 +0,0 @@
// ----------------------------------------------------------------------------
// Description : Scanner for xTextFile
// ----------------------------------------------------------------------------
// (c) Copyright 1999 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <FlexLexer.h>
#include "ixlib_i18n.hh"
#include <ixlib_numconv.hh>
#include <ixlib_token_lex.hh>
#include <ixlib_scanner.hh>
using namespace std;
using namespace ixion;
// Plain text rendering table -------------------------------------------------
static char *(PlainText[]) = {
N_("Unknown token"),
N_("End of input")
};
// scanner_exception ----------------------------------------------------------
scanner_exception::scanner_exception(TErrorCode error, TIndex line,
string const &info)
: base_exception(error, NULL, NULL, 0, "SCAN") {
HasInfo = true;
try {
string temp = "line ";
temp += unsigned2dec(line);
if (info != "") {
temp += " : ";
temp += info;
}
strcpy(Info, temp.c_str());
}
catch (...) { }
}
char *scanner_exception::getText() const {
return PlainText[Error];
}
// scanner --------------------------------------------------------------------
scanner::scanner(FlexLexer &lexer)
: Lexer(lexer) {
}
scanner::token_list scanner::scan() {
CurrentToken.Type = Lexer.yylex();
CurrentToken.Line = Lexer.lineno();
CurrentToken.Text = Lexer.YYText();
token_list tokenlist;
while (!reachedEOF()) {
tokenlist.push_back(getNextToken());
}
return tokenlist;
}
scanner::token scanner::getNextToken() {
if (!reachedEOF()) {
token lasttoken = CurrentToken;
CurrentToken.Type = Lexer.yylex();
CurrentToken.Line = Lexer.lineno();
CurrentToken.Text = Lexer.YYText();
if (CurrentToken.Type == TT_UNKNOWN)
throw scanner_exception(ECSCAN_UNKNOWN_TOKEN,CurrentToken.Line,CurrentToken.Text);
else return lasttoken;
}
throw scanner_exception(ECSCAN_UNKNOWN_TOKEN, CurrentToken.Line, "");
}
bool scanner::reachedEOF() const {
return (CurrentToken.Type == TT_EOF);
}

View File

@@ -1,317 +0,0 @@
// ----------------------------------------------------------------------------
// Description : String object
// ----------------------------------------------------------------------------
// (c) Copyright 1999 by iXiONmedia, all rights reserved.
// ----------------------------------------------------------------------------
#include <cstring>
#include <cctype>
#include <ixlib_numconv.hh>
#include <ixlib_string.hh>
using namespace std;
using namespace ixion;
// String utility functions ---------------------------------------------------
string ixion::findReplace(string const &target,string const &src,string const &dest) {
string result = target;
TIndex foundpos = string::npos;
TIndex n = src.size();
while ((foundpos = result.find(src)) != string::npos)
result.replace(foundpos,n,dest);
return result;
}
string ixion::findReplace(string const &target,char* src,char *dest) {
string result = target;
TSize foundpos = string::npos;
TSize n = strlen(src);
while ((foundpos = result.find(src)) != string::npos)
result.replace(foundpos,n,dest);
return result;
}
string ixion::findReplace(string const &target,char src,char dest) {
string result = target;
string::iterator first = result.begin(),last = result.end();
while (first != last) {
if (*first == src) *first = dest;
first++;
}
return result;
}
string ixion::upper(string const &original) {
string temp(original);
string::iterator first = temp.begin(),last = temp.end();
while (first != last) {
*first = toupper(*first);
first++;
}
return temp;
}
string ixion::lower(string const &original) {
string temp(original);
string::iterator first = temp.begin(),last = temp.end();
while (first != last) {
*first = tolower(*first);
first++;
}
return temp;
}
string ixion::removeLeading(string const &original,char ch) {
string copy(original);
string::iterator first = copy.begin(), last = copy.end();
while (first != last && *first == ch) first++;
if (first != copy.begin()) copy.erase(copy.begin(),first);
return copy;
}
string ixion::removeTrailing(string const &original,char ch) {
string copy(original);
string::iterator first = copy.begin(), last = copy.end();
if (first != last) {
last--;
while (first != last && *last == ch) last--;
if (*last != ch) last++;
}
if (last != copy.end()) copy.erase(last,copy.end());
return copy;
}
string ixion::removeLeadingTrailing(string const &original,char ch) {
string copy(original);
string::iterator first = copy.begin(), last = copy.end();
while (first != last && *first == ch) first++;
if (first != copy.begin()) copy.erase(copy.begin(),first);
first = copy.begin();
last = copy.end();
if (first != last) {
last--;
while (first != last && *last == ch) last--;
if (*last != ch) last++;
}
if (last != copy.end()) copy.erase(last,copy.end());
return copy;
}
string ixion::parseCEscapes(string const &original) {
string result = "";
string::const_iterator first = original.begin(),last = original.end();
while (first != last) {
if (*first == '\\') {
first++;
if (first == last) {
result += '\\';
break;
}
#define GET_TEMP_STRING(LENGTH) \
if (original.end()-first < LENGTH) \
EXGEN_THROWINFO(EC_INVALIDPAR,"invalid escape sequence") \
tempstring = string(first,first+LENGTH); \
first += LENGTH;
char value;
string tempstring;
switch (*first) {
case 'b': result += '\b'; first++; break;
case 'f': result += '\f'; first++; break;
case 'n': result += '\n'; first++; break;
case 't': result += '\t'; first++; break;
case 'v': result += '\v'; first++; break;
case 'X':
case 'x': first++;
GET_TEMP_STRING(2)
value = evalNumeral(tempstring,16);
result += value;
break;
case 'u': first++;
GET_TEMP_STRING(4)
value = evalNumeral(tempstring,16);
result += value;
break;
case '0':
GET_TEMP_STRING(3)
value = evalNumeral(tempstring,8);
result += value;
break;
default: result += *first++;
}
}
else result += *first++;
}
return result;
}
namespace {
TByte const B64_INVALID = 0xff;
TByte const B64_PAD = 0xfe;
char const B64_PAD_CHAR = '=';
char Base64EncodeTable[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
TByte Base64DecodeTable[] = { // based at 0
// see test/invertmap.js on how to generate this table
B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,
B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,
B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,
B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,
B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,
B64_INVALID,B64_INVALID,B64_INVALID,62,B64_INVALID,B64_INVALID,B64_INVALID,63,52,53,54,
55,56,57,58,59,60,61,B64_INVALID,B64_INVALID,B64_INVALID,B64_PAD,B64_INVALID,
B64_INVALID,B64_INVALID,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
19,20,21,22,23,24,25,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,
B64_INVALID,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,
44,45,46,47,48,49,50,51,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,B64_INVALID,
};
}
TSize ixion::getMaxBase64DecodedSize(TSize encoded) {
return ((encoded+3)/4)*3;
}
TSize ixion::base64decode(TByte *data,string const &base64) {
string::const_iterator first = base64.begin(),last = base64.end();
TByte *data_start = data;
TUnsigned32 block;
TByte a,b,c,d;
while (first != last) {
a = Base64DecodeTable[*(first++)];
b = Base64DecodeTable[*(first++)];
c = Base64DecodeTable[*(first++)];
d = Base64DecodeTable[*(first++)];
if (c == B64_PAD) {
block = a << 3*6 | b << 2*6;
*data++ = (block >> 16) & 0xff;
}
else if (d == B64_PAD) {
block = a << 3*6 | b << 2*6 | c << 1*6;
*data++ = (block >> 16) & 0xff;
*data++ = (block >> 8) & 0xff;
}
else {
block = a << 3*6 | b << 2*6 | c << 1*6 | d << 0*6;
*data++ = (block >> 16) & 0xff;
*data++ = (block >> 8) & 0xff;
*data++ = (block >> 0) & 0xff;
}
}
return data-data_start;
}
void ixion::base64encode(string &base64,TByte const *data,TSize size) {
base64.resize((size+2)/3*4);
TUnsigned32 block;
TByte a,b,c,d;
TByte const *end = data+size;
string::iterator first = base64.begin();
while (data < end)
if (data+1 == end) {
block = data[0] << 16;
a = (block >> 3*6) & 0x3f;
b = (block >> 2*6) & 0x3f;
*first++ = Base64EncodeTable[a];
*first++ = Base64EncodeTable[b];
*first++ = B64_PAD_CHAR;
*first++ = B64_PAD_CHAR;
data++;
}
else if (data+2 == end) {
block = data[0] << 16 | data[1] << 8;
a = (block >> 3*6) & 0x3f;
b = (block >> 2*6) & 0x3f;
c = (block >> 1*6) & 0x3f;
*first++ = Base64EncodeTable[a];
*first++ = Base64EncodeTable[b];
*first++ = Base64EncodeTable[c];
*first++ = B64_PAD_CHAR;
data += 2;
}
else {
block = data[0] << 16 | data[1] << 8 | data[2];
a = (block >> 3*6) & 0x3f;
b = (block >> 2*6) & 0x3f;
c = (block >> 1*6) & 0x3f;
d = (block >> 0*6) & 0x3f;
*first++ = Base64EncodeTable[a];
*first++ = Base64EncodeTable[b];
*first++ = Base64EncodeTable[c];
*first++ = Base64EncodeTable[d];
data += 3;
}
}
// string_hash ----------------------------------------------------------------
unsigned long ixion::string_hash::operator()(string const &str) const {
// the sgi stl uses the same hash algorithm
unsigned long h = 0;
FOREACH_CONST(first,str,string)
h = 5*h + *first;
return h;
}

View File

@@ -22,6 +22,10 @@
//
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <simgear/compiler.h>
#include <stdio.h>

View File

@@ -49,6 +49,11 @@ typedef vector < int > int_list;
typedef int_list::iterator int_list_iterator;
typedef int_list::const_iterator const_int_list_iterator;
/** STL vector list of doubles */
typedef vector < double > double_list;
typedef double_list::iterator double_list_iterator;
typedef double_list::const_iterator const_double_list_iterator;
/** STL vector list of Point3D */
typedef vector < Point3D > point_list;
typedef point_list::iterator point_list_iterator;

View File

@@ -8,36 +8,6 @@
#include "props_io.hxx"
////////////////////////////////////////////////////////////////////////
// Implementation of SGCommandState class.
////////////////////////////////////////////////////////////////////////
SGCommandState::SGCommandState ()
: _args(0)
{
}
SGCommandState::SGCommandState (const SGPropertyNode * args)
: _args(0)
{
setArgs(args);
}
SGCommandState::~SGCommandState ()
{
delete _args;
}
void
SGCommandState::setArgs (const SGPropertyNode * args)
{
delete _args;
_args = new SGPropertyNode();
copyProperties(args, _args);
}
////////////////////////////////////////////////////////////////////////
// Implementation of SGCommandMgr class.
@@ -81,14 +51,13 @@ SGCommandMgr::getCommandNames () const
}
bool
SGCommandMgr::execute (const string &name, const SGPropertyNode * arg,
SGCommandState ** state) const
SGCommandMgr::execute (const string &name, const SGPropertyNode * arg) const
{
command_t command = getCommand(name);
if (command == 0)
return false;
else
return (*command)(arg, state);
return (*command)(arg);
}
// end of commands.cxx

View File

@@ -24,58 +24,13 @@ SG_USING_STD(map);
SG_USING_STD(vector);
/**
* Stored state for a command.
*
* <p>This class allows a command to cache parts of its state between
* invocations with the same parameters. Nearly every command that
* actually uses this will subclass it in some way. The command
* allocates the structure, but it is up to the caller to delete it
* when it is no longer necessary, unless the command deletes it
* and replaces the value with 0 or another command-state object
* first.</p>
*
* <p>Note that this class is for caching only; all of the information
* in it must be recoverable by other means, since the state could
* arbitrarily disappear between invocations if the caller decides to
* delete it.</p>
*
* <p>By default, the command state includes a place to keep a copy of
* the parameters.</p>
*
* @author David Megginson, david@megginson.com
*/
class SGCommandState
{
public:
SGCommandState ();
SGCommandState (const SGPropertyNode * args);
virtual ~SGCommandState ();
virtual void setArgs (const SGPropertyNode * args);
virtual const SGPropertyNode * getArgs () const { return _args; }
private:
SGPropertyNode * _args;
};
/**
* Manage commands.
*
* <p>This class allows the application to register and unregister
* commands, and provides shortcuts for executing them. Commands are
* simple functions that take a const pointer to an SGPropertyNode and
* a pointer to a pointer variable (which should be 0 initially) where
* the function can store compiled copies of its arguments, etc. to
* avoid expensive recalculations. If the command deletes the
* SGCommandState, it must replace it with a new pointer or 0;
* otherwise, the caller is free to delete and zero the pointer at any
* time and the command will start fresh with the next invocation.
* The command must return a bool value indicating success or failure.
* The property node may be ignored, or it may contain values that the
* command uses as parameters.</p>
*
* <p>There are convenience methods for invoking a command function
* with no arguments or with a single, primitive argument.</p>
* simple functions that take a const pointer to an SGPropertyNode:
* the function may use the nodes children as parameters.</p>
*
* @author David Megginson, david@megginson.com
*/
@@ -86,8 +41,7 @@ public:
/**
* Type for a command function.
*/
typedef bool (*command_t) (const SGPropertyNode * arg,
SGCommandState ** state);
typedef bool (*command_t) (const SGPropertyNode * arg);
/**
@@ -136,9 +90,6 @@ public:
/**
* Execute a command.
*
* This is the primary method for invoking a command; the others
* are convenience methods that invoke this one indirectly.
*
* @param name The name of the command.
* @param arg A const pointer to an SGPropertyNode. The node
* may have a value and/or children, etc., so that it is possible
@@ -146,9 +97,7 @@ public:
* @return true if the command is present and executes successfully,
* false otherwise.
*/
virtual bool execute (const string &name,
const SGPropertyNode * arg,
SGCommandState ** state) const;
virtual bool execute (const string &name, const SGPropertyNode * arg) const;
private:

View File

@@ -140,6 +140,7 @@ void
PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
{
State &st = state();
const char * attval;
if (_level == 0) {
if (string(name) != (string)"PropertyList") {
@@ -148,12 +149,23 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
message += "; expected PropertyList";
throw sg_io_exception(message, "SimGear Property Reader");
}
// Check for an include.
attval = atts.getValue("include");
if (attval != 0) {
SGPath path(SGPath(_base).dir());
path.append(attval);
try {
readProperties(path.str(), _root);
} catch (sg_io_exception &e) {
setException(e);
}
}
push_state(_root, "", DEFAULT_MODE);
}
else {
const char * attval;
// Get the index.
attval = atts.getValue("n");
int index = 0;

View File

@@ -1,5 +1,7 @@
includedir = @includedir@/sky
SUBDIRS = clouds3d
lib_LIBRARIES = libsgsky.a
include_HEADERS = \

View File

@@ -368,5 +368,9 @@ ssgSimpleState *SGCloudMakeState( const string &path ) {
state->enable( GL_ALPHA_TEST );
state->setAlphaClamp( 0.01 );
// ref() the state so it doesn't get deleted if the last layer of
// it's type is deleted.
state->ref();
return state;
}

View File

@@ -0,0 +1,53 @@
includedir = @includedir@/sky/clouds3d
# enable the following line once extgl.c get's added to the distro
EXTRA_DIST = extgl.c extgl.h
if EXTGL_NEEDED
EXTGL_SOURCE = extgl.c extgl.h
else
EXTGL_SOURCE =
endif
lib_LIBRARIES = libsgclouds3d.a
include_HEADERS = \
SkySceneLoader.hpp \
SkyUtil.hpp
libsgclouds3d_a_SOURCES = \
$(EXTGL_SOURCE) \
vec3fv.cpp vec3fv.hpp vec3f.hpp vec4f.hpp vec2f.hpp \
mat16fv.cpp mat16fv.hpp \
mat33.hpp mat33impl.hpp \
mat44.hpp mat44impl.hpp \
tri.cpp tri.hpp \
plane.cpp plane.hpp \
camera.cpp camera.hpp \
camutils.cpp camutils.hpp \
minmaxbox.cpp minmaxbox.hpp \
SkyAABBTree.hpp \
SkyArchive.cpp SkyArchive.hpp \
SkyBoundingVolume.hpp \
SkyBVTree.hpp SkyBVTreeSplitter.hpp \
SkyCloud.cpp SkyCloud.hpp \
SkyCloudParticle.hpp \
SkyContext.cpp SkyContext.hpp \
SkyDynamicTextureManager.cpp SkyDynamicTextureManager.hpp \
SkyLight.cpp SkyLight.hpp \
SkyMaterial.cpp SkyMaterial.hpp \
SkyMinMaxBox.cpp SkyMinMaxBox.hpp \
SkyRenderable.hpp \
SkyRenderableInstance.hpp \
SkyRenderableInstanceCloud.cpp SkyRenderableInstanceCloud.hpp \
SkyRenderableInstanceGeneric.hpp \
SkyRenderableInstanceGroup.cpp SkyRenderableInstanceGroup.hpp \
SkySceneLoader.cpp \
SkySceneManager.cpp SkySceneManager.hpp \
SkySingleton.hpp \
SkyTexture.hpp \
SkyTextureManager.cpp SkyTextureManager.hpp \
SkyTextureState.cpp SkyTextureState.hpp \
SkyUtil.cpp
INCLUDES = -I$(top_srcdir)

View 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__

File diff suppressed because it is too large Load Diff

View 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__

View 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__

View 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__

View 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 &center)
* @brief Sets the center of the bounding volume.
*/
virtual void SetCenter(const Vec3f &center) { _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__

View File

@@ -0,0 +1,980 @@
//------------------------------------------------------------------------------
// File : SkyCloud.cpp
//------------------------------------------------------------------------------
// SkyWorks : Adapted from skyworks program writen by Mark J. Harris and
// The University of North Carolina at Chapel Hill
// : by J. Wojnaroski Sep 2002
//------------------------------------------------------------------------------
// 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 "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.
_vecSortPos = -cam.ViewDir();
_vecSortPos *= (1.1 * _boundingBox.GetRadius());
_vecSortPos += _boundingBox.GetCenter();
// 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());
_vecSortPos += _boundingBox.GetCenter();
// 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();
// _vecLastSortCamPos = GLVU::GetCurrent()->GetCurrentCam()->Orig;
// 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;
}
SKYRESULT SkyCloud::Load(const SkyArchive &archive,
float rScale, /* = 1.0f */
double latitude, double longitude )
{
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
// this "almost" works not quite the right solution okay to get some up and running
// we need to develop our own scheme for loading and positioning clouds
Mat33f R;
Vec3f moveit;
R.Set( 0, 1, 0,
1, 0, 0,
0, 0, 1);
// clouds sit in the y-z plane and x-axis is the vertical cloud height
Rotate( R );
// rotate the cloud field about the fgfs z-axis based on initial longitude
float ex = 0.0;
float ey = 0.0;
float ez = 1.0;
float phi = longitude / 57.29578;
float one_min_cos = 1 - cos(phi);
R.Set(
cos(phi) + one_min_cos*ex*ex, one_min_cos*ex*ey - ez*sin(phi), one_min_cos*ex*ez + ey*sin(phi),
one_min_cos*ex*ey + ez*sin(phi), cos(phi) + one_min_cos*ey*ey, one_min_cos*ey*ez - ex*sin(phi),
one_min_cos*ex*ez - ey*sin(phi), one_min_cos*ey*ez + ex*sin(phi), cos(phi) + one_min_cos*ez*ez );
Rotate( R );
// okay now that let's rotate about a vector for latitude where longitude forms the
// components of a unit vector in the x-y plane
ex = sin( longitude / 57.29578 );
ey = -cos( longitude / 57.29578 );
ez = 0.0;
phi = latitude / 57.29578;
one_min_cos = 1 - cos(phi);
R.Set(
cos(phi) + one_min_cos*ex*ex, one_min_cos*ex*ey - ez*sin(phi), one_min_cos*ex*ez + ey*sin(phi),
one_min_cos*ex*ey + ez*sin(phi), cos(phi) + one_min_cos*ey*ey, one_min_cos*ey*ez - ex*sin(phi),
one_min_cos*ex*ez - ey*sin(phi), one_min_cos*ey*ez + ex*sin(phi), cos(phi) + one_min_cos*ez*ez );
Rotate( R );
// need to calculate an offset to place the clouds at ~3000 feet MSL ATM this is an approximation
// to move the clouds to some altitude above sea level. At some locations this could be underground
// will need a better scheme to position clouds per user preferences
float cloud_level_msl = 3000.0f;
float x_offset = ex * cloud_level_msl;
float y_offset = ey * cloud_level_msl;
float z_offset = cloud_level_msl * 0.5;
moveit.Set( x_offset, y_offset, z_offset );
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))
}

View File

@@ -0,0 +1,177 @@
//------------------------------------------------------------------------------
// 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"
#include <plib/sg.h>
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,double latitude=0.0, double longitude=0.0);
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__

View 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__

View File

@@ -0,0 +1,305 @@
//------------------------------------------------------------------------------
// 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.
*/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <GL/glut.h>
#ifndef WIN32
#include <GL/glx.h>
#endif
//#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()
{
#ifdef WIN32
ContextMaterialIterator cmi = _currentMaterials.find(wglGetCurrentContext());
#else
ContextMaterialIterator cmi = _currentMaterials.find(glXGetCurrentContext());
#endif
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()
{
#ifdef WIN32
ContextTextureStateIterator ctsi = _currentTextureState.find(wglGetCurrentContext());
#else
ContextTextureStateIterator ctsi = _currentTextureState.find(glXGetCurrentContext());
#endif
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;
#ifdef WIN32
_currentMaterials.insert(std::make_pair(wglGetCurrentContext(), pCurrentMaterial));
#else
_currentMaterials.insert(std::make_pair(glXGetCurrentContext(), pCurrentMaterial));
#endif
SkyTextureState *pCurrentTS = new SkyTextureState;
#ifdef WIN32
_currentTextureState.insert(std::make_pair(wglGetCurrentContext() , pCurrentTS));
#else
_currentTextureState.insert(std::make_pair(glXGetCurrentContext() , pCurrentTS));
#endif
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;
}

View File

@@ -0,0 +1,139 @@
//------------------------------------------------------------------------------
// 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__
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
// warning for truncation of template name for browse info
// #pragma warning( disable : 4786)
#include "SkySingleton.hpp"
#include <simgear/compiler.h>
#include <list>
#include <map>
#include <algorithm>
#ifdef WIN32
# include "extgl.h"
#else
typedef void *HANDLE;
typedef HANDLE *PHANDLE;
#define DECLARE_HANDLE(n) typedef HANDLE n
DECLARE_HANDLE(HGLRC);
#endif
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__

View 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__

View 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__

View 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;
}

View 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__

View File

@@ -0,0 +1,231 @@
//------------------------------------------------------------------------------
// 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.
*/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#ifdef WIN32
# ifdef _MSC_VER
# pragma warning( disable : 4786)
# endif
# include "extgl.h"
#endif
#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;
}

View 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__

View File

@@ -0,0 +1,445 @@
//------------------------------------------------------------------------------
// 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;
}
//------------------------------------------------------------------------------
// Function : SkyMaterial::Force
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMaterial::Force()
* @brief @todo <WRITE BRIEF SkyMaterial::SetMaterialPropertiesForDisplay DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyMaterial::SetMaterialPropertiesForDisplay FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyMaterial::Force()
{
// 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
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &(GetDiffuse().x));
pCurrentMaterial->SetDiffuse(GetDiffuse());
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &(GetSpecular().x));
pCurrentMaterial->SetSpecular(GetSpecular());
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &(GetAmbient().x));
pCurrentMaterial->SetAmbient(GetAmbient());
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &(GetEmissive().x));
pCurrentMaterial->SetEmissive(GetEmissive());
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GetSpecularPower());
pCurrentMaterial->SetSpecularPower(GetSpecularPower());
// lighting
if (IsLightingEnabled())
glEnable(GL_LIGHTING);
else
glDisable(GL_LIGHTING);
pCurrentMaterial->EnableLighting(IsLightingEnabled());
// color material (which material property tracks color calls)
glColorMaterial(GetColorMaterialFace(), GetColorMaterialMode());
pCurrentMaterial->SetColorMaterialFace(GetColorMaterialFace());
pCurrentMaterial->SetColorMaterialMode(GetColorMaterialMode());
if (IsColorMaterialEnabled())
glEnable(GL_COLOR_MATERIAL);
else
glDisable(GL_COLOR_MATERIAL);
pCurrentMaterial->EnableColorMaterial(IsColorMaterialEnabled());
// fog
glFogf(GL_FOG_MODE, GetFogMode());
pCurrentMaterial->SetFogMode(GetFogMode());
glFogfv(GL_FOG_COLOR, GetFogColor());
pCurrentMaterial->SetFogColor(GetFogColor());
glFogf(GL_FOG_DENSITY, GetFogParameter(GL_FOG_DENSITY));
pCurrentMaterial->SetFogParameter(GL_FOG_DENSITY, GetFogParameter(GL_FOG_DENSITY));
glFogf(GL_FOG_START, GetFogParameter(GL_FOG_START));
pCurrentMaterial->SetFogParameter(GL_FOG_START, GetFogParameter(GL_FOG_START));
glFogf(GL_FOG_END, GetFogParameter(GL_FOG_END));
pCurrentMaterial->SetFogParameter(GL_FOG_END, GetFogParameter(GL_FOG_END));
if (IsFogEnabled())
glEnable(GL_FOG);
else
glDisable(GL_FOG);
pCurrentMaterial->EnableFog(IsFogEnabled());
// depth test
glDepthFunc(GetDepthFunc());
pCurrentMaterial->SetDepthFunc(GetDepthFunc());
glDepthMask(GetDepthMask());
pCurrentMaterial->SetDepthMask(GetDepthMask());
if (IsDepthTestEnabled())
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
pCurrentMaterial->EnableDepthTest(IsDepthTestEnabled());
// alpha test
glAlphaFunc(GetAlphaFunc(), GetAlphaRef());
pCurrentMaterial->SetAlphaFunc(GetAlphaFunc());
pCurrentMaterial->SetAlphaRef(GetAlphaRef());
if (IsAlphaTestEnabled())
glEnable(GL_ALPHA_TEST);
else
glDisable(GL_ALPHA_TEST);
// blending
glBlendFunc(GetBlendingSourceFactor(), GetBlendingDestFactor());
pCurrentMaterial->SetBlendFunc(GetBlendingSourceFactor(), GetBlendingDestFactor());
if (IsBlendingEnabled())
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
pCurrentMaterial->EnableBlending(IsBlendingEnabled());
glCullFace(GetFaceCullingMode());
pCurrentMaterial->SetFaceCullingMode(GetFaceCullingMode());
if (IsFaceCullingEnabled())
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
pCurrentMaterial->EnableFaceCulling(IsFaceCullingEnabled());
// texturing
FAIL_RETURN(_textureState.Force());
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GetTextureApplicationMode());
pCurrentMaterial->SetTextureApplicationMode(GetTextureApplicationMode());
return SKYRESULT_OK;
}

View File

@@ -0,0 +1,269 @@
//------------------------------------------------------------------------------
// 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();
SKYRESULT Force();
// 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__

View 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);
}

View 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__

View 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__

View 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__

View File

@@ -0,0 +1,708 @@
//------------------------------------------------------------------------------
// 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()));
}
else
{//cout << "Using impostor image\n";
if (!_pBackTexture || (bDisplayFrontOfSplit && !_pFrontTexture)) {
// cout << "texture id failure" << endl;
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();
// s_pMaterial->Force();
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);
}
s_iCount++;
}

View 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__

View 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__

View 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);
}
}

View 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__

View File

@@ -0,0 +1,250 @@
//------------------------------------------------------------------------------
// 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 <plib/sg.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/math/point3d.hxx>
#include <simgear/math/polar3d.hxx>
#include <simgear/math/vector.hxx>
#include "SkySceneLoader.hpp"
#include "SkySceneManager.hpp"
#include "SkyTextureManager.hpp"
#include "SkySceneManager.hpp"
#include "SkyDynamicTextureManager.hpp"
#include "SkyContext.hpp"
#include "SkyLight.hpp"
#include "camera.hpp"
ssgLight _sky_ssgLights [ 8 ] ;
sgdVec3 cam_pos;
static sgdVec3 delta;
Point3D origin;
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);
// hack
sgMat4 my_copy_of_ssgOpenGLAxisSwapMatrix =
{
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f }
};
//------------------------------------------------------------------------------
// 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 filepath)
bool SkySceneLoader::Load( SGPath filename, double latitude, double longitude )
{
SkyArchive archive;
SGPath base = filename.dir();
if (SKYFAILED(archive.Load(filename.c_str()))) {
cout << "Archive file not found\n" << filename.c_str();
return false;
}
char *pFilename;
// Need to create the managers
cout << "GraphicsContext::Instantiate();" << endl;
GraphicsContext::Instantiate();
cout << " TextureManager::Instantiate();" << endl;
TextureManager::Instantiate();
cout << " DynamicTextureManager::Instantiate();" << endl;
DynamicTextureManager::Instantiate();
cout << " SceneManager::Instantiate();" << endl;
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));
// this is where we have to append the $fg_root string to the filename
base.append( pFilename );
const char *FilePath = base.c_str();
//float rScale = 1.0;
//FAIL_RETURN(archive.FindFloat32("CloudScale", &rScale, i));
float rScale = 40.0;
SkyArchive cloudArchive;
FAIL_RETURN(cloudArchive.Load(FilePath));
FAIL_RETURN(SceneManager::InstancePtr()->LoadClouds(cloudArchive, rScale, latitude, longitude));
}
}
Vec3f dir(0, 0, 1);
pLight->SetPosition(Vec3f(0, 0, 17000));
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 )
{
// set origin for cloud coordinates to initial tile center
origin = *posit;
sgdSetVec3( delta, origin[0], origin[1], origin[2]);
//printf("Cloud marker %f %f %f\n", origin[0], origin[1], origin[2] );
}
void SkySceneLoader::Update( double *view_pos )
{
double wind_x, wind_y, wind_z;
wind_x = 0.0; wind_z = 0.0;
// just a dumb test to see what happens if we can move the clouds en masse via the camera
delta[0] += wind_x; delta[2] += wind_z;
sgdSubVec3( cam_pos, view_pos, delta );
//cout << "ORIGIN: " << delta[0] << " " << delta[1] << " " << delta[2] << endl;
//cout << "CAM : " << cam_pos[0] << " " << cam_pos[1] << " " << cam_pos[2] << 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( sgMat4 mat )
{/* need this if you want to look at FG matrix
if ( _ssgCurrentContext == NULL )
{
cout<< "ssg: No Current Context: Did you forgot to call ssgInit()?" ; char x; cin >> x;
}
ssgForceBasicState () ;
*/
sgMat4 test, m, *pm, viewmat, cameraMatrix;
pm = &m;
sgSetVec4(mat[3], cam_pos[0], cam_pos[1], cam_pos[2], SG_ONE);
// at this point the view matrix has the cloud camera position relative to cloud origin
// now transform to screen coordinates
sgTransposeNegateMat4 ( viewmat, mat ) ;
sgCopyMat4 ( cameraMatrix, my_copy_of_ssgOpenGLAxisSwapMatrix ) ;
sgPreMultMat4 ( cameraMatrix, viewmat ) ;
//sgCopyMat4 ( test, cameraMatrix );
//printf( "\nSkyworks ViewModel 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;
// this is the cameraview matrix used by flightgear to render scene
//_ssgCurrentContext->getModelviewMatrix( m );
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity () ;
glLoadMatrixf( (float *) cameraMatrix );
//sgCopyMat4( test, m );
pCam->SetModelviewMatrix( (float *) cameraMatrix );
//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;
SceneManager::InstancePtr()->Display(*pCam);
//pLight->Display(); // draw the light position to debug with sun position
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity () ;
}

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// 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__
#ifdef HAVE_CONFIG
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/math/point3d.hxx>
#include "SkyUtil.hpp"
//------------------------------------------------------------------------------
/**
* @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( SGPath fileroot, double latitude, double longitude );
void Set_Cloud_Orig( Point3D *posit );
void Update( double *view_pos );
void Resize( double w, double h);
void Draw( sgMat4 mat );
};
#endif //__SKYSCENELOADER_HPP__

View File

@@ -0,0 +1,922 @@
//------------------------------------------------------------------------------
// 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 "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.Force();
_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, double latitude, double longitude)
{
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+1, iNumClouds);
cloudArchive.FindArchive("Cloud", &subArchive, i);
SkyCloud *pCloud = new SkyCloud();
pCloud->Load(subArchive, rScale, latitude, longitude);
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))
return _TestInsertInstanceIntoClouds(cam, pNode->GetRightChild(), pInstanceToInsert, bTransparent);
else
return true;
}
}
else
return false;
}

View 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, double latitude=0.0, double longitude=0.0);
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__

View 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__

View File

@@ -0,0 +1,100 @@
//------------------------------------------------------------------------------
// 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 )
#define __glext_h_
#define __GLEXT_H_
#define __glext_h_
#define __GLEXT_H_
#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__

View 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.c_str());
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)
{
GLenum 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,
(GLenum) iFormat,
GL_UNSIGNED_BYTE,
pData);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D,
0, 0, 0,
iWidth, iHeight,
(GLenum) 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)
{
glDeleteTextures(texture.iDepth, texture.pSliceIDs);
delete [] texture.pSliceIDs;
} */
}

View 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

View File

@@ -0,0 +1,351 @@
//------------------------------------------------------------------------------
// 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;
#ifdef GL_ARB_multitexture
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &iNumTextureUnits);
if (iNumTextureUnits > 0)
s_iNumTextureUnits = iNumTextureUnits;
else
s_iNumTextureUnits = 1;
#endif
}
_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)
{
#ifdef GL_ARB_multitexture
if (s_iNumTextureUnits > 1)
glActiveTextureARB(GL_TEXTURE0_ARB + i);
#endif
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_MAG_FILTER, paramValue);
}
//GLVU::CheckForGLError("SkyTextureState::Activate()");
}
#ifdef GL_ARB_multitexture
if (s_iNumTextureUnits > 1)
glActiveTextureARB(GL_TEXTURE0_ARB);
#endif
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::Force
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::Force()
* @brief @todo <WRITE BRIEF SkyTextureState::Activate DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyTextureState::Activate FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyTextureState::Force()
{
SkyTextureState *pCurrent = GraphicsContext::InstancePtr()->GetCurrentTextureState();
assert(NULL != pCurrent);
//GLVU::CheckForGLError("SkyTextureState::Activate(8)");
for (unsigned int i = 0; i < s_iNumTextureUnits; ++i)
{
#ifdef GL_ARB_multitexture
if (s_iNumTextureUnits > 1)
glActiveTextureARB(GL_TEXTURE0_ARB + i);
#endif
bool bEnabled = IsTextureEnabled(i);
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)");
GLenum eTarget = GetActiveTarget(i);
unsigned int iID = GetTextureID(i);
FAIL_RETURN(pCurrent->SetTexture(i, eTarget, iID));
glBindTexture(eTarget, iID);
//GLVU::CheckForGLError("SkyTextureState::Activate(5)");
GLenum paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_S);
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);
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);
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);
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);
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_MAG_FILTER, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, paramValue);
#ifdef GL_ARB_multitexture
if (s_iNumTextureUnits > 1)
glActiveTextureARB(GL_TEXTURE0_ARB);
#endif
}
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;
}

View File

@@ -0,0 +1,206 @@
//------------------------------------------------------------------------------
// 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 Force();
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__

View 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
}

View 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__

Some files were not shown because too many files have changed in this diff Show More