Compare commits
43 Commits
RELEASE_0_
...
RELEASE_0_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16bd8cef38 | ||
|
|
f2567f9af4 | ||
|
|
c363758449 | ||
|
|
dfdeb8be9b | ||
|
|
d1c8f60ca9 | ||
|
|
2fb961c922 | ||
|
|
2e17b28994 | ||
|
|
c3f558b034 | ||
|
|
65ce1a04b2 | ||
|
|
3af4a19f76 | ||
|
|
5178f69f18 | ||
|
|
52e2005b3e | ||
|
|
94fa51e3f7 | ||
|
|
590547e12d | ||
|
|
c6832d2513 | ||
|
|
1fd63c30e9 | ||
|
|
f08ae9f2ea | ||
|
|
5c61e97358 | ||
|
|
87e38e2617 | ||
|
|
92e1856caa | ||
|
|
20c099b7ef | ||
|
|
7eb74c7e2a | ||
|
|
8d63c300e2 | ||
|
|
01ccdd3ae1 | ||
|
|
ab074726df | ||
|
|
ed26458a24 | ||
|
|
fcf1d34e55 | ||
|
|
19f99ea273 | ||
|
|
fe5bb76def | ||
|
|
7ecf508453 | ||
|
|
83e6e44eab | ||
|
|
69a93342c0 | ||
|
|
e17338622a | ||
|
|
a67fd7ea99 | ||
|
|
cf2b8afbe9 | ||
|
|
a1e7761384 | ||
|
|
d068915b42 | ||
|
|
adeb0d48fc | ||
|
|
55c89ea865 | ||
|
|
8bd07e358f | ||
|
|
01113e82f3 | ||
|
|
6d79582890 | ||
|
|
2ae3c89406 |
@@ -2,6 +2,7 @@ Makefile
|
||||
Makefile.in
|
||||
SimGear.spec
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.cache
|
||||
config.log
|
||||
config.status
|
||||
|
||||
2
Doxyfile
2
Doxyfile
@@ -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.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
EXTRA_DIST = \
|
||||
acinclude.m4 \
|
||||
autogen.sh \
|
||||
mksymlinks.sh \
|
||||
README.MSVC \
|
||||
README.metakit \
|
||||
README.zlib \
|
||||
|
||||
16
NEWS
16
NEWS
@@ -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
|
||||
|
||||
|
||||
1373
SimGear.dsp
1373
SimGear.dsp
File diff suppressed because it is too large
Load Diff
1
TODO
Normal file
1
TODO
Normal file
@@ -0,0 +1 @@
|
||||
03/25/2001 - Resolve location of Sky dome implimentation documentation.
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
@@ -4,4 +4,5 @@ simgear_config.h
|
||||
simgear_config.h.in
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
stamp-h1
|
||||
version.h
|
||||
|
||||
@@ -30,4 +30,4 @@ SUBDIRS = \
|
||||
timing \
|
||||
xgl
|
||||
|
||||
DIST_SUBDIRS = $(SUBDIRS) interpreter
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#include "interpreter.hxx"
|
||||
|
||||
SGInterpreter::SGInterpreter ()
|
||||
{
|
||||
}
|
||||
|
||||
SGInterpreter::~SGInterpreter ()
|
||||
{
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef __INTERPRETER_HXX
|
||||
#define __INTERPRETER_HXX 1
|
||||
|
||||
class SGInterpreter
|
||||
{
|
||||
public:
|
||||
|
||||
SGInterpreter ();
|
||||
virtual ~SGInterpreter ();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ¶meters); \
|
||||
}; \
|
||||
} \
|
||||
ixion::ref<ixion::javascript::value> NAME::call(parameter_list const ¶meters)
|
||||
|
||||
#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 ¶meters);
|
||||
virtual ref<value> callAsMethod(ref<value> instance,parameter_list const ¶meters);
|
||||
virtual ref<value> construct(parameter_list const ¶meters);
|
||||
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 ¶meters);
|
||||
};
|
||||
|
||||
public:
|
||||
ref<value> lookup(std::string const &identifier);
|
||||
virtual ref<value> callMethod(std::string const &identifier,parameter_list const ¶meters) = 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 ¶meters);
|
||||
|
||||
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
|
||||
@@ -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 ¶meters);
|
||||
|
||||
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 ¶meters);
|
||||
|
||||
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 ¶meters);
|
||||
|
||||
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 ¶meters);
|
||||
ref<value> callAsMethod(ref<value> instance,parameter_list const ¶meters);
|
||||
ref<value> construct(parameter_list const ¶meters);
|
||||
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 ¶meters) const;
|
||||
ref<value> callAsMethod(ref<value> instance,parameter_list const ¶meters);
|
||||
ref<value> construct(parameter_list const ¶meters);
|
||||
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 ¶meters) 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 ¶meters);
|
||||
};
|
||||
|
||||
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 ¶meters);
|
||||
};
|
||||
|
||||
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 ¶meters);
|
||||
};
|
||||
|
||||
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 ¶meters);
|
||||
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 ¶meters);
|
||||
};
|
||||
|
||||
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 ¶meters);
|
||||
};
|
||||
|
||||
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 ¶meters);
|
||||
};
|
||||
|
||||
// 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ¶meters) {
|
||||
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 ¶meters) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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 ¶meters);
|
||||
};
|
||||
|
||||
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 ¶meters);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// eval -----------------------------------------------------------------------
|
||||
ref<value>
|
||||
eval::
|
||||
call(parameter_list const ¶meters) {
|
||||
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 ¶meters) {
|
||||
#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
@@ -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()))
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -22,6 +22,10 @@
|
||||
//
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
includedir = @includedir@/sky
|
||||
|
||||
SUBDIRS = clouds3d
|
||||
|
||||
lib_LIBRARIES = libsgsky.a
|
||||
|
||||
include_HEADERS = \
|
||||
@@ -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;
|
||||
}
|
||||
53
simgear/scene/sky/clouds3d/Makefile.am
Normal file
53
simgear/scene/sky/clouds3d/Makefile.am
Normal 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)
|
||||
19
simgear/scene/sky/clouds3d/SkyAABBTree.hpp
Normal file
19
simgear/scene/sky/clouds3d/SkyAABBTree.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
//============================================================================
|
||||
// File : SkyAABBTree.hpp
|
||||
//
|
||||
// Author : Wesley Hunt
|
||||
//
|
||||
// Content : axis-aligned bounding box tree
|
||||
//
|
||||
//============================================================================
|
||||
#ifndef __SKYAABBTREE_HPP__
|
||||
#define __SKYAABBTREE_HPP__
|
||||
|
||||
#include "SkyBVTree.hpp"
|
||||
#include "SkyBVTreeSplitter.hpp"
|
||||
|
||||
template <class object>
|
||||
class SkyAABBTree : public SkyBVTree<object, SkyMinMaxBox, SkyAABBTreeSplitter<object> >
|
||||
{};
|
||||
|
||||
#endif //__SKYAABBTREE_HPP__
|
||||
1204
simgear/scene/sky/clouds3d/SkyArchive.cpp
Normal file
1204
simgear/scene/sky/clouds3d/SkyArchive.cpp
Normal file
File diff suppressed because it is too large
Load Diff
243
simgear/scene/sky/clouds3d/SkyArchive.hpp
Normal file
243
simgear/scene/sky/clouds3d/SkyArchive.hpp
Normal file
@@ -0,0 +1,243 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyArchive.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyArchive.hpp
|
||||
*
|
||||
* A hierarchical archive Class for storing data.
|
||||
*/
|
||||
#ifndef __SKYARCHIVE_HPP__
|
||||
#define __SKYARCHIVE_HPP__
|
||||
|
||||
// #pragma warning( disable : 4786 )
|
||||
|
||||
#include "vec2f.hpp"
|
||||
#include "vec3f.hpp"
|
||||
#include "vec4f.hpp"
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
#include <map> // for std::multimap
|
||||
|
||||
//! Types supported by the archive system
|
||||
enum SkyArchiveTypeCode
|
||||
{
|
||||
BOOL_TYPE,
|
||||
INT8_TYPE,
|
||||
INT16_TYPE,
|
||||
INT32_TYPE,
|
||||
UINT8_TYPE,
|
||||
UINT16_TYPE,
|
||||
UINT32_TYPE,
|
||||
FLOAT32_TYPE,
|
||||
FLOAT64_TYPE,
|
||||
STRING_TYPE,
|
||||
VEC2F_TYPE,
|
||||
VEC3F_TYPE,
|
||||
VEC4F_TYPE,
|
||||
ARCHIVE_TYPE,
|
||||
ANY_TYPE,
|
||||
NULL_TYPE
|
||||
};
|
||||
|
||||
struct SkyArchiveEntry;
|
||||
|
||||
struct StringLessFunctor
|
||||
{
|
||||
bool operator() (const char* p1, const char* p2) const
|
||||
{
|
||||
return ::strcmp( p1, p2) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Class : SkyArchive
|
||||
//
|
||||
//! A simple hierarchical archive file useful for loading and saving data.
|
||||
//
|
||||
/*! SkyArchive bundles information so that an application can store,
|
||||
manipulate, and retrieve data in a storage-independent manner. Information
|
||||
stored in an SkyArchive file can be modified without breaking
|
||||
compatibility with the code that retrieves the data. In essence, it can be
|
||||
thought of as a very basic database mechanism.
|
||||
|
||||
A SkyArchive is simply a container. The class defines methods that allow
|
||||
you to put information in a SkyArchive, determine the information in a
|
||||
SkyArchive, and retrieve information from a SkyArchive. It's important
|
||||
to note that the SkyArchive is a recursive storage mechanism; a
|
||||
SkyArchive itself can hold one or more other SkyArchives.
|
||||
|
||||
Data are added to an archive in fields. The datum in a field is associated
|
||||
with a name, number of bytes, and a type code. The name can be anything you
|
||||
choose and is not required to be unique. The number of bytes must be accurate.
|
||||
The type code must be one of the SkyArchiveTypeCode enums. Several of the Add
|
||||
functions have been specialized for the common base types. It isn't necessary
|
||||
to provide the number of bytes when using the specialized functions, since it can be
|
||||
inferred from the type code.
|
||||
|
||||
The functions that retrieve fields from an archive are similar to the ones
|
||||
that add data, only their roles are reversed. As with the Add functions,
|
||||
there are several specialized functions for the common base types while
|
||||
custom information can be retrieved using the generic FindData function.
|
||||
|
||||
Querying the contents of an archive is provided through the GetInfo
|
||||
functions. These functions are important as they allow you to write
|
||||
code that can intelligently determine how to retrieve information at
|
||||
run-time: you no longer have to hardcode the order in which you retrieve
|
||||
data from your files.
|
||||
|
||||
archive data fields are held in using an STL multimap. The multimap key
|
||||
is a QString (field name) and the data is held in a SkyArchiveEntry
|
||||
structure (see SkyArchive.cpp for details of this structure).
|
||||
The fields are stored in alphabetical order based on the key names.
|
||||
*/
|
||||
class SkyArchive
|
||||
{
|
||||
public:
|
||||
//=========================================================================
|
||||
// Creation & Destruction
|
||||
//=========================================================================
|
||||
// Empty archive: no name, no data fields.
|
||||
SkyArchive();
|
||||
// Creates a named archive with no data fields.
|
||||
SkyArchive( const char* pName);
|
||||
// Deep copy the contents of one archive to another.
|
||||
SkyArchive( const SkyArchive& src);
|
||||
// Deep copy the contents of one archive to another.
|
||||
SkyArchive& operator=( const SkyArchive& src);
|
||||
|
||||
~SkyArchive();
|
||||
|
||||
//=========================================================================
|
||||
// Basic SkyArchive Information
|
||||
//=========================================================================
|
||||
// Returns true if the archive contains no data fields.
|
||||
bool IsEmpty() const;
|
||||
//! Returns the archive's name.
|
||||
const char* GetName() const { return _pName; };
|
||||
|
||||
//=========================================================================
|
||||
// Adding Content to SkyArchive
|
||||
//=========================================================================
|
||||
// Adds a new datafield to the archive.
|
||||
SKYRESULT AddData(const char* pName,
|
||||
SkyArchiveTypeCode eType,
|
||||
const void* pData,
|
||||
unsigned int iNumBytes,
|
||||
unsigned int iNumItems = 1);
|
||||
|
||||
SKYRESULT AddBool( const char* pName, bool aBool);
|
||||
SKYRESULT AddInt8( const char* pName, char anInt8);
|
||||
SKYRESULT AddInt16( const char* pName, short anInt16);
|
||||
SKYRESULT AddInt32( const char* pName, int anInt32);
|
||||
SKYRESULT AddUInt8( const char* pName, unsigned char anUInt8);
|
||||
SKYRESULT AddUInt16( const char* pName, unsigned short anUInt16);
|
||||
SKYRESULT AddUInt32( const char* pName, unsigned int anUInt32);
|
||||
SKYRESULT AddFloat32( const char* pName, float aFloat32);
|
||||
SKYRESULT AddFloat64( const char* pName, double aFloat64);
|
||||
SKYRESULT AddString( const char* pName, const char* pString);
|
||||
|
||||
SKYRESULT AddArchive( const SkyArchive& anArchive);
|
||||
|
||||
// Vector types (MJH:: only supports float versions for now!!!)
|
||||
SKYRESULT AddVec2f( const char* pName, const Vec2f& aPoint2f);
|
||||
SKYRESULT AddVec3f( const char* pName, const Vec3f& aPoint3f);
|
||||
SKYRESULT AddVec4f( const char* pName, const Vec4f& aPoint4f);
|
||||
|
||||
//=========================================================================
|
||||
// Retrieving Content from SkyArchive
|
||||
//=========================================================================
|
||||
// Retrieves the specified datafield the archive, if it exists.
|
||||
SKYRESULT FindData( const char* pName,
|
||||
SkyArchiveTypeCode eType,
|
||||
void** const pData,
|
||||
unsigned int* pNumBytes,
|
||||
unsigned int index = 0) const;
|
||||
|
||||
SKYRESULT FindBool( const char* pName, bool* pBool, unsigned int index = 0) const;
|
||||
SKYRESULT FindInt8( const char* pName, char* pInt8, unsigned int index = 0) const;
|
||||
SKYRESULT FindInt16( const char* pName, short* pInt16, unsigned int index = 0) const;
|
||||
SKYRESULT FindInt32( const char* pName, int* pInt32, unsigned int index = 0) const;
|
||||
SKYRESULT FindUInt8( const char* pName, unsigned char* pUInt8, unsigned int index = 0) const;
|
||||
SKYRESULT FindUInt16( const char* pName, unsigned short* pUInt16, unsigned int index = 0) const;
|
||||
SKYRESULT FindUInt32( const char* pName, unsigned int* pUInt32, unsigned int index = 0) const;
|
||||
SKYRESULT FindFloat32(const char* pName, float* pFloat32, unsigned int index = 0) const;
|
||||
SKYRESULT FindFloat64(const char* pName, double* pFloat64, unsigned int index = 0) const;
|
||||
SKYRESULT FindString( const char* pName, char** const pString, unsigned int index = 0) const;
|
||||
SKYRESULT FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index = 0) const;
|
||||
|
||||
SKYRESULT FindVec2f( const char* pName, Vec2f* pVec2f, unsigned int index = 0) const;
|
||||
SKYRESULT FindVec3f( const char* pName, Vec3f* pVec3f, unsigned int index = 0) const;
|
||||
SKYRESULT FindVec4f( const char* pName, Vec4f* pVec4f, unsigned int index = 0) const;
|
||||
|
||||
SKYRESULT AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index = 0) const;
|
||||
|
||||
//=========================================================================
|
||||
// Querying Contents of SkyArchive
|
||||
//=========================================================================
|
||||
// Computes the number of fields that contain the given name and type.
|
||||
SKYRESULT GetInfo(const char* pName,
|
||||
SkyArchiveTypeCode eType,
|
||||
unsigned int* pNumFound = NULL) const;
|
||||
|
||||
// Returns information about the key at the specified index.
|
||||
SKYRESULT GetInfo(unsigned int iNameIndex,
|
||||
char** pNameFound,
|
||||
SkyArchiveTypeCode* pTypeCode,
|
||||
unsigned int* pNumFound);
|
||||
|
||||
// Computes the number of unique key names in _dataTableable.
|
||||
unsigned int GetNumUniqueNames() const;
|
||||
|
||||
|
||||
// Remove the contents of the SkyArchive.
|
||||
SKYRESULT MakeEmpty();
|
||||
|
||||
// Loads the contents from a file.
|
||||
SKYRESULT Load(const char* pFileName);
|
||||
|
||||
// Commits the contents of a SkyArchive to file storage.
|
||||
SKYRESULT Save(const char* pFileName) const;
|
||||
|
||||
private:
|
||||
|
||||
char* _pName; // this archive's name
|
||||
|
||||
//=========================================================================
|
||||
// Data storage
|
||||
//=========================================================================
|
||||
typedef std::multimap<char*, SkyArchiveEntry*, StringLessFunctor> SkyArchiveMMap;
|
||||
typedef SkyArchiveMMap::const_iterator SkyMMapConstIter;
|
||||
typedef SkyArchiveMMap::iterator SkyMMapIter;
|
||||
|
||||
SkyArchiveMMap _dataTable; // this is where the data reside.
|
||||
|
||||
// Performs a deep-copy of one archive's archive_mmap_t to another.
|
||||
void _CopyDataTable( const SkyArchiveMMap& src);
|
||||
|
||||
// Locates an archive entry in _dataTable
|
||||
const SkyArchiveEntry* _FindEntry( const char* pName,
|
||||
unsigned int index,
|
||||
SkyArchiveTypeCode eType) const;
|
||||
|
||||
// Saves the archive to a file stream.
|
||||
SKYRESULT _Save(FILE* pDestFile) const;
|
||||
// Initializes the archive from a file stream.
|
||||
SKYRESULT _Load(FILE* pSrcFile);
|
||||
};
|
||||
|
||||
#endif //__SKYARCHIVE_HPP__
|
||||
297
simgear/scene/sky/clouds3d/SkyBVTree.hpp
Normal file
297
simgear/scene/sky/clouds3d/SkyBVTree.hpp
Normal file
@@ -0,0 +1,297 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyBVTree.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// Empyrean / SkyWorks : Copyright 2002 Mark J. Harris
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @file SkyBVTree.hpp
|
||||
*
|
||||
* This source was written by Wesley Hunt. Many thanks to him for providing it.
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
// SkyBVTree.hpp
|
||||
//
|
||||
// Author: Wesley Hunt (hunt@cs.unc.edu)
|
||||
// Date: 2000/12/19
|
||||
//-----------------------------------------------------------------------------
|
||||
// Overview
|
||||
// --------
|
||||
// declare an SkyBVTree with whatever object type and bounding volume type you
|
||||
// want. The hard part is to pass in a NodeSplitter class that determines how
|
||||
// to split a node up. See below for a description of its requirements.
|
||||
// Finally, use that tree like so:
|
||||
// * BeginTree()
|
||||
// * AddObject(Object, ObjectBV)
|
||||
// * ...
|
||||
// * EndTree()
|
||||
// < Do whatever you want with GetRoot() >
|
||||
// < Use GetLeftChild() and GetRightChild() to traverse the nodes >
|
||||
//
|
||||
// The class hierarchy is designed for a flexible, simple public interface.
|
||||
// This pushes some extra complexity into the class hierarchy, but there are two
|
||||
// main advantages to the final approach:
|
||||
// 1. There are no interface requirements for the Object and BoundingVolume
|
||||
// template parameters. This means you don't have to modify your existing
|
||||
// class interfaces to use them with the tree.
|
||||
// 2. All the dependent logic for dealing with the bounding volumes is pushed
|
||||
// into the NodeSplitter class. So there is one centralized location for
|
||||
// adapting your bounding volume classes to work with the tree. See the
|
||||
// description of the NodeSplitter template requirements for more details.
|
||||
//
|
||||
// Class Descriptions
|
||||
// ------------------
|
||||
//
|
||||
// SkyBaseBVTree
|
||||
// -------------
|
||||
// declares the node class that the tree holds. It exposes
|
||||
// the public functions of the nodes and defines protected accessors that
|
||||
// the derived tree class can use to manipulate nodes and build the tree.
|
||||
//
|
||||
// Node
|
||||
// ----
|
||||
// This is the class that gives access to the tree. You can access each
|
||||
// object and bounding volume owned by a node, along with that node's
|
||||
// children.
|
||||
//
|
||||
// NodeObject
|
||||
// ----------------
|
||||
// An aggregation of an object and its associated bounding volume.
|
||||
// Each node in the tree essentially owns an array of NodeObjects. This
|
||||
// array is passed to the NodeSplitter class to allow it to examine a
|
||||
// node's contained objects before making a decision on how to split the
|
||||
// node up.
|
||||
//
|
||||
// SkyBVTree
|
||||
// ---------
|
||||
// The main tree class. To use it, supply and object type, a bounding volume
|
||||
// type, and a NodeSplitter class that is used to split the nodes up during
|
||||
// tree construction.
|
||||
//
|
||||
// Template class requirements
|
||||
// ---------------------------
|
||||
//
|
||||
// Object
|
||||
// ------
|
||||
// None
|
||||
//
|
||||
// BoundingVolume
|
||||
// --------------
|
||||
// None
|
||||
//
|
||||
// NodeSplitter
|
||||
// ------------
|
||||
// This is the user-supplied class that decides how to split a node during
|
||||
// tree construction. It is given an array of NodeObjects that the node owns and
|
||||
// is responsible for determining the node's bounding volume as well as how to
|
||||
// split the node up into left and right children.
|
||||
// The required API is as follows:
|
||||
//
|
||||
// * a constructor that takes an array of NodeObject and an unsigned int giving
|
||||
// the size of the array. These are the objects owned by the node to be split.
|
||||
// * a method GetNodeBV() that returns the BoundingVolume of the node.
|
||||
// Typically this is the union of the bounding volumes of the objects owned
|
||||
// by the node.
|
||||
// * A unary function operator used to partition the objects in the node. The
|
||||
// operator must take a single NodeObject as a parameter and return as
|
||||
// a bool whether to place the NodeObject in the left or right child.
|
||||
// Basically, it should be compatible with std::partition using NodeObjects.
|
||||
// * A binary function operator used to sort the objects. If a partition fails,
|
||||
// the nodes are then sorted based on this function and half are sent to each child.
|
||||
// This operator must define a total ordering of the NodeObjects.
|
||||
// Basically, it should be compatible with std::sort using NodeObjects.
|
||||
//
|
||||
// Example:
|
||||
// struct NodeSplitter
|
||||
// {
|
||||
// NodeSplitter(const NodeObject* objs, unsigned int numObjs);
|
||||
// BoundingVolume& GetNodeBV() const;
|
||||
// // Partition predicate
|
||||
// bool operator()(const NodeObject& obj) const;
|
||||
// // Sort predicate
|
||||
// bool operator()(const NodeObject& obj1, const NodeObject& obj2) const;
|
||||
// };
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __SKYBVTREE_HPP__
|
||||
#define __SKYBVTREE_HPP__
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SkyBaseBVTree<Object, BoundingVolume>
|
||||
//-----------------------------------------------------------------------------
|
||||
// See header description for details.
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Object, class BoundingVolume>
|
||||
class SkyBaseBVTree
|
||||
{
|
||||
public:
|
||||
typedef BoundingVolume BV;
|
||||
class NodeObject;
|
||||
|
||||
public:
|
||||
class Node
|
||||
{
|
||||
friend class SkyBaseBVTree<Object, BoundingVolume>;
|
||||
public:
|
||||
Node() : _pObjs(NULL), _iNumObjs(0) {}
|
||||
Node(NodeObject* pObjs, unsigned int iNumObjs) : _pObjs(pObjs), _iNumObjs(iNumObjs) {}
|
||||
|
||||
// Public interface
|
||||
const Object& GetObj(unsigned int index) const { assert(_iNumObjs != 0 && _pObjs != NULL && index < _iNumObjs); return _pObjs[index].GetObj(); }
|
||||
const BV& GetBV(unsigned int index) const { assert(_iNumObjs != 0 && _pObjs != NULL && index < _iNumObjs); return _pObjs[index].GetBV(); }
|
||||
unsigned int GetNumObjs() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _iNumObjs; }
|
||||
const BV& GetNodeBV() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _volume; }
|
||||
const Node* GetLeftChild() const { assert(_iNumObjs != 0 && _pObjs != NULL); return this+1; }
|
||||
const Node* GetRightChild() const { assert(_iNumObjs != 0 && _pObjs != NULL); return this+(GetLeftChild()->GetNumObjs()<<1); }
|
||||
bool IsLeaf() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _iNumObjs == 1; }
|
||||
|
||||
private:
|
||||
// List of Objects owned by the node
|
||||
NodeObject *_pObjs;
|
||||
unsigned int _iNumObjs;
|
||||
BV _volume;
|
||||
};
|
||||
|
||||
public:
|
||||
class NodeObject
|
||||
{
|
||||
public:
|
||||
NodeObject(const Object& o, const BV& v) : _obj(o), _volume(v) {}
|
||||
|
||||
const Object& GetObj() const { return _obj; }
|
||||
const BV& GetBV() const { return _volume; }
|
||||
private:
|
||||
Object _obj;
|
||||
BV _volume;
|
||||
};
|
||||
|
||||
protected:
|
||||
// Give non-const access to the node for descendant classes to build the tree
|
||||
BV& GetNodeBV(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode->_volume; }
|
||||
Node* GetLeftChild(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode+1; }
|
||||
Node* GetRightChild(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode+(GetLeftChild(pNode)->GetNumObjs()<<1); }
|
||||
NodeObject* GetObjs(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode->_pObjs; }
|
||||
|
||||
// Links a node's children by assigning the given number of objects to each child
|
||||
// assumes the node has already had it's objects partitioned
|
||||
void LinkNodeChildren(Node* pNode, unsigned int iLeftNumObjs)
|
||||
{
|
||||
assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL);
|
||||
GetLeftChild(pNode)->_pObjs = pNode->_pObjs;
|
||||
GetLeftChild(pNode)->_iNumObjs = iLeftNumObjs;
|
||||
GetRightChild(pNode)->_pObjs = pNode->_pObjs + iLeftNumObjs;
|
||||
GetRightChild(pNode)->_iNumObjs = pNode->_iNumObjs - iLeftNumObjs;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : ClearVector
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn ClearVector(std::vector<T>& vec)
|
||||
* @brief This utility function uses the std::vector::swap trick to free the memory of a vector
|
||||
*
|
||||
* This is necessary since clear() doesn't actually free anything.
|
||||
*/
|
||||
template<class T>
|
||||
void ClearVector(std::vector<T>& vec)
|
||||
{
|
||||
std::vector<T>().swap(vec);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SkyBVTree<Object, BoundingVolume, NodeSplitter>
|
||||
//-----------------------------------------------------------------------------
|
||||
// See header description for details.
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Object, class BoundingVolume, class NodeSplitter>
|
||||
class SkyBVTree : public SkyBaseBVTree<Object, BoundingVolume>
|
||||
{
|
||||
public:
|
||||
typedef SkyBaseBVTree<Object, BoundingVolume> BaseTree;
|
||||
typedef BaseTree::BV BV;
|
||||
typedef BaseTree::NodeObject NodeObject;
|
||||
typedef BaseTree::Node Node;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
BeginTree();
|
||||
}
|
||||
|
||||
void BeginTree(unsigned int iNumObjs = 0)
|
||||
{
|
||||
ClearVector(_objList);
|
||||
ClearVector(_nodes);
|
||||
if (iNumObjs > 0) _objList.reserve(iNumObjs);
|
||||
}
|
||||
|
||||
void AddObject(const Object &obj, const BV& volume)
|
||||
{
|
||||
_objList.push_back(NodeObject(obj, volume));
|
||||
}
|
||||
|
||||
void EndTree()
|
||||
{
|
||||
if (_objList.size() == 0) return;
|
||||
// Initialize the root node with all the objects
|
||||
_nodes.push_back(Node(&_objList[0], _objList.size()));
|
||||
// create room for the other nodes. They are initialized in BuildTree().
|
||||
_nodes.reserve(_objList.size()*2-1);
|
||||
_nodes.resize(_objList.size()*2-1);
|
||||
BuildTree(&_nodes[0]);
|
||||
}
|
||||
|
||||
const Node *GetRoot() const { return _nodes.empty() ? NULL : &_nodes[0]; }
|
||||
|
||||
// Memory usage info
|
||||
unsigned int CalcMemUsage() const
|
||||
{
|
||||
unsigned int usage = 0;
|
||||
usage += sizeof(*this);
|
||||
usage += _objList.capacity() * sizeof(_objList[0]);
|
||||
usage += _nodes.capacity() * sizeof(_nodes[0]);
|
||||
return usage;
|
||||
}
|
||||
|
||||
public:
|
||||
private:
|
||||
// Does the real work
|
||||
void BuildTree(Node *pCurNode)
|
||||
{
|
||||
int iLeftNumObjs;
|
||||
{
|
||||
// Initialize the node splitter with the current node
|
||||
NodeSplitter splitter(GetObjs(pCurNode), pCurNode->GetNumObjs());
|
||||
|
||||
// set the node's bounding volume using the splitter
|
||||
GetNodeBV(pCurNode) = splitter.GetNodeBV();
|
||||
|
||||
// When a node has one object we can stop
|
||||
if (pCurNode->GetNumObjs() == 1) return;
|
||||
|
||||
// Try and partition the objects
|
||||
iLeftNumObjs = std::partition(GetObjs(pCurNode), &GetObjs(pCurNode)[pCurNode->GetNumObjs()], splitter) - GetObjs(pCurNode);
|
||||
|
||||
if ((iLeftNumObjs == 0) || (iLeftNumObjs == pCurNode->GetNumObjs()))
|
||||
{
|
||||
// Partition failed. Sort and split again to force a complete tree
|
||||
std::sort(GetObjs(pCurNode), &GetObjs(pCurNode)[pCurNode->GetNumObjs()], splitter);
|
||||
iLeftNumObjs = pCurNode->GetNumObjs() / 2;
|
||||
}
|
||||
}
|
||||
|
||||
LinkNodeChildren(pCurNode, iLeftNumObjs);
|
||||
BuildTree(GetLeftChild(pCurNode));
|
||||
BuildTree(GetRightChild(pCurNode));
|
||||
}
|
||||
|
||||
std::vector<Node> _nodes;
|
||||
std::vector<NodeObject> _objList;
|
||||
};
|
||||
|
||||
#endif //__SKYBVTREE_HPP__
|
||||
242
simgear/scene/sky/clouds3d/SkyBVTreeSplitter.hpp
Normal file
242
simgear/scene/sky/clouds3d/SkyBVTreeSplitter.hpp
Normal file
@@ -0,0 +1,242 @@
|
||||
//============================================================================
|
||||
// File : SkyBVTreeSplitter.hpp
|
||||
//
|
||||
// Author : Wesley Hunt
|
||||
//
|
||||
// Content : NodeSplitter classes for SkyBVTrees using SkyBoundingBox or
|
||||
// SkyBoundingSphere (not implemented).
|
||||
//
|
||||
//============================================================================
|
||||
#ifndef __SKYBVTREESPLITTER_HPP__
|
||||
#define __SKYBVTREESPLITTER_HPP__
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//-- Includes ----------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
#include "SkyBVTree.hpp"
|
||||
#include "SkyMinMaxBox.hpp"
|
||||
//#include <Mlx/MlxBoundingSphere.hpp>
|
||||
//#if _MSC_VER == 1200
|
||||
//#include <Auxlib/AuxCompileTimeChecker.hpp>
|
||||
//#endif
|
||||
//----------------------------------------------------------------------------
|
||||
//-- Forward Declarations ----------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
// A strategy for splitting nodes compatible with bounding boxes and spheres.
|
||||
template<class Object> class SkyBoundingBoxSplitter;
|
||||
// SkyBVTree compatible node splitters implemented using the above strategy.
|
||||
template<class Object> class SkyAABBTreeSplitter;
|
||||
//template<class Object> class SkySphereTreeSplitter;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//-- Defines, Constants, Enumerated Types ------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
const float rLongObjectPercentageTolerance = 0.75f;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// SkyBoundingBoxSplitter
|
||||
//----------------------------------------------------------------------------
|
||||
// This class defines a NodeSplitter strategy that has the functionality
|
||||
// required by SkyBVTree's NodeSplitter template class. Can be used with
|
||||
// SkyMinMaxBox and SkyBoundingSphere.
|
||||
//
|
||||
// It defines a two-tiered split strategy:
|
||||
//
|
||||
// * First it tries to separate large objects from any smaller objects.
|
||||
// * If there are no large objects, it splits along the midpoint of the longest
|
||||
// axis defined by the objects.
|
||||
// * Finally, if all else fails, it defines a total ordering along the longest
|
||||
// axis based on the center of each node.
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Object>
|
||||
class SkyBoundingBoxSplitter
|
||||
{
|
||||
public:
|
||||
typedef SkyBaseBVTree<Object, SkyMinMaxBox>::NodeObject NodeObjectBox;
|
||||
//typedef SkyBaseBVTree<Object, SkyBoundingSphere>::NodeObject NodeObjectSphere;
|
||||
|
||||
#if _MSC_VER == 1200
|
||||
// !!! WRH HACK MSVC++6 SP5 Workaround.
|
||||
// VC6 can't disambiguate this constructor because it doesn't consider the two
|
||||
// NodeObject templates to be different classes for the purposes of
|
||||
// overloading. It won't recognize that the second template parameters are
|
||||
// different. Forcing them to be explicit template specializations fixes
|
||||
// the problem.
|
||||
template<class BV>
|
||||
SkyBoundingBoxSplitter(const SkyBaseBVTree<Object, BV>::NodeObject*, unsigned int)
|
||||
{
|
||||
//AUX_STATIC_CHECK(false, VisualC_6_WorkAround); ???
|
||||
}
|
||||
template<>
|
||||
#endif
|
||||
SkyBoundingBoxSplitter(const NodeObjectBox* pObjs, unsigned int iNumObjs)
|
||||
{
|
||||
for (unsigned int i = 0; i < iNumObjs; ++i)
|
||||
{
|
||||
_nodeBBox.Union(pObjs[i].GetBV());
|
||||
}
|
||||
Init(pObjs, iNumObjs);
|
||||
}
|
||||
/*#if _MSC_VER == 1200
|
||||
template<>
|
||||
#endif
|
||||
SkyBoundingBoxSplitter(const NodeObjectSphere* objs,
|
||||
#ifdef _PLATFORM_XBOX
|
||||
Int32
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
numObjs)
|
||||
{
|
||||
for (int i=0; i<numObjs; ++i)
|
||||
{
|
||||
SkyMinMaxBox box;
|
||||
box.AddPoint(objs[i].GetBV().GetCenter());
|
||||
box.Bloat(objs[i].GetBV().GetRadius());
|
||||
_nodeBBox.Union(box);
|
||||
}
|
||||
Init(objs, numObjs);
|
||||
}*/
|
||||
|
||||
template<class nodeObj>
|
||||
bool SplitLeft(const nodeObj& obj) const
|
||||
{
|
||||
if (_bIsolateLongObjects)
|
||||
return GetSplitAxisLength(obj.GetBV()) < _rMaxObjectLength;
|
||||
else
|
||||
return GetSplitAxisCenter(obj.GetBV()) < _rSplitValue;
|
||||
}
|
||||
|
||||
template<class nodeObj>
|
||||
bool LessThan(const nodeObj& obj1, const nodeObj& obj2) const
|
||||
{
|
||||
return GetSplitAxisCenter(obj1.GetBV()) < GetSplitAxisCenter(obj2.GetBV());
|
||||
}
|
||||
|
||||
const SkyMinMaxBox& GetNodeBBox() const { return _nodeBBox; }
|
||||
|
||||
private:
|
||||
template<class nodeObj>
|
||||
void Init(const nodeObj* pObjs, unsigned int iNumObjs)
|
||||
{
|
||||
_iSplitAxis = FindSplitAxis(_nodeBBox);
|
||||
_rSplitValue = FindSplitValue(_nodeBBox, _iSplitAxis);
|
||||
_rMaxObjectLength = GetSplitAxisLength(_nodeBBox) * rLongObjectPercentageTolerance;
|
||||
|
||||
_bIsolateLongObjects = false;
|
||||
for (unsigned int i = 0; i < iNumObjs; ++i)
|
||||
{
|
||||
if (GetSplitAxisLength(pObjs[i].GetBV()) > _rMaxObjectLength)
|
||||
{
|
||||
_bIsolateLongObjects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FindSplitAxis(const SkyMinMaxBox& bbox)
|
||||
{
|
||||
int iAxis = 0, i;
|
||||
Vec3f vecExt = bbox.GetMax() - bbox.GetMin();
|
||||
for (i = 1; i < 3; ++i) if (vecExt[i] > vecExt[iAxis]) iAxis = i;
|
||||
return iAxis;
|
||||
}
|
||||
float FindSplitValue(const SkyMinMaxBox& bbox, int iSplitAxis)
|
||||
{
|
||||
return (bbox.GetMin()[iSplitAxis] + bbox.GetMax()[iSplitAxis])*0.5f;
|
||||
}
|
||||
|
||||
/*float GetSplitAxisLength(const SkyBoundingSphere& sphere) const
|
||||
{
|
||||
return 2.f*sphere.GetRadius();
|
||||
}*/
|
||||
float GetSplitAxisLength(const SkyMinMaxBox& bbox) const
|
||||
{
|
||||
return bbox.GetMax()[_iSplitAxis] - bbox.GetMin()[_iSplitAxis];
|
||||
}
|
||||
|
||||
float GetSplitAxisCenter(const SkyMinMaxBox& bbox) const
|
||||
{
|
||||
return (bbox.GetMin()[_iSplitAxis] + bbox.GetMax()[_iSplitAxis]) * 0.5f;
|
||||
}
|
||||
/*float GetSplitAxisCenter(const SkyBoundingSphere& sphere) const
|
||||
{
|
||||
return sphere.GetCenter()[SplitAxis];
|
||||
}*/
|
||||
|
||||
int _iSplitAxis;
|
||||
float _rSplitValue;
|
||||
bool _bIsolateLongObjects;
|
||||
float _rMaxObjectLength;
|
||||
|
||||
SkyMinMaxBox _nodeBBox;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// SkyAABBTreeSplitter
|
||||
//----------------------------------------------------------------------------
|
||||
// A NodeSplitter that is compatible with SkyBVTree for SkyMinMaxBox.
|
||||
// Implemented using the SkyBoundingBoxSplitter strategy.
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Object>
|
||||
class SkyAABBTreeSplitter
|
||||
{
|
||||
public:
|
||||
typedef SkyMinMaxBox BV;
|
||||
typedef SkyBaseBVTree<Object, BV>::NodeObject NodeObject;
|
||||
|
||||
SkyAABBTreeSplitter(const NodeObject* pObjs, unsigned int iNumObjs) : _splitter(pObjs, iNumObjs) {}
|
||||
|
||||
const BV& GetNodeBV() const { return _splitter.GetNodeBBox(); }
|
||||
|
||||
bool operator()(const NodeObject& obj) const
|
||||
{
|
||||
return _splitter.SplitLeft(obj);
|
||||
}
|
||||
|
||||
bool operator()(const NodeObject& obj1, const NodeObject& obj2) const
|
||||
{
|
||||
return _splitter.LessThan(obj1, obj2);
|
||||
}
|
||||
|
||||
private:
|
||||
SkyBoundingBoxSplitter<Object> _splitter;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// SkySphereTreeSplitter
|
||||
//----------------------------------------------------------------------------
|
||||
// A NodeSplitter that is compatible with SkyBVTree for SkyBoundingSphere.
|
||||
// Implemented using the SkyBoundingBoxSplitter strategy.
|
||||
//----------------------------------------------------------------------------
|
||||
/*template<class Object>
|
||||
class SkySphereTreeSplitter
|
||||
{
|
||||
public:
|
||||
typedef SkyBoundingSphere BV;
|
||||
typedef SkyBaseBVTree<Object, BV>::NodeObject NodeObject;
|
||||
|
||||
MlxSphereTreeSplitter(const NodeObject* pObjs, unsigned int iNumObjs) : _splitter(pObjs, iNumObjs)
|
||||
{
|
||||
_nodeBV = pObjs[0].GetBV();
|
||||
for (unsigned int i = 1; i < iNumObjs; ++i) _nodeBV.Union(pObjs[i].GetBV());
|
||||
}
|
||||
|
||||
const BV& GetNodeBV() const { return _nodeBV; }
|
||||
|
||||
bool operator()(const NodeObject& obj) const
|
||||
{
|
||||
return _splitter.SplitLeft(obj);
|
||||
}
|
||||
|
||||
bool operator()(const NodeObject& obj1, const NodeObject& obj2) const
|
||||
{
|
||||
return _splitter.LessThan(obj1, obj2);
|
||||
}
|
||||
|
||||
private:
|
||||
BV _nodeBV;
|
||||
SkyBoundingBoxSplitter<Object> _splitter;
|
||||
};*/
|
||||
|
||||
#endif //__SKYBVTREESPLITTER_HPP__
|
||||
151
simgear/scene/sky/clouds3d/SkyBoundingVolume.hpp
Normal file
151
simgear/scene/sky/clouds3d/SkyBoundingVolume.hpp
Normal file
@@ -0,0 +1,151 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyBoundingVolume.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyBoundingVolume.hpp
|
||||
*
|
||||
* Base class interface definition for a bounding volume.
|
||||
*/
|
||||
#ifndef __SKYBOUNDINGVOLUME_HPP__
|
||||
#define __SKYBOUNDINGVOLUME_HPP__
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include "mat44.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class Camera;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyBoundingVolume
|
||||
* @brief An abstract base class for bounding volumes (AABB,OBB,Sphere,etc.)
|
||||
*
|
||||
* This base class maintains a center and a radius, so it is effectively a bounding
|
||||
* sphere. Derived classes may represent other types of bounding volumes, but they
|
||||
* should be sure to update the radius and center, because some objects will treat
|
||||
* all bounding volumes as spheres.
|
||||
*
|
||||
*/
|
||||
class SkyBoundingVolume
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
SkyBoundingVolume() : _vecCenter(0, 0, 0), _rRadius(0) {}
|
||||
//! Destructor
|
||||
virtual ~SkyBoundingVolume() {}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SetCenter
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SetCenter(const Vec3f ¢er)
|
||||
* @brief Sets the center of the bounding volume.
|
||||
*/
|
||||
virtual void SetCenter(const Vec3f ¢er) { _vecCenter = center; }
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SetRadius
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SetRadius(float radius)
|
||||
* @brief Sets the radius of the bounding volume.
|
||||
*/
|
||||
virtual void SetRadius(float radius) { _rRadius = radius; }
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Vec3f& GetCenter
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Vec3f& GetCenter() const
|
||||
* @brief Returns the center of the bounding volume.
|
||||
*/
|
||||
virtual const Vec3f& GetCenter() const { return _vecCenter; }
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : GetRadius
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn GetRadius() const
|
||||
* @brief Returns the radius ofthe bounding volume.
|
||||
*/
|
||||
virtual float GetRadius() const { return _rRadius; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : ViewFrustumCull
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn ViewFrustumCull( const Camera &cam, const Mat44f &mat )
|
||||
* @brief Cull a bounding volume.
|
||||
*
|
||||
* Returns false if the bounding volume is entirely outside the camera's frustum,
|
||||
* true otherwise.
|
||||
*/
|
||||
virtual bool ViewFrustumCull( const Camera &cam, const Mat44f &mat ) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : AddPoint
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* @fn AddPoint( const Vec3f &pt )
|
||||
* @brief Add a point to a bounding volume.
|
||||
*
|
||||
* One way to create a bounding volume is to add points. What should/could happen
|
||||
* is that the BV will store an object space BV and then when a call to SetPosition
|
||||
* is called, the stored values will be transformed and stored separately, so that
|
||||
* the original values always exist.
|
||||
*
|
||||
*/
|
||||
//virtual void AddPoint( const Vec3f &point ) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : AddPoint
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* @fn AddPoint( float x, float y, float z )
|
||||
* @brief Add a point to a bounding volume.
|
||||
*
|
||||
* @see AddPoint(const Vec3f &pt)
|
||||
*/
|
||||
//virtual void AddPoint( float x, float y, float z ) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Clear
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* @fn Clear()
|
||||
* @brief Clear all data from the bounding volume.
|
||||
*/
|
||||
//virtual void Clear() = 0;
|
||||
|
||||
protected:
|
||||
Vec3f _vecCenter;
|
||||
float _rRadius;
|
||||
};
|
||||
|
||||
#endif //__SKYBOUNDINGVOLUME_HPP__
|
||||
980
simgear/scene/sky/clouds3d/SkyCloud.cpp
Normal file
980
simgear/scene/sky/clouds3d/SkyCloud.cpp
Normal 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))
|
||||
}
|
||||
177
simgear/scene/sky/clouds3d/SkyCloud.hpp
Normal file
177
simgear/scene/sky/clouds3d/SkyCloud.hpp
Normal 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__
|
||||
175
simgear/scene/sky/clouds3d/SkyCloudParticle.hpp
Normal file
175
simgear/scene/sky/clouds3d/SkyCloudParticle.hpp
Normal file
@@ -0,0 +1,175 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyCloudParticle.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
/**
|
||||
* @file SkyCloudParticle.hpp
|
||||
*
|
||||
* Definition of a simple cloud particle class.
|
||||
*/
|
||||
#ifndef __SKYCLOUDPARTICLE_HPP__
|
||||
#define __SKYCLOUDPARTICLE_HPP__
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include "vec4f.hpp"
|
||||
#include <vector>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyCloudParticle
|
||||
* @brief A class for particles that make up a cloud.
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyCloudParticle
|
||||
{
|
||||
public:
|
||||
inline SkyCloudParticle();
|
||||
inline SkyCloudParticle(const Vec3f& pos,
|
||||
float rRadius,
|
||||
const Vec4f& baseColor,
|
||||
float rTransparency = 0);
|
||||
inline ~SkyCloudParticle();
|
||||
|
||||
//! Returns the radius of the particle.
|
||||
float GetRadius() const { return _rRadius; }
|
||||
//! Returns the transparency of the particle.
|
||||
float GetTransparency() const { return _rTransparency; }
|
||||
//! Returns the position of the particle.
|
||||
const Vec3f& GetPosition() const { return _vecPosition; }
|
||||
//! Returns the base color of the particle. This is often used for ambient color.
|
||||
const Vec4f& GetBaseColor() const { return _vecBaseColor; }
|
||||
//! Returns the number of light contributions to this particle's color.
|
||||
unsigned int GetNumLitColors() const { return _vecLitColors.size(); }
|
||||
//! Returns the light contribution to the color of this particle from light @a index.
|
||||
inline const Vec4f& GetLitColor(unsigned int index) const;
|
||||
//! Returns the square distance from the sort position used for the operator< in sorts / splits.
|
||||
float GetSquareSortDistance() const { return _rSquareSortDistance; }
|
||||
|
||||
//! Sets the radius of the particle.
|
||||
void SetRadius(float rad) { _rRadius = rad; }
|
||||
//! Returns the transparency of the particle.
|
||||
void SetTransparency(float trans) { _rTransparency = trans; }
|
||||
//! Sets the position of the particle.
|
||||
void SetPosition(const Vec3f& pos) { _vecPosition = pos; }
|
||||
//! Sets the base color of the particle. This is often used for ambient color.
|
||||
void SetBaseColor(const Vec4f& col) { _vecBaseColor = col; }
|
||||
//! Sets the light contribution to the color of this particle from light @a index.
|
||||
void AddLitColor(const Vec4f& col) { _vecLitColors.push_back(col); }
|
||||
//! Clears the list of light contributions.
|
||||
void ClearLitColors() { _vecLitColors.clear(); }
|
||||
//! Sets the square distance from the sort position used for the operator< in sorts.
|
||||
void SetSquareSortDistance(float rSquareDistance) { _rSquareSortDistance = rSquareDistance; }
|
||||
|
||||
//! This operator is used to sort particle arrays from nearest to farthes.
|
||||
bool operator<(const SkyCloudParticle& p) const
|
||||
{
|
||||
return (_rSquareSortDistance < p._rSquareSortDistance);
|
||||
}
|
||||
|
||||
//! This operator is used to sort particle arrays from farthest to nearest.
|
||||
bool operator>(const SkyCloudParticle& p) const
|
||||
{
|
||||
return (_rSquareSortDistance > p._rSquareSortDistance);
|
||||
}
|
||||
|
||||
protected:
|
||||
float _rRadius;
|
||||
float _rTransparency;
|
||||
Vec3f _vecPosition;
|
||||
Vec4f _vecBaseColor;
|
||||
std::vector<Vec4f> _vecLitColors;
|
||||
Vec3f _vecEye;
|
||||
|
||||
// for sorting particles during shading
|
||||
float _rSquareSortDistance;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloudParticle::SkyCloudParticle
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloudParticle::SkyCloudParticle()
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
inline SkyCloudParticle::SkyCloudParticle()
|
||||
: _rRadius(0),
|
||||
_rTransparency(0),
|
||||
_vecPosition(0, 0, 0),
|
||||
_vecBaseColor(0, 0, 0, 1),
|
||||
_vecEye(0, 0, 0),
|
||||
_rSquareSortDistance(0)
|
||||
{
|
||||
_vecLitColors.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloudParticle::SkyCloudParticle
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloudParticle::SkyCloudParticle(const Vec3f& pos, float rRadius, const Vec4f& baseColor, float rTransparency)
|
||||
* @brief Constructor.
|
||||
*/
|
||||
inline SkyCloudParticle::SkyCloudParticle(const Vec3f& pos,
|
||||
float rRadius,
|
||||
const Vec4f& baseColor,
|
||||
float rTransparency /* = 0 */)
|
||||
: _rRadius(rRadius),
|
||||
_rTransparency(rTransparency),
|
||||
_vecPosition(pos),
|
||||
_vecBaseColor(baseColor),
|
||||
_vecEye(0, 0, 0),
|
||||
_rSquareSortDistance(0)
|
||||
{
|
||||
_vecLitColors.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyCloudParticle::~SkyCloudParticle
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyCloudParticle::~SkyCloudParticle()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
inline SkyCloudParticle::~SkyCloudParticle()
|
||||
{
|
||||
_vecLitColors.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Vec4f& SkyCloudParticle::GetLitColor
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Vec4f& SkyCloudParticle::GetLitColor(unsigned int index) const
|
||||
* @brief Returns the lit color specified by index.
|
||||
*
|
||||
* If the index is out of range, returns a zero vector.
|
||||
*/
|
||||
inline const Vec4f& SkyCloudParticle::GetLitColor(unsigned int index) const
|
||||
{
|
||||
if (index <= _vecLitColors.size())
|
||||
return _vecLitColors[index];
|
||||
else
|
||||
return Vec4f::ZERO;
|
||||
}
|
||||
|
||||
#endif //__SKYCLOUDPARTICLE_HPP__
|
||||
305
simgear/scene/sky/clouds3d/SkyContext.cpp
Normal file
305
simgear/scene/sky/clouds3d/SkyContext.cpp
Normal 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;
|
||||
}
|
||||
139
simgear/scene/sky/clouds3d/SkyContext.hpp
Normal file
139
simgear/scene/sky/clouds3d/SkyContext.hpp
Normal 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__
|
||||
65
simgear/scene/sky/clouds3d/SkyControlled.hpp
Normal file
65
simgear/scene/sky/clouds3d/SkyControlled.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyControlled.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyControlled.hpp
|
||||
*
|
||||
* Interface definition for controlled objects.
|
||||
*/
|
||||
#ifndef __SKYCONTROLLED_HPP__
|
||||
#define __SKYCONTROLLED_HPP__
|
||||
|
||||
//#include "BHXController.hpp"
|
||||
|
||||
template<typename ControlStateType> class SkyController;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyControlled
|
||||
* @brief A base class defining an interface for controlled objects.
|
||||
*
|
||||
* This class abstracts the control of objects into a simple interface that a
|
||||
* class may inherit that allows it to be controlled by SkyController objects.
|
||||
* A class simply inherits from SkyControlled, which forces the class to implement
|
||||
* the method UpdateStateFromControls(). This method usually uses the SkyController
|
||||
* object passed to SetController() to query the input state via
|
||||
* SkyController::GetControlState().
|
||||
*
|
||||
* @see SkyController
|
||||
*/
|
||||
template<typename ControlStateType>
|
||||
class SkyControlled
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
SkyControlled() { _pController = NULL; }
|
||||
//! Destructor
|
||||
virtual ~SkyControlled() { _pController = NULL; }
|
||||
|
||||
//! Sets the controller which will control this controlled object.
|
||||
void SetController(SkyController<ControlStateType> *pController) { _pController = pController; }
|
||||
|
||||
//! Updates the state of the controlled object based on the controls (received from the controller).
|
||||
virtual SKYRESULT UpdateStateFromControls(SKYTIME timeStep) = 0;
|
||||
|
||||
protected:
|
||||
SkyController<ControlStateType> *_pController;
|
||||
ControlStateType _controlState;
|
||||
};
|
||||
|
||||
#endif //__SKYCONTROLLED_HPP__
|
||||
56
simgear/scene/sky/clouds3d/SkyController.hpp
Normal file
56
simgear/scene/sky/clouds3d/SkyController.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyController.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyController.hpp
|
||||
*
|
||||
* Abstract base class for game object controllers.
|
||||
*/
|
||||
#ifndef __SKYCONTROLLER_HPP__
|
||||
#define __SKYCONTROLLER_HPP__
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyController
|
||||
* @brief A class that defines an interface for translating general control input into game object control.
|
||||
*
|
||||
* This class abstracts game object control from specific control input, such
|
||||
* as via user interface devices or via artificial intelligence. Subclasses of
|
||||
* this class implement the method GetControlState() so that objects controlled
|
||||
* by an instance of a SkyController can query the control state that determines
|
||||
* their actions. The object need not know whether it is controlled by a human
|
||||
* or the computer since either controller provides it the same interface.
|
||||
*
|
||||
* @see SkyControlled
|
||||
*/
|
||||
template <typename ControlStateType>
|
||||
class SkyController
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
SkyController() {}
|
||||
//! Destructor.
|
||||
virtual ~SkyController() {}
|
||||
|
||||
//! Fills out the control state structure passed in with the current state of controls.
|
||||
virtual SKYRESULT GetControlState(ControlStateType &controlState) = 0;
|
||||
};
|
||||
|
||||
#endif //__SKYCONTROLLER_HPP__
|
||||
278
simgear/scene/sky/clouds3d/SkyDynamicTextureManager.cpp
Normal file
278
simgear/scene/sky/clouds3d/SkyDynamicTextureManager.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyDynamicTextureManager.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyDynamicTextureManager.cpp
|
||||
*
|
||||
* Implementation of a repository for check out and check in of dynamic textures.
|
||||
*/
|
||||
|
||||
#pragma warning( disable : 4786 )
|
||||
|
||||
#include "SkyDynamicTextureManager.hpp"
|
||||
#include "SkyTexture.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
|
||||
#pragma warning( disable : 4786 )
|
||||
|
||||
//! Set this to 1 to print lots of dynamic texture usage messages.
|
||||
#define SKYDYNTEXTURE_VERBOSE 0
|
||||
//! The maximum number of textures of each resolution to allow in the checked in pool.
|
||||
#define SKYDYNTEXTURE_TEXCACHE_LIMIT 32
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::SkyDynamicTextureManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::SkyDynamicTextureManager()
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyDynamicTextureManager::SkyDynamicTextureManager()
|
||||
#ifdef SKYDYNTEXTURE_VERBOSE
|
||||
: _iNumTextureBytesUsed(0),
|
||||
_iNumTextureBytesCheckedIn(0),
|
||||
_iNumTextureBytesCheckedOut(0)
|
||||
#endif
|
||||
{
|
||||
for (int i = 0; i < 11; ++i)
|
||||
for (int j = 0; j < 11; ++j)
|
||||
_iAvailableSizeCounts[i][j] = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::~SkyDynamicTextureManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::~SkyDynamicTextureManager()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkyDynamicTextureManager::~SkyDynamicTextureManager()
|
||||
{
|
||||
for ( TextureSet::iterator subset = _availableTexturePool.begin();
|
||||
subset != _availableTexturePool.end();
|
||||
++subset )
|
||||
{ // iterate over texture subsets.
|
||||
for ( TextureSubset::iterator texture = (*subset).second->begin();
|
||||
texture != (*subset).second->end();
|
||||
++texture )
|
||||
{
|
||||
texture->second->Destroy();
|
||||
delete texture->second;
|
||||
}
|
||||
subset->second->clear();
|
||||
}
|
||||
_availableTexturePool.clear();
|
||||
|
||||
for ( TextureSubset::iterator texture = _checkedOutTexturePool.begin();
|
||||
texture != _checkedOutTexturePool.end();
|
||||
++texture )
|
||||
{
|
||||
texture->second->Destroy();
|
||||
delete texture->second;
|
||||
}
|
||||
_checkedOutTexturePool.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::CheckOutTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::CheckOutTexture(unsigned int iWidth, unsigned int iHeight)
|
||||
* @brief Returns a texture from the available pool, creating a new one if necessary.
|
||||
*
|
||||
* Thi texture returned by this method is checked out: it will be maintained in a
|
||||
* checked out pool until it is checked in with CheckInTexture(). The texture is owned
|
||||
* by the SkyDynamicTextureManager -- it should not be deleted by another object. Checked out
|
||||
* textures can be modified (copied, or rendered to, etc.), but should not be reallocated
|
||||
* or resized. All checked out textures will be deleted when the SkyDynamicTextureManager
|
||||
* is destroyed, so this manager should be destroyed only after rendering ceases.
|
||||
*/
|
||||
SkyTexture* SkyDynamicTextureManager::CheckOutTexture(unsigned int iWidth,
|
||||
unsigned int iHeight)
|
||||
{
|
||||
int iWidthLog, iHeightLog;
|
||||
iWidthLog = SkyGetLogBaseTwo(iWidth);
|
||||
iHeightLog = SkyGetLogBaseTwo(iHeight);
|
||||
|
||||
// first see if a texture of this resolution is available:
|
||||
// find the subset of textures with width = iWidth, if it exists.
|
||||
TextureSet::iterator subset = _availableTexturePool.find(iWidth);
|
||||
if (subset != _availableTexturePool.end())
|
||||
{ // found the iWidth subset
|
||||
// now find a texture with height = iHeight:
|
||||
TextureSubset::iterator texture = (*subset).second->find(iHeight);
|
||||
if (texture != (*subset).second->end())
|
||||
{ // found one!
|
||||
// extract the texture
|
||||
SkyTexture *pTexture = (*texture).second;
|
||||
(*texture).second = NULL;
|
||||
// first remove it from this set.
|
||||
(*subset).second->erase(texture);
|
||||
// now add it to the checked out texture set.
|
||||
_checkedOutTexturePool.insert(TextureSubset::value_type(pTexture->GetID(), pTexture));
|
||||
|
||||
// update checked out/in amount.
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesCheckedIn -= iWidth * iHeight * 4;
|
||||
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
|
||||
printf("CHECKOUT: %d x %d\n", iWidth, iHeight);
|
||||
#endif
|
||||
_iAvailableSizeCounts[iWidthLog][iHeightLog]--;
|
||||
// we're now free to give this texture to the user
|
||||
return pTexture;
|
||||
}
|
||||
else
|
||||
{ // we didn't find an iWidth x iHeight texture, although the iWidth subset exists
|
||||
// create a new texture of the appropriate dimensions and return it.
|
||||
SkyTexture *pNewTexture = CreateDynamicTexture(iWidth, iHeight);
|
||||
_checkedOutTexturePool.insert(TextureSubset::value_type(pNewTexture->GetID(),
|
||||
pNewTexture));
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
|
||||
#endif
|
||||
|
||||
return pNewTexture;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // we don't yet have a subset for iWidth textures. Create one.
|
||||
TextureSubset *pSubset = new TextureSubset;
|
||||
_availableTexturePool.insert(TextureSet::value_type(iWidth, pSubset));
|
||||
// now create a new texture of the appropriate dimensions and return it.
|
||||
SkyTexture *pNewTexture = CreateDynamicTexture(iWidth, iHeight);
|
||||
_checkedOutTexturePool.insert(TextureSubset::value_type(pNewTexture->GetID(), pNewTexture));
|
||||
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
|
||||
#endif
|
||||
return pNewTexture;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::CheckInTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::CheckInTexture(SkyTexture *pTexture)
|
||||
* @brief Returns a checked-out texture to the available pool.
|
||||
*
|
||||
* This method removes the checked out texture from the checked out pool if it is
|
||||
* checked out, and then checks it in to the available pool.
|
||||
*/
|
||||
void SkyDynamicTextureManager::CheckInTexture(SkyTexture *pTexture)
|
||||
{
|
||||
// first see if the texture is in the checked out pool.
|
||||
TextureSubset::iterator coTexture = _checkedOutTexturePool.find(pTexture->GetID());
|
||||
if (coTexture != _checkedOutTexturePool.end())
|
||||
{ // if it is there, remove it.
|
||||
_checkedOutTexturePool.erase(coTexture);
|
||||
_iNumTextureBytesCheckedOut -= pTexture->GetWidth() * pTexture->GetHeight() * 4;
|
||||
}
|
||||
|
||||
// Don't cache too many unused textures.
|
||||
int iWidthLog, iHeightLog;
|
||||
iWidthLog = SkyGetLogBaseTwo(pTexture->GetWidth());
|
||||
iHeightLog = SkyGetLogBaseTwo(pTexture->GetHeight());
|
||||
if (_iAvailableSizeCounts[iWidthLog][iHeightLog] >= SKYDYNTEXTURE_TEXCACHE_LIMIT)
|
||||
{
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesUsed -= pTexture->GetWidth() * pTexture->GetHeight() * 4;
|
||||
printf("%dx%d texture DESTROYED.\n\t Total memory used: %d bytes.\n",
|
||||
pTexture->GetWidth(), pTexture->GetHeight(), _iNumTextureBytesUsed);
|
||||
#endif
|
||||
|
||||
pTexture->Destroy();
|
||||
SAFE_DELETE(pTexture);
|
||||
return;
|
||||
}
|
||||
|
||||
// now check the texture into the available pool.
|
||||
// find the width subset:
|
||||
TextureSet::iterator subset = _availableTexturePool.find(pTexture->GetWidth());
|
||||
if (subset != _availableTexturePool.end())
|
||||
{ // the subset exists. Add the texture to it
|
||||
(*subset).second->insert(TextureSubset::value_type(pTexture->GetHeight(), pTexture));
|
||||
_iNumTextureBytesCheckedIn += pTexture->GetWidth() * pTexture->GetHeight() * 4;
|
||||
|
||||
_iAvailableSizeCounts[iWidthLog][iHeightLog]++;
|
||||
}
|
||||
else
|
||||
{ // subset not found. Create it.
|
||||
TextureSubset *pSubset = new TextureSubset;
|
||||
// insert the texture.
|
||||
pSubset->insert(TextureSubset::value_type(pTexture->GetHeight(), pTexture));
|
||||
// insert the subset into the available pool
|
||||
_availableTexturePool.insert(TextureSet::value_type(pTexture->GetWidth(), pSubset));
|
||||
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
_iNumTextureBytesCheckedIn += pTexture->GetWidth() * pTexture->GetHeight() * 4;
|
||||
_iAvailableSizeCounts[iWidthLog][iHeightLog]++;
|
||||
#endif
|
||||
}
|
||||
|
||||
pTexture = NULL;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyDynamicTextureManager::CreateDynamicTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyDynamicTextureManager::CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight)
|
||||
* @brief Allocate a new dynamic texture object of the given resolution.
|
||||
*
|
||||
* This method is used by CheckOutTexture() when it can't find an available texture of
|
||||
* the requested resolution. It can also be called externally, but will result in an
|
||||
* unmanaged texture unless the new texture is subsequently checked in using CheckInTexture().
|
||||
*/
|
||||
SkyTexture* SkyDynamicTextureManager::CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight)
|
||||
{
|
||||
unsigned int iID;
|
||||
glGenTextures(1, &iID);
|
||||
SkyTexture *pNewTexture = new SkyTexture(iWidth, iHeight, iID);
|
||||
glBindTexture(GL_TEXTURE_2D, pNewTexture->GetID());
|
||||
// set default filtering.
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
// create an empty buffer
|
||||
unsigned char *pData = new unsigned char[iWidth * iHeight * 4];
|
||||
|
||||
// allocate the texture
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, iWidth, iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData );
|
||||
|
||||
delete [] pData;
|
||||
|
||||
// update the used texture bytes...
|
||||
_iNumTextureBytesUsed += iWidth * iHeight * 4;
|
||||
#if SKYDYNTEXTURE_VERBOSE
|
||||
printf("New %dx%d texture created.\n\t Total memory used: %d bytes\n", iWidth, iHeight, _iNumTextureBytesUsed);
|
||||
printf("\tTotal memory checked in: %d\n", _iNumTextureBytesCheckedIn);
|
||||
printf("\tTotal memory checked out: %d\n", _iNumTextureBytesCheckedOut);
|
||||
#endif
|
||||
|
||||
return pNewTexture;
|
||||
}
|
||||
80
simgear/scene/sky/clouds3d/SkyDynamicTextureManager.hpp
Normal file
80
simgear/scene/sky/clouds3d/SkyDynamicTextureManager.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyDynamicTextureManager.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyDynamicTextureManager.hpp
|
||||
*
|
||||
* Interface definition of a repository for check out and check in of dynamic textures.
|
||||
*/
|
||||
#ifndef __SKYDYNAMICTEXTUREMANAGER_HPP__
|
||||
#define __SKYDYNAMICTEXTUREMANAGER_HPP__
|
||||
|
||||
// warning for truncation of template name for browse info
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <map>
|
||||
#include <GL/glut.h>
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkySingleton.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SkyTexture;
|
||||
class SkyDynamicTextureManager;
|
||||
|
||||
//! Dynamic Texture Manager Singleton declaration.
|
||||
/*! The DynamicTextureManager must be created by calling DynamicTextureManager::Instantiate(). */
|
||||
typedef SkySingleton<SkyDynamicTextureManager> DynamicTextureManager;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyDynamicTextureManager
|
||||
* @brief A repository that allows check-out and check-in from a pool of dynamic textures.
|
||||
*
|
||||
* When an object needs a dynamic texture, it checks it out using CheckOutTexture(), passing
|
||||
* the resolution of the texture it needs. When the object is done with the texture, it
|
||||
* calls CheckInTexture(). New dynamic textures can be allocated by calling CreateDynamicTexture,
|
||||
* but these textures will be unmanaged.
|
||||
*/
|
||||
class SkyDynamicTextureManager
|
||||
{
|
||||
public:
|
||||
SkyTexture* CheckOutTexture(unsigned int iWidth, unsigned int iHeight);
|
||||
void CheckInTexture(SkyTexture* pTexture);
|
||||
|
||||
SkyTexture* CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight);
|
||||
|
||||
protected: // methods
|
||||
SkyDynamicTextureManager(); // these are protected because it is a singleton.
|
||||
~SkyDynamicTextureManager();
|
||||
|
||||
protected: // datatypes
|
||||
typedef multimap<unsigned int, SkyTexture*> TextureSubset;
|
||||
typedef multimap<unsigned int, TextureSubset*> TextureSet;
|
||||
|
||||
protected: // data
|
||||
TextureSet _availableTexturePool;
|
||||
TextureSubset _checkedOutTexturePool;
|
||||
|
||||
unsigned int _iAvailableSizeCounts[11][11];
|
||||
|
||||
unsigned int _iNumTextureBytesUsed;
|
||||
unsigned int _iNumTextureBytesCheckedOut;
|
||||
unsigned int _iNumTextureBytesCheckedIn;
|
||||
};
|
||||
|
||||
#endif //__SKYDYNAMICTEXTUREMANAGER_HPP__
|
||||
231
simgear/scene/sky/clouds3d/SkyLight.cpp
Normal file
231
simgear/scene/sky/clouds3d/SkyLight.cpp
Normal 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;
|
||||
}
|
||||
97
simgear/scene/sky/clouds3d/SkyLight.hpp
Normal file
97
simgear/scene/sky/clouds3d/SkyLight.hpp
Normal file
@@ -0,0 +1,97 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyLight.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
/**
|
||||
* @file SkyLight.hpp
|
||||
*
|
||||
* Definition of a class that maintains the state and operation of a light.
|
||||
*/
|
||||
#ifndef __SKYLIGHT_HPP__
|
||||
#define __SKYLIGHT_HPP__
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include "vec4f.hpp"
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
class SkyMaterial;
|
||||
|
||||
class SkyLight
|
||||
{
|
||||
public: // types
|
||||
enum SkyLightType
|
||||
{
|
||||
SKY_LIGHT_POINT,
|
||||
SKY_LIGHT_DIRECTIONAL,
|
||||
SKY_LIGHT_SPOT,
|
||||
SKY_LIGHT_NUM_TYPES
|
||||
};
|
||||
|
||||
public: // methods
|
||||
SkyLight(SkyLightType eType);
|
||||
virtual ~SkyLight();
|
||||
|
||||
// for visualization of light positions / directions.
|
||||
void Display() const;
|
||||
|
||||
bool GetEnabled() const { return _bEnabled; }
|
||||
SkyLightType GetType() const { return _eType; }
|
||||
const float* GetPosition() const { return _vecPosition; }
|
||||
const float* GetDirection() const { return _vecDirection; }
|
||||
const float* GetDiffuse() const { return _vecDiffuse; }
|
||||
const float* GetAmbient() const { return _vecAmbient; }
|
||||
const float* GetSpecular() const { return _vecSpecular; }
|
||||
const float* GetAttenuation() const { return _vecAttenuation; }
|
||||
float GetSpotExponent() const { return _rSpotExponent; }
|
||||
float GetSpotCutoff() const { return _rSpotCutoff; }
|
||||
|
||||
void Enable(bool bEnable) { _bEnabled = bEnable; _bDirty = true; }
|
||||
void SetType(const SkyLightType& t) { _eType = t; _bDirty = true; }
|
||||
void SetPosition(const float pos[3])
|
||||
{ _vecPosition.Set(pos[0], pos[1], pos[2], (_eType != SKY_LIGHT_DIRECTIONAL)); _bDirty = true; }
|
||||
|
||||
void SetDirection(const float dir[3]) { _vecDirection.Set(dir[0], dir[1], dir[2], 0); _bDirty = true; }
|
||||
void SetDiffuse(const float color[4]) { _vecDiffuse.Set(color); _bDirty = true; }
|
||||
void SetAmbient(const float color[4]) { _vecAmbient.Set(color); _bDirty = true; }
|
||||
void SetSpecular(const float color[4]){ _vecSpecular.Set(color); _bDirty = true; }
|
||||
void SetAttenuation(float rConstant, float rLinear, float rQuadratic)
|
||||
{ _vecAttenuation.Set(rConstant, rLinear, rQuadratic); _bDirty = true; }
|
||||
|
||||
void SetSpotExponent(float rExp) { _rSpotExponent = rExp; _bDirty = true; }
|
||||
void SetSpotCutoff(float rCutoff) { _rSpotCutoff = rCutoff; _bDirty = true; }
|
||||
|
||||
SKYRESULT Activate(int iLightID);
|
||||
|
||||
protected: // data
|
||||
bool _bEnabled;
|
||||
bool _bDirty;
|
||||
|
||||
int _iLastGLID;
|
||||
|
||||
SkyLightType _eType;
|
||||
|
||||
Vec4f _vecPosition;
|
||||
Vec4f _vecDirection;
|
||||
Vec4f _vecDiffuse;
|
||||
Vec4f _vecAmbient;
|
||||
Vec4f _vecSpecular;
|
||||
Vec3f _vecAttenuation; // constant, linear, and quadratic attenuation factors.
|
||||
float _rSpotExponent;
|
||||
float _rSpotCutoff;
|
||||
|
||||
static SkyMaterial *s_pMaterial; // used for rendering the lights during debugging
|
||||
};
|
||||
|
||||
#endif //__SKYLIGHT_HPP__
|
||||
445
simgear/scene/sky/clouds3d/SkyMaterial.cpp
Normal file
445
simgear/scene/sky/clouds3d/SkyMaterial.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
269
simgear/scene/sky/clouds3d/SkyMaterial.hpp
Normal file
269
simgear/scene/sky/clouds3d/SkyMaterial.hpp
Normal 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__
|
||||
322
simgear/scene/sky/clouds3d/SkyMinMaxBox.cpp
Normal file
322
simgear/scene/sky/clouds3d/SkyMinMaxBox.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyMinMaxBox.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyMinMaxBox.cpp
|
||||
*
|
||||
* Implementation of a bounding box class. Modified from Wes Hunt's BoundingBox.
|
||||
*/
|
||||
#include "SkyMinMaxBox.hpp"
|
||||
#include "camutils.hpp"
|
||||
#include <GL/glut.h>
|
||||
#include <float.h>
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::SkyMinMaxBox
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::SkyMinMaxBox()
|
||||
* @brief Constructor
|
||||
*/
|
||||
SkyMinMaxBox::SkyMinMaxBox()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::Clear
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::Clear()
|
||||
* @brief Reset the min and max to floating point extremes.
|
||||
*
|
||||
*/
|
||||
void SkyMinMaxBox::Clear()
|
||||
{
|
||||
_min.x = FLT_MAX;
|
||||
_min.y = FLT_MAX;
|
||||
_min.z = FLT_MAX;
|
||||
_max.x = -FLT_MAX;
|
||||
_max.y = -FLT_MAX;
|
||||
_max.z = -FLT_MAX;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::PointInBBox
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::PointInBBox( const Vec3f &pt ) const
|
||||
* @brief Queries pt to see if it is inside the SkyMinMaxBox.
|
||||
*
|
||||
*/
|
||||
bool SkyMinMaxBox::PointInBBox( const Vec3f &pt ) const
|
||||
{
|
||||
if( (pt.x >= _min.x) && ( pt.x <= _max.x ) )
|
||||
{
|
||||
if( (pt.y >= _min.y) && ( pt.y <= _max.y ) )
|
||||
{
|
||||
if( (pt.z >= _min.z) && ( pt.z <= _max.z ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::AddPoint
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::AddPoint( float x , float y , float z )
|
||||
* @brief Adds a point and adjusts bounds if necessary.
|
||||
*/
|
||||
void SkyMinMaxBox::AddPoint( float x , float y , float z )
|
||||
{
|
||||
if( x > _max.x )
|
||||
_max.x = x;
|
||||
if( x < _min.x )
|
||||
_min.x = x;
|
||||
|
||||
if( y > _max.y )
|
||||
_max.y = y;
|
||||
if( y < _min.y )
|
||||
_min.y = y;
|
||||
|
||||
if( z > _max.z )
|
||||
_max.z = z;
|
||||
if( z < _min.z )
|
||||
_min.z = z;
|
||||
|
||||
// update the center and radius
|
||||
_UpdateSphere();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::AddPoint
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::AddPoint( const Vec3f &pt )
|
||||
* @brief Adds a point and adjusts bounds if necessary.
|
||||
*/
|
||||
void SkyMinMaxBox::AddPoint( const Vec3f &pt )
|
||||
{
|
||||
if( pt.x > _max.x )
|
||||
_max.x = pt.x;
|
||||
if( pt.x < _min.x )
|
||||
_min.x = pt.x;
|
||||
|
||||
if( pt.y > _max.y )
|
||||
_max.y = pt.y;
|
||||
if( pt.y < _min.y )
|
||||
_min.y = pt.y;
|
||||
|
||||
if( pt.z > _max.z )
|
||||
_max.z = pt.z;
|
||||
if( pt.z < _min.z )
|
||||
_min.z = pt.z;
|
||||
|
||||
// update the center and radius
|
||||
_UpdateSphere();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::ViewFrustumCull
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::ViewFrustumCull( const Camera &cam, const Mat44f &mat )
|
||||
* @brief Returns true if bounding volume culled against cam.
|
||||
*
|
||||
* This function must transform the object space min and max then adjust the new
|
||||
* min and max box by expanding it. Each of the 8 points must be tested. This
|
||||
* is faster then doing an xform of all the geometry points and finding a tight
|
||||
* fitting min max box, however this will be enlarged.
|
||||
*/
|
||||
bool SkyMinMaxBox::ViewFrustumCull( const Camera &cam, const Mat44f &mat )
|
||||
{
|
||||
SkyMinMaxBox xBV; // Xformed Bounding Volume
|
||||
Vec3f xMin = mat * _min; // Xformed _min
|
||||
Vec3f xMax = mat * _max; // Xformed _max
|
||||
Vec3f offset = _max - _min; // Offset for sides of MinMaxBox
|
||||
Vec3f tmp;
|
||||
|
||||
xBV.Clear(); // Clear the values first
|
||||
|
||||
// First find the new minimum x,y,z
|
||||
// Find min + x
|
||||
tmp.Set(mat.M[0], mat.M[4], mat.M[8]);
|
||||
tmp *= offset.x;
|
||||
tmp += xMin;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Find min + y
|
||||
tmp.Set(mat.M[1], mat.M[5], mat.M[9]);
|
||||
tmp *= offset.y;
|
||||
tmp += xMin;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Find min + z
|
||||
tmp.Set(mat.M[3], mat.M[6], mat.M[10]);
|
||||
tmp *= offset.z;
|
||||
tmp += xMin;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Second find the new maximum x,y,z
|
||||
// Find max - x
|
||||
tmp.Set(mat.M[0], mat.M[4], mat.M[8]);
|
||||
tmp *= -offset.x;
|
||||
tmp += xMax;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Find max - y
|
||||
tmp.Set(mat.M[1], mat.M[5], mat.M[9]);
|
||||
tmp *= -offset.y;
|
||||
tmp += xMax;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Find max - z
|
||||
tmp.Set(mat.M[3], mat.M[6], mat.M[10]);
|
||||
tmp *= -offset.z;
|
||||
tmp += xMax;
|
||||
xBV.AddPoint(tmp);
|
||||
|
||||
// Use the camera utility function that already exists for minmax boxes
|
||||
return VFC(&cam, xBV.GetMin(), xBV.GetMax());
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::Transform
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::Transform(const Mat44f& mat)
|
||||
* @brief @todo <WRITE BRIEF SkyMinMaxBox::Transform DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyMinMaxBox::Transform FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyMinMaxBox::Transform(const Mat44f& mat)
|
||||
{
|
||||
Vec3f verts[8];
|
||||
_CalcVerts(verts);
|
||||
Clear();
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
AddPoint(mat * verts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::_UpdateSphere
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::_UpdateSphere()
|
||||
* @brief Updates the bounding sphere based on min and max.
|
||||
*/
|
||||
void SkyMinMaxBox::_UpdateSphere()
|
||||
{
|
||||
_vecCenter = _min;
|
||||
_vecCenter += _max;
|
||||
_vecCenter *= 0.5f;
|
||||
|
||||
Vec3f rad = _max;
|
||||
rad -= _vecCenter;
|
||||
_rRadius = rad.Length();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::Display() const
|
||||
* @brief @todo <WRITE BRIEF SkyMinMaxBox::Display DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyMinMaxBox::Display FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyMinMaxBox::Display() const
|
||||
{
|
||||
Vec3f V[8];
|
||||
_CalcVerts(V);
|
||||
|
||||
glPushAttrib(GL_LINE_BIT);
|
||||
glLineWidth(1.0);
|
||||
|
||||
glBegin(GL_LINE_LOOP); // TOP FACE
|
||||
glVertex3fv(V[4]); glVertex3fv(V[5]); glVertex3fv(V[1]); glVertex3fv(V[0]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // BOTTOM FACE
|
||||
glVertex3fv(V[3]); glVertex3fv(V[2]); glVertex3fv(V[6]); glVertex3fv(V[7]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // LEFT FACE
|
||||
glVertex3fv(V[1]); glVertex3fv(V[5]); glVertex3fv(V[6]); glVertex3fv(V[2]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // RIGHT FACE
|
||||
glVertex3fv(V[0]); glVertex3fv(V[3]); glVertex3fv(V[7]); glVertex3fv(V[4]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // NEAR FACE
|
||||
glVertex3fv(V[1]); glVertex3fv(V[2]); glVertex3fv(V[3]); glVertex3fv(V[0]);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_LOOP); // FAR FACE
|
||||
glVertex3fv(V[4]); glVertex3fv(V[7]); glVertex3fv(V[6]); glVertex3fv(V[5]);
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Calculates the eight corner vertices of the MinMaxBox.
|
||||
// V must be prealloced.
|
||||
// 5---4
|
||||
// / /|
|
||||
// 1---0 | VERTS : 0=RTN,1=LTN,2=LBN,3=RBN,4=RTF,5=LTF,6=LBF,7=RBF
|
||||
// | | 7 (L,R, B,T, N,F) = (Left,Right, Bottom,Top, Near,Far)
|
||||
// | |/
|
||||
// 2---3
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyMinMaxBox::_CalcVerts
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyMinMaxBox::_CalcVerts(Vec3f pVerts[8]) const
|
||||
* @brief @todo <WRITE BRIEF SkyMinMaxBox::_CalcVerts DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyMinMaxBox::_CalcVerts FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
void SkyMinMaxBox::_CalcVerts(Vec3f pVerts[8]) const
|
||||
{
|
||||
pVerts[0].Set(_max); pVerts[4].Set(_max.x, _max.y, _min.z);
|
||||
pVerts[1].Set(_min.x, _max.y, _max.z); pVerts[5].Set(_min.x, _max.y, _min.z);
|
||||
pVerts[2].Set(_min.x, _min.y, _max.z); pVerts[6].Set(_min);
|
||||
pVerts[3].Set(_max.x, _min.y, _max.z); pVerts[7].Set(_max.x, _min.y, _min.z);
|
||||
}
|
||||
85
simgear/scene/sky/clouds3d/SkyMinMaxBox.hpp
Normal file
85
simgear/scene/sky/clouds3d/SkyMinMaxBox.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyMinMaxBox.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyMinMaxBox.hpp
|
||||
*
|
||||
* Interface definition for a min-max bounding box class for bounding volume hierarchies.
|
||||
*/
|
||||
#ifndef __SKYMINMAXBOX_HPP__
|
||||
#define __SKYMINMAXBOX_HPP__
|
||||
|
||||
#include "SkyBoundingVolume.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyMinMaxBox
|
||||
* @brief An AABB class that can be used in bounding volume hierarchies.
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyMinMaxBox : public SkyBoundingVolume
|
||||
{
|
||||
public:
|
||||
SkyMinMaxBox();
|
||||
//! Destructor
|
||||
virtual ~SkyMinMaxBox() {}
|
||||
|
||||
void AddPoint( const Vec3f &pt );
|
||||
void AddPoint( float x , float y , float z );
|
||||
|
||||
//! Expand this box to contain @a box.
|
||||
void Union(const SkyMinMaxBox& box) { AddPoint(box.GetMin()); AddPoint(box.GetMax()); }
|
||||
|
||||
//! Returns the minimum corner of the bounding box.
|
||||
const Vec3f &GetMin() const { return _min; }
|
||||
//! Returns the maximum corner of the bounding box.
|
||||
const Vec3f &GetMax() const { return _max; }
|
||||
|
||||
//! Sets the minimum corner of the bounding box.
|
||||
void SetMin(const Vec3f &min) { _min = min; _UpdateSphere(); }
|
||||
//! Sets the maximum corner of the bounding box.
|
||||
void SetMax(const Vec3f &max) { _max = max; _UpdateSphere(); }
|
||||
|
||||
//! Returns the X width of the bounding box.
|
||||
float GetWidthInX() const { return _max.x - _min.x;}
|
||||
//! Returns the Y width of the bounding box.
|
||||
float GetWidthInY() const { return _max.y - _min.y;}
|
||||
//! Returns the Z width of the bounding box.
|
||||
float GetWidthInZ() const { return _max.z - _min.z;}
|
||||
|
||||
bool PointInBBox( const Vec3f &pt ) const;
|
||||
|
||||
bool ViewFrustumCull( const Camera &cam, const Mat44f &mat );
|
||||
|
||||
void Transform(const Mat44f& mat);
|
||||
|
||||
// Reset the bounding box
|
||||
void Clear();
|
||||
|
||||
void Display() const;
|
||||
|
||||
protected:
|
||||
void _UpdateSphere();
|
||||
void _CalcVerts(Vec3f pVerts[8]) const;
|
||||
|
||||
private:
|
||||
Vec3f _min; // Original object space BV
|
||||
Vec3f _max;
|
||||
};
|
||||
|
||||
#endif //__SKYMINMAXBOX_HPP__
|
||||
116
simgear/scene/sky/clouds3d/SkyRenderable.hpp
Normal file
116
simgear/scene/sky/clouds3d/SkyRenderable.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderable.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderable.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// Sky : Copyright 2002 Mark J. Harris and Andrew Zaferakis
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @file SkyRenderable.hpp
|
||||
*
|
||||
* Abstract base class definition for SkyRenderable, a renderable object class.
|
||||
*/
|
||||
#ifndef __SKYRENDERABLE_HPP__
|
||||
#define __SKYRENDERABLE_HPP__
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class SkyMinMaxBox;
|
||||
class SkyRenderableInstance;
|
||||
class Camera;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderable
|
||||
* @brief An base class for renderable objects.
|
||||
*
|
||||
* Each SkyRenderable object should know how to Display itself, however some
|
||||
* objects may not have a bounding volume that is useful (skybox, etc.)
|
||||
*/
|
||||
class SkyRenderable
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
SkyRenderable() {}
|
||||
//! Destructor
|
||||
virtual ~SkyRenderable() { }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SetName
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SetName(const std::string &name)
|
||||
* @brief Set a name for this renderable.
|
||||
*/
|
||||
void SetName(const std::string &name) { _name = name; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : GetName
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn GetName() const
|
||||
* @brief Get the name of this renderable.
|
||||
*/
|
||||
const std::string& GetName() const { return _name; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Update
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Update(const Camera &cam, SkyRenderableInstance *pInstance)
|
||||
* @brief Update the state of the renderable.
|
||||
*
|
||||
* This method is optional, as some renderables will need periodic updates
|
||||
* (i.e. for animation) and others will not.
|
||||
*/
|
||||
virtual SKYRESULT Update(const Camera &cam, SkyRenderableInstance *pInstance = NULL)
|
||||
{ return SKYRESULT_OK; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Display(const Camera &cam, SkyRenderableInstance *pInstance)
|
||||
* @brief Display the object.
|
||||
*/
|
||||
virtual SKYRESULT Display(const Camera &cam, SkyRenderableInstance *pInstance = NULL) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : CopyBoundingVolume
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn CopyBoundingVolume() const
|
||||
* @brief Create a copy of the object's bounding volume, useful for collision, VFC, etc.
|
||||
*/
|
||||
virtual SkyMinMaxBox* CopyBoundingVolume() const = 0;// { return 0; }
|
||||
|
||||
protected:
|
||||
std::string _name; // the name of this renderable.
|
||||
};
|
||||
|
||||
#endif //__SKYRENDERABLE_HPP__
|
||||
202
simgear/scene/sky/clouds3d/SkyRenderableInstance.hpp
Normal file
202
simgear/scene/sky/clouds3d/SkyRenderableInstance.hpp
Normal file
@@ -0,0 +1,202 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstance.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyRenderableInstance.hpp
|
||||
*
|
||||
* Interface definition for SkyRenderableInstance, an instance of a renderable object.
|
||||
*/
|
||||
#ifndef __SKYRENDERABLEINSTANCE_HPP__
|
||||
#define __SKYRENDERABLEINSTANCE_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include "mat33.hpp"
|
||||
#include "mat44.hpp"
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class Camera;
|
||||
class SkyMinMaxBox;
|
||||
|
||||
// forward so we can make the following typedefs easily visible in the header.
|
||||
// rather than buried under the class definition.
|
||||
class SkyRenderableInstance;
|
||||
|
||||
//! A dynamic array of SkyRenderableInstance pointers.
|
||||
typedef std::vector<SkyRenderableInstance*> InstanceArray;
|
||||
//! An instance array iterator.
|
||||
typedef InstanceArray::iterator InstanceIterator;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderableInstance
|
||||
* @brief An instance of a SkyRenderable object.
|
||||
*
|
||||
* An instance contains a pointer to a SkyRenderable object. The
|
||||
* instance contains attributes such as position, orientation,
|
||||
* scale, etc. that vary between instances.
|
||||
*/
|
||||
class SkyRenderableInstance
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
SkyRenderableInstance()
|
||||
: _bCulled(false), _bAlive(true), _vecPosition(0, 0, 0), _rScale(1), _rSquareSortDistance(0)
|
||||
{
|
||||
_matRotation.Identity(); _matInvRotation.Identity();
|
||||
}
|
||||
|
||||
//! Constructor.
|
||||
SkyRenderableInstance(const Vec3f &position,
|
||||
const Mat33f &rotation,
|
||||
const float scale)
|
||||
: _bCulled(false), _bAlive(true), _vecPosition(position),
|
||||
_matRotation(rotation), _rScale(scale), _rSquareSortDistance(0)
|
||||
{
|
||||
_matInvRotation = _matRotation;
|
||||
_matInvRotation.Transpose();
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
virtual ~SkyRenderableInstance() {}
|
||||
|
||||
// Setters / Getters
|
||||
//! Set the world space position of the instance.
|
||||
virtual void SetPosition(const Vec3f &position) { _vecPosition = position; }
|
||||
//! Set the world space rotation of the instance.
|
||||
virtual void SetRotation(const Mat33f &rotation) { _matRotation = rotation;
|
||||
_matInvRotation = rotation;
|
||||
_matInvRotation.Transpose(); }
|
||||
//! Set the world space scale of the instance.
|
||||
virtual void SetScale( const float &scale) { _rScale = scale; }
|
||||
|
||||
//! Returns the world space position of the instance.
|
||||
virtual const Vec3f& GetPosition() const { return _vecPosition; }
|
||||
//! Returns the world space rotation matrix of the instance.
|
||||
virtual const Mat33f& GetRotation() const { return _matRotation; }
|
||||
//! Returns the inverse of the world space rotation matrix of the instance.
|
||||
virtual const Mat33f& GetInverseRotation() const { return _matInvRotation; }
|
||||
//! Returns the world space scale of the instance.
|
||||
virtual float GetScale() const { return _rScale; }
|
||||
|
||||
//! Update the instance based on the given camera, @a cam.
|
||||
virtual SKYRESULT Update(const Camera &cam) { return SKYRESULT_OK; }
|
||||
//! Render the instance.
|
||||
virtual SKYRESULT Display() { return SKYRESULT_OK; }
|
||||
|
||||
//! Returns the transform matrix from model space to world space.
|
||||
inline virtual void GetModelToWorldTransform(Mat44f &mat) const;
|
||||
|
||||
//! Returns the transform matrix from world space to model space.
|
||||
|
||||
inline virtual void GetWorldToModelTransform(Mat44f &mat) const;
|
||||
|
||||
//! Returns the object-space bounding volume for this instance, or NULL if none is available.
|
||||
virtual SkyMinMaxBox* GetBoundingVolume() const { return NULL; }
|
||||
|
||||
//! Returns true if and only if the bounding volume of this instance lies entirely outside @a cam.
|
||||
virtual bool ViewFrustumCull(const Camera &cam) { return false; }
|
||||
//! Returns true if the instance was culled.
|
||||
virtual bool IsCulled() { return _bCulled; }
|
||||
//! Sets the culled state of the instance.
|
||||
virtual void SetCulled(bool bCulled) { _bCulled = bCulled; }
|
||||
|
||||
//! Returns true if the instance is currently active.
|
||||
virtual bool IsAlive() { return _bAlive; }
|
||||
//! Activates or deactivates the instance.
|
||||
virtual void SetIsAlive(bool bAlive) { _bAlive = bAlive; }
|
||||
|
||||
//! Sets the distance of this object from the sort position. Used to sort instances.
|
||||
virtual void SetSquareSortDistance(float rSqrDist) { _rSquareSortDistance = rSqrDist; }
|
||||
//! Returns the distance of this object from the sort position. (Set with SetSquareSortDistance())
|
||||
virtual float GetSquareSortDistace() const { return _rSquareSortDistance; }
|
||||
|
||||
//! This operator is used to sort instance arrays.
|
||||
bool operator<(const SkyRenderableInstance& instance) const
|
||||
{
|
||||
return (_rSquareSortDistance > instance._rSquareSortDistance);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _bCulled; // Culled flag
|
||||
bool _bAlive; // Alive object flag
|
||||
|
||||
Vec3f _vecPosition; // Position
|
||||
Mat33f _matRotation; // Rotation
|
||||
Mat33f _matInvRotation; // inverse rotation
|
||||
float _rScale; // Scale
|
||||
|
||||
// for sorting particles during shading
|
||||
float _rSquareSortDistance;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstance::GetModelToWorldTransform
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstance::GetModelToWorldTransform(Mat44f &mat) const
|
||||
* @brief Returns the 4x4 transformation matrix from world to model space.
|
||||
*/
|
||||
inline void SkyRenderableInstance::GetModelToWorldTransform(Mat44f &mat) const
|
||||
{
|
||||
mat[0] = _matRotation.M[0]; mat[4] = _matRotation.M[3];
|
||||
mat[8] = _matRotation.M[6]; mat[12] = 0;
|
||||
mat[1] = _matRotation.M[1]; mat[5] = _matRotation.M[4];
|
||||
mat[9] = _matRotation.M[7]; mat[13] = 0;
|
||||
mat[2] = _matRotation.M[2]; mat[6] = _matRotation.M[5];
|
||||
mat[10] = _matRotation.M[8]; mat[14] = 0;
|
||||
mat[3] = 0; mat[7] = 0; mat[11] = 0; mat[15] = 0;
|
||||
|
||||
// Scale the matrix (we don't want to scale translation or mat[15] which is 1)
|
||||
if (_rScale != 1)
|
||||
mat *= _rScale;
|
||||
|
||||
// Set the translation and w coordinate after the potential scaling
|
||||
mat[12] = _vecPosition.x; mat[13] = _vecPosition.y; mat[14] = _vecPosition.z;
|
||||
mat[15] = 1;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Mat44f& SkyRenderableInstance::GetWorldToModelTransform
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstance::GetWorldToModelTransform(Mat44f &mat) const
|
||||
* @brief Returns the 4x4 transformation matrix from world to model space.
|
||||
*/
|
||||
inline void SkyRenderableInstance::GetWorldToModelTransform(Mat44f &mat) const
|
||||
{
|
||||
mat[0] = _matRotation.M[0]; mat[4] = _matRotation.M[1];
|
||||
mat[8] = _matRotation.M[2]; mat[12] = 0;
|
||||
mat[1] = _matRotation.M[3]; mat[5] = _matRotation.M[4];
|
||||
mat[9] = _matRotation.M[5]; mat[13] = 0;
|
||||
mat[2] = _matRotation.M[6]; mat[6] = _matRotation.M[7];
|
||||
mat[10] = _matRotation.M[8]; mat[14] = 0;
|
||||
mat[3] = 0; mat[7] = 0; mat[11] = 0; mat[15] = 0;
|
||||
|
||||
// Scale the matrix (we don't want to scale translation or mat[15] which is 1)
|
||||
if (_rScale != 1)
|
||||
mat *= (1 / _rScale);
|
||||
|
||||
// Set the translation and w coordinate after the potential scaling
|
||||
mat[12] = -_vecPosition.x; mat[13] = -_vecPosition.y; mat[14] = -_vecPosition.z;
|
||||
mat[15] = 1;
|
||||
}
|
||||
|
||||
#endif //__SKYRENDERABLEINSTANCE_HPP__
|
||||
708
simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.cpp
Normal file
708
simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.cpp
Normal 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++;
|
||||
}
|
||||
273
simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.hpp
Normal file
273
simgear/scene/sky/clouds3d/SkyRenderableInstanceCloud.hpp
Normal file
@@ -0,0 +1,273 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceCloud.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
/**
|
||||
* @file SkyRenderableInstanceCloud.hpp
|
||||
*
|
||||
* Interface for class SkyRenderableInstanceCloud, an instance of a SkyCloud object.
|
||||
*/
|
||||
#ifndef __SKYRENDERABLEINSTANCECLOUD_HPP__
|
||||
#define __SKYRENDERABLEINSTANCECLOUD_HPP__
|
||||
|
||||
class SkyCloud;
|
||||
class SkyTexture;
|
||||
//class SkyOffScreenBuffer;
|
||||
|
||||
#include <vector>
|
||||
#include "camera.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
#include "SkyRenderableInstanceGeneric.hpp"
|
||||
#include "SkyCloud.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderableInstanceCloud
|
||||
* @brief An instance of a cloud. Renders using an impostor.
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyRenderableInstanceCloud : public SkyRenderableInstance
|
||||
{
|
||||
public:
|
||||
SkyRenderableInstanceCloud( SkyCloud *pCloud, bool bUseOffScreenBuffer = false);
|
||||
SkyRenderableInstanceCloud( SkyCloud *pCloud,
|
||||
const Vec3f &position,
|
||||
const Mat33f &rotation,
|
||||
const float scale,
|
||||
bool bUseOffScreenBuffer = false);
|
||||
virtual ~SkyRenderableInstanceCloud();
|
||||
|
||||
// Setters / Getters
|
||||
//! Sets the identifier for this cloud (used by SkySceneManager.)
|
||||
void SetID(int id) { _iCloudID = id; }
|
||||
|
||||
virtual void SetPosition(const Vec3f &position);
|
||||
|
||||
virtual void SetRotation(const Mat33f &rotation);
|
||||
|
||||
virtual void SetScale(const float &scale);
|
||||
|
||||
//! Returns SkySceneManager's id for this cloud.
|
||||
int GetID() const { return _iCloudID; }
|
||||
//! Returns a pointer to the renderable that this instance represents.
|
||||
virtual SkyCloud* GetCloud() const { return _pCloud; }
|
||||
|
||||
//! Returns the world space bounding box of the cloud instance.
|
||||
const SkyMinMaxBox& GetWorldSpaceBounds() { return *_pWorldSpaceBV; }
|
||||
|
||||
//! Make this into a split impostor. Will be rendered as two halves, around the split point.
|
||||
void SetSplit(bool bSplit) { _bSplit = bSplit; }
|
||||
|
||||
//! Set the distance at which the cloud will be split (from the camera position).
|
||||
void SetSplitPoint(const Vec3f& vecSplit) { _vecSplit = vecSplit; }
|
||||
|
||||
//! Returns true if this is a split impostor (cloud contains objects)
|
||||
bool IsSplit() const { return _bSplit; }
|
||||
|
||||
//! Returns true if the camera is inside this clouds bounding volume.
|
||||
bool IsScreenImpostor() const { return _bScreenImpostor; }
|
||||
|
||||
virtual SKYRESULT Update(const Camera& cam);
|
||||
virtual SKYRESULT Display(bool bDisplayFrontOfSplit = false);
|
||||
SKYRESULT DisplayWithoutImpostor(const Camera& cam);
|
||||
|
||||
virtual bool ViewFrustumCull( const Camera &cam );
|
||||
|
||||
void ReleaseImpostorTextures();
|
||||
|
||||
|
||||
virtual SkyMinMaxBox* GetBoundingVolume() const { return _pWorldSpaceBV; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Determine if the current impostor image is valid for the given viewpoint
|
||||
//----------------------------------------------------------------------------
|
||||
bool IsImpostorValid(const Camera &cam);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Enable
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Enable(bool bEnable)
|
||||
* @brief Enable / Disable the use of impostor images (if disabled, displays geometry).
|
||||
*/
|
||||
void Enable(bool bEnable) { _bEnabled = bEnable; }
|
||||
|
||||
static void SetErrorToleranceAngle(float rDegrees);
|
||||
|
||||
protected: // methods
|
||||
void _Initialize();
|
||||
inline int _GetRequiredLogResolution(float rObjectDistance, float rObjectRadius, float rCamRadius);
|
||||
|
||||
inline void _UpdateWorldSpaceBounds();
|
||||
|
||||
protected: // data
|
||||
int _iCloudID; // used by the scene manager to identify clouds.
|
||||
|
||||
SkyCloud *_pCloud; // Pointer to the cloud object
|
||||
SkyMinMaxBox *_pWorldSpaceBV; // Pointer to bounding volume in object space
|
||||
|
||||
float _rRadius; // Radius of the impostor.
|
||||
bool _bScreenImpostor; // Is this a screen space or world space impostor?
|
||||
bool _bImageExists; // The impostor image exists and is ready to use.
|
||||
bool _bEnabled; // if disabled, draw geometry -- otherwise, draw impostor.
|
||||
bool _bUseOffScreenBuffer; // if enabled, uses off-screen rendering to create impostor images.
|
||||
|
||||
bool _bSplit; // true if the cloud contains other object instances.
|
||||
Vec3f _vecSplit; // the point about which this cloud is split.
|
||||
|
||||
Vec3f _vecNearPoint; // Nearest point on bounding sphere to viewpoint.
|
||||
Vec3f _vecFarPoint; // Farthest point on bounding sphere from viewpoint.
|
||||
|
||||
Camera _impostorCam; // camera used to generate this impostor
|
||||
|
||||
unsigned int _iLogResolution; // Log base 2 of current impostor image resolution.
|
||||
|
||||
SkyTexture *_pBackTexture; // Back texture for split clouds or main texture for unsplit.
|
||||
SkyTexture *_pFrontTexture; // Front texture for split clouds.
|
||||
|
||||
unsigned int _iCulledCount; // used to determine when to release textures
|
||||
|
||||
static unsigned int s_iCount; // keep track of number of impostors using the render buffer.
|
||||
//JW?? static SkyOffScreenBuffer* s_pRenderBuffer;
|
||||
static float s_rErrorToleranceAngle;
|
||||
static SkyMaterial *s_pMaterial; // shared material for cloud impostors.
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyContainerCloud
|
||||
* @brief A class used to organize the rendering order of cloud impostors and the objects in the clouds
|
||||
*
|
||||
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
|
||||
*/
|
||||
class SkyContainerCloud : public SkyRenderableInstance
|
||||
{
|
||||
public: // methods
|
||||
//! Constructor.
|
||||
SkyContainerCloud(SkyRenderableInstanceCloud *cloud) : SkyRenderableInstance(), pCloud(cloud) {}
|
||||
//! Destructor.
|
||||
~SkyContainerCloud()
|
||||
{ pCloud = NULL; containedOpaqueInstances.clear(); containedTransparentInstances.clear(); }
|
||||
|
||||
virtual SKYRESULT Display()
|
||||
{
|
||||
// display the back half of the split impostor.
|
||||
FAIL_RETURN_MSG(pCloud->Display(false),
|
||||
"SkySceneManager::Display(): cloud instance display failed.");
|
||||
|
||||
if (pCloud->IsSplit())
|
||||
{
|
||||
// display contained instances -- first opaque, then transparent.
|
||||
InstanceIterator ii;
|
||||
for (ii = containedOpaqueInstances.begin(); ii != containedOpaqueInstances.end(); ++ii)
|
||||
FAIL_RETURN((*ii)->Display());
|
||||
for (ii = containedTransparentInstances.begin(); ii != containedTransparentInstances.end(); ++ii)
|
||||
FAIL_RETURN((*ii)->Display());
|
||||
|
||||
// now display the front half of the split impostor.
|
||||
FAIL_RETURN_MSG(pCloud->Display(true),
|
||||
"SkySceneManager::Display(): cloud instance display failed.");
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
virtual const Vec3f& GetPosition() const { return pCloud->GetPosition(); }
|
||||
|
||||
public: //data -- here the data are public because the interface is minimal.
|
||||
SkyRenderableInstanceCloud *pCloud;
|
||||
|
||||
InstanceArray containedOpaqueInstances;
|
||||
InstanceArray containedTransparentInstances;
|
||||
|
||||
// This operator is used to sort ContainerCloud arrays.
|
||||
bool operator<(const SkyContainerCloud& container) const
|
||||
{
|
||||
return (*((SkyRenderableInstance*)pCloud) < *((SkyRenderableInstance*)container.pCloud));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : _GetRequiredLogResolution
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::_GetRequiredLogResolution(float rObjectDistance, float rObjectRadius, float rCamRadius)
|
||||
* @brief Returns the integer logarithm base two of the expected impostor resolution.
|
||||
*
|
||||
* Impostor resolution is based on object size, distance, and the FOV of the camera (stored as the
|
||||
* radius of a sphere centered at the camera position and passing through the corners of the
|
||||
* projection plane.
|
||||
*/
|
||||
inline int SkyRenderableInstanceCloud::_GetRequiredLogResolution(float rObjectDistance,
|
||||
float rObjectRadius,
|
||||
float rCamRadius)
|
||||
{
|
||||
int iScreenWidth, iScreenHeight;
|
||||
GraphicsContext::InstancePtr()->GetWindowSize(iScreenWidth, iScreenHeight);
|
||||
//cout << "SkyRes: w=" << iScreenWidth << "h=" << iScreenHeight << endl; char ff; cin >> ff;
|
||||
int iScreenResolution = (iScreenWidth > iScreenHeight) ? iScreenWidth : iScreenHeight;
|
||||
int iLogMinScreenResolution = (iScreenWidth > iScreenHeight) ? iScreenHeight : iScreenWidth;
|
||||
iLogMinScreenResolution = SkyGetLogBaseTwo(iLogMinScreenResolution) - 1;
|
||||
|
||||
int iRes = 2 * iScreenResolution * _pWorldSpaceBV->GetRadius() / rObjectDistance;
|
||||
int iLogResolution;
|
||||
|
||||
if (rObjectDistance - (0.5f * rObjectRadius) < rCamRadius)
|
||||
{
|
||||
iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 8);
|
||||
}
|
||||
else if (rObjectDistance - rObjectRadius < rCamRadius)
|
||||
{
|
||||
iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 4);
|
||||
}
|
||||
else if (iRes > iScreenResolution)
|
||||
{
|
||||
iLogResolution = SkyGetLogBaseTwo(iScreenResolution / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
iLogResolution = SkyGetLogBaseTwo(iRes);
|
||||
}
|
||||
|
||||
// if not rendering to an off screen buffer, make sure the resolution fits in the window!
|
||||
if (!_bUseOffScreenBuffer && (iLogMinScreenResolution < iLogResolution))
|
||||
iLogResolution = iLogMinScreenResolution;
|
||||
|
||||
return iLogResolution;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds()
|
||||
* @brief Updates the world space bounding box of the cloud.
|
||||
*/
|
||||
inline void SkyRenderableInstanceCloud::_UpdateWorldSpaceBounds()
|
||||
{
|
||||
SAFE_DELETE(_pWorldSpaceBV);
|
||||
_pWorldSpaceBV = _pCloud->CopyBoundingVolume();
|
||||
_vecPosition = _pCloud->CopyBoundingVolume()->GetCenter();
|
||||
}
|
||||
|
||||
#endif //__SKYRENDERABLEINSTANCECLOUD_HPP__
|
||||
76
simgear/scene/sky/clouds3d/SkyRenderableInstanceGeneric.hpp
Normal file
76
simgear/scene/sky/clouds3d/SkyRenderableInstanceGeneric.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceGeneric.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyRenderableInstanceGeneric.hpp
|
||||
*
|
||||
* Interface for a basic implementation of SkyRenderableInstance
|
||||
*/
|
||||
#ifndef __SKYRENDERABLEINSTANCEGENERIC_HPP__
|
||||
#define __SKYRENDERABLEINSTANCEGENERIC_HPP__
|
||||
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class SkyRenderable;
|
||||
class SkyMinMaxBox;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderableInstanceGeneric
|
||||
* @brief A generic renderable instance
|
||||
*
|
||||
* The SkyRenderableInstanceGeneric is a basic implementation of the base class.
|
||||
* For view frustum culling, the function ViewFrustumCull should be called once
|
||||
* per frame, at which point a flag is set if the object is culled or not. It
|
||||
* is possible that the object is then queried multiple times if it is culled or
|
||||
* not by various other objects before being displayed, that is why the flag is
|
||||
* stored.
|
||||
*/
|
||||
class SkyRenderableInstanceGeneric : public SkyRenderableInstance
|
||||
{
|
||||
public:
|
||||
SkyRenderableInstanceGeneric(SkyRenderable *pObject);
|
||||
SkyRenderableInstanceGeneric(SkyRenderable *pObject,
|
||||
const Vec3f &position,
|
||||
const Mat33f &rotation,
|
||||
const float scale);
|
||||
virtual ~SkyRenderableInstanceGeneric();
|
||||
|
||||
// Setters / Getters
|
||||
|
||||
virtual void SetRenderable(SkyRenderable *pRenderable );
|
||||
|
||||
//! Returns a pointer to the renderable that this instance represents.
|
||||
virtual SkyRenderable* GetRenderable() const { return _pObj; }
|
||||
|
||||
virtual SKYRESULT Display();
|
||||
|
||||
// Test / Set / Get
|
||||
virtual bool ViewFrustumCull( const Camera &cam );
|
||||
|
||||
|
||||
virtual SkyMinMaxBox* GetBoundingVolume() const { return _pBV; }
|
||||
|
||||
protected:
|
||||
|
||||
protected:
|
||||
SkyRenderable *_pObj; // Pointer to the renderable object
|
||||
SkyMinMaxBox *_pBV; // Pointer to bounding volume
|
||||
};
|
||||
|
||||
#endif //__SKYRENDERABLEINSTANCEGENERIC_HPP__
|
||||
178
simgear/scene/sky/clouds3d/SkyRenderableInstanceGroup.cpp
Normal file
178
simgear/scene/sky/clouds3d/SkyRenderableInstanceGroup.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceGroup.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyRenderableInstanceGroup.cpp
|
||||
*
|
||||
* Implementation of class SkyRenderableInstanceGroup, an instance that groups
|
||||
* other instances.
|
||||
*/
|
||||
|
||||
#include <GL/glut.h>
|
||||
#include "SkyRenderableInstanceGroup.hpp"
|
||||
#include "SkySceneManager.hpp"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::SkyRenderableInstanceGroup
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::SkyRenderableInstanceGroup()
|
||||
* @brief Constructor.
|
||||
*/
|
||||
SkyRenderableInstanceGroup::SkyRenderableInstanceGroup()
|
||||
: SkyRenderableInstance(),
|
||||
_pObjectSpaceBV(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup()
|
||||
* @brief Destructor.
|
||||
*/
|
||||
SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::Update
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::Update(const Camera &cam)
|
||||
* @brief Processes any per frame updates the instance requires.
|
||||
*
|
||||
* This method simply calls the SkyRenderableInstance::Update() method of each of
|
||||
* its sub-instances.
|
||||
*/
|
||||
SKYRESULT SkyRenderableInstanceGroup::Update(const Camera &cam)
|
||||
{
|
||||
InstanceIterator ii;
|
||||
for (ii = _opaqueSubInstances.begin(); ii != _opaqueSubInstances.end(); ++ii)
|
||||
{
|
||||
FAIL_RETURN((*ii)->Update(cam));
|
||||
}
|
||||
for (ii = _transparentSubInstances.begin(); ii != _transparentSubInstances.end(); ++ii)
|
||||
{
|
||||
FAIL_RETURN((*ii)->Update(cam));
|
||||
}
|
||||
|
||||
SkySceneManager::SortInstances(_transparentSubInstances, cam.Orig);
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::Display
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::Display()
|
||||
* @brief Displays all sub-instances of this instance.
|
||||
*
|
||||
* The object-to-world transform of this instance group will be applied to all sub-instances before
|
||||
* their own object-to-world transforms are applied.
|
||||
*/
|
||||
SKYRESULT SkyRenderableInstanceGroup::Display()
|
||||
{
|
||||
// Get and set the world space transformation
|
||||
Mat44f mat;
|
||||
GetModelToWorldTransform(mat);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glMultMatrixf(mat.M);
|
||||
|
||||
InstanceIterator ii;
|
||||
/***
|
||||
for (ii = _opaqueSubInstances.begin(); ii != _opaqueSubInstances.end(); ++ii)
|
||||
{
|
||||
FAIL_RETURN((*ii)->Display());
|
||||
}
|
||||
|
||||
for (ii = _transparentSubInstances.begin(); ii != _transparentSubInstances.end(); ++ii)
|
||||
{
|
||||
FAIL_RETURN((*ii)->Display());
|
||||
}
|
||||
***/
|
||||
_pObjectSpaceBV->Display();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::ViewFrustumCull
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::ViewFrustumCull(const Camera& cam)
|
||||
* @brief @todo <WRITE BRIEF SkyRenderableInstanceGroup::ViewFrustumCull DOCUMENTATION>
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyRenderableInstanceGroup::ViewFrustumCull FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
bool SkyRenderableInstanceGroup::ViewFrustumCull(const Camera& cam)
|
||||
{
|
||||
Mat44f xform;
|
||||
GetModelToWorldTransform(xform);
|
||||
_bCulled = (_pObjectSpaceBV == NULL) ? false : _pObjectSpaceBV->ViewFrustumCull(cam, xform);
|
||||
return _bCulled;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyRenderableInstanceGroup::AddSubInstance
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyRenderableInstanceGroup::AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent)
|
||||
* @brief Adds a sub-instance to the group.
|
||||
*/
|
||||
void SkyRenderableInstanceGroup::AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent)
|
||||
{
|
||||
if (!bTransparent)
|
||||
_opaqueSubInstances.push_back(pInstance);
|
||||
else
|
||||
_transparentSubInstances.push_back(pInstance);
|
||||
|
||||
// update the bounds...
|
||||
Mat44f xform;
|
||||
pInstance->GetModelToWorldTransform(xform);
|
||||
|
||||
SkyMinMaxBox *pBV = pInstance->GetBoundingVolume();
|
||||
if (pBV)
|
||||
{
|
||||
Vec3f min = pInstance->GetBoundingVolume()->GetMin();
|
||||
Vec3f max = pInstance->GetBoundingVolume()->GetMax();
|
||||
|
||||
if (!_pObjectSpaceBV)
|
||||
_pObjectSpaceBV = new SkyMinMaxBox;
|
||||
|
||||
_pObjectSpaceBV->AddPoint(xform * min);
|
||||
_pObjectSpaceBV->AddPoint(xform * max);
|
||||
}
|
||||
}
|
||||
63
simgear/scene/sky/clouds3d/SkyRenderableInstanceGroup.hpp
Normal file
63
simgear/scene/sky/clouds3d/SkyRenderableInstanceGroup.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyRenderableInstanceGroup.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyRenderableInstanceGroup.hpp
|
||||
*
|
||||
* Interface definition for class SkyRenderableInstanceGroup, an instance that groups
|
||||
* other instances.
|
||||
*/
|
||||
#ifndef __SKYRENDERABLEINSTANCEGROUP_HPP__
|
||||
#define __SKYRENDERABLEINSTANCEGROUP_HPP__
|
||||
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
#include "SkyMinMaxBox.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyRenderableInstanceGroup
|
||||
* @brief A renderable instance that groups other instances.
|
||||
*
|
||||
* This class provides a very basic way to implement static hierarchies of objects.
|
||||
* It is not meant to be a full scene graph --
|
||||
*/
|
||||
class SkyRenderableInstanceGroup : public SkyRenderableInstance
|
||||
{
|
||||
public:
|
||||
SkyRenderableInstanceGroup();
|
||||
virtual ~SkyRenderableInstanceGroup();
|
||||
|
||||
//! Update all sub-instances.
|
||||
virtual SKYRESULT Update(const Camera &cam);
|
||||
//! Render all sub-instances.
|
||||
virtual SKYRESULT Display();
|
||||
|
||||
//! Returns true if and only if the bounding volume of this instance lies entirely outside @a cam.
|
||||
virtual bool ViewFrustumCull(const Camera &cam);
|
||||
|
||||
//! Adds an instance to the group that this instance represents.
|
||||
void AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent);
|
||||
|
||||
protected:
|
||||
InstanceArray _opaqueSubInstances;
|
||||
InstanceArray _transparentSubInstances;
|
||||
|
||||
SkyMinMaxBox *_pObjectSpaceBV; // Pointer to bounding volume in object space
|
||||
};
|
||||
|
||||
|
||||
#endif //__SKYRENDERABLEINSTANCEGROUP_HPP__
|
||||
250
simgear/scene/sky/clouds3d/SkySceneLoader.cpp
Normal file
250
simgear/scene/sky/clouds3d/SkySceneLoader.cpp
Normal 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 () ;
|
||||
|
||||
}
|
||||
63
simgear/scene/sky/clouds3d/SkySceneLoader.hpp
Normal file
63
simgear/scene/sky/clouds3d/SkySceneLoader.hpp
Normal 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__
|
||||
922
simgear/scene/sky/clouds3d/SkySceneManager.cpp
Normal file
922
simgear/scene/sky/clouds3d/SkySceneManager.cpp
Normal 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;
|
||||
}
|
||||
188
simgear/scene/sky/clouds3d/SkySceneManager.hpp
Normal file
188
simgear/scene/sky/clouds3d/SkySceneManager.hpp
Normal file
@@ -0,0 +1,188 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkySceneManager.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkySceneManager.hpp
|
||||
*
|
||||
* The SkySceneManager class manages all of the renderable objects and
|
||||
* instances. This class maintains lists of each object and instance.
|
||||
* The scene manager decides what to display, it can make use of various
|
||||
* techniques such as view frustum culling, material grouping, etc.
|
||||
*/
|
||||
#ifndef __SKYSCENEMANAGER_HPP__
|
||||
#define __SKYSCENEMANAGER_HPP__
|
||||
|
||||
// warning for truncation of template name for browse info
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "vec3f.hpp"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
#include "SkySingleton.hpp"
|
||||
#include "SkyRenderableInstance.hpp"
|
||||
#include "SkyMaterial.hpp"
|
||||
#include "SkyAABBTree.hpp"
|
||||
#include "SkyRenderableInstanceCloud.hpp"
|
||||
|
||||
// forward to reduce unnecessary dependencies
|
||||
class Camera;
|
||||
class SkyRenderable;
|
||||
class SkyRenderableInstance;
|
||||
class SkyMaterial;
|
||||
class SkyLight;
|
||||
class SkyCloud;
|
||||
//class SkyHeavens;
|
||||
//class SkyHeightField;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkySceneManager
|
||||
* @brief Manages all of the renderable objects and instances.
|
||||
*/
|
||||
class SkySceneManager; // Forward declaration
|
||||
|
||||
//! A singleton of the SkySceneManager. Can only create the SceneManager with SceneManager::Instantiate();
|
||||
typedef SkySingleton<SkySceneManager> SceneManager;
|
||||
|
||||
class SkySceneManager
|
||||
{
|
||||
public:
|
||||
SKYRESULT AddObject( SkyRenderable *pObject);
|
||||
SKYRESULT AddInstance( SkyRenderableInstance *pInstance, bool bTransparent = false);
|
||||
|
||||
SKYRESULT AddCloud( SkyCloud *pCloud);
|
||||
SKYRESULT AddCloudInstance(SkyRenderableInstanceCloud *pInstance);
|
||||
|
||||
SKYRESULT AddMaterial( SkyMaterial *pMaterial);
|
||||
SkyMaterial* GetMaterial( int iMaterialID);
|
||||
SKYRESULT ActivateMaterial(int iMaterialID);
|
||||
|
||||
SKYRESULT AddLight( SkyLight *pLight);
|
||||
SkyLight* GetLight( int iLightID);
|
||||
|
||||
//! Set the sky box for this scene.
|
||||
// void SetSkyBox( SkyHeavens *pSkyBox) { _pSkyBox = pSkyBox; }
|
||||
//! Set the terrain for this scene.
|
||||
//void SetTerrain( SkyHeightField *pTerrain) { _pTerrain = pTerrain; }
|
||||
|
||||
//! Enable wireframe display of lights (for debugging).
|
||||
void EnableDrawLights(bool bEnable) { _bDrawLights = bEnable; }
|
||||
//! Enable wireframe display of bounding volume tree of clouds.
|
||||
void EnableDrawBVTree(bool bEnable) { _bDrawTree = bEnable; }
|
||||
|
||||
//! Returns true if wireframe display of lights is enabled.
|
||||
bool IsDrawLightsEnabled() const { return _bDrawLights; }
|
||||
//! Returns true if wireframe display of the cloud bounding volume tree is enabled.
|
||||
bool IsDrawBVTreeEnabled() const { return _bDrawTree; }
|
||||
|
||||
SKYRESULT Update( const Camera &cam);
|
||||
SKYRESULT Display( const Camera &cam);
|
||||
|
||||
SKYRESULT RebuildCloudBVTree();
|
||||
SKYRESULT ShadeClouds();
|
||||
|
||||
//! Force the illumination of all clouds to be recomputed in the next update.
|
||||
void ForceReshadeClouds() { _bReshadeClouds = true; }
|
||||
|
||||
// sort instances in @a instances from back to front.
|
||||
static void SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint);
|
||||
|
||||
// load a set of clouds from an archive file.
|
||||
SKYRESULT LoadClouds(SkyArchive& cloudArchive, float rScale = 1.0f, 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__
|
||||
292
simgear/scene/sky/clouds3d/SkySingleton.hpp
Normal file
292
simgear/scene/sky/clouds3d/SkySingleton.hpp
Normal file
@@ -0,0 +1,292 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkySingleton.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkySingleton.hpp
|
||||
*
|
||||
* A generic singleton template wrapper to make classes into singletons
|
||||
*/
|
||||
#ifndef __SKYSINGLETON_HPP__
|
||||
#define __SKYSINGLETON_HPP__
|
||||
|
||||
#include "SkyUtil.hpp"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkySingleton
|
||||
* @brief A singleton template class.
|
||||
*
|
||||
* Usage : Use this template container class to make any class into a
|
||||
* singleton. I usually do this:
|
||||
*
|
||||
* @code
|
||||
* class MyClass
|
||||
* {
|
||||
* public:
|
||||
* // normal class stuff, but don't put ctor/dtor here.
|
||||
* int GetData() { return _someData; }
|
||||
* protected:
|
||||
* // Make the ctor(s)/dtor protected, so this can only be
|
||||
* // instantiated as a singleton. Note: singleton will still
|
||||
* // work on classes that do not follow this (public ctors)
|
||||
* // but violation of the singleton is possible then, since non-
|
||||
* // singleton versions of the class can be instantiated.
|
||||
* MyClass() : _someData(5) {}
|
||||
* MyClass(int arg) : _someData(arg) {} // etc...
|
||||
* // don't implement the copy constructor, because singletons
|
||||
* // shouldn't be copied!
|
||||
* MyClass(const MyClass& mc) {}
|
||||
* ~MyClass() {}
|
||||
* private:
|
||||
* int _someData;
|
||||
* };
|
||||
*
|
||||
* // now create a singleton of MyClass
|
||||
* typedef SkySingleton<MyClass> MyClassSingleton;
|
||||
*
|
||||
* @endcode
|
||||
* Later, in your program code, you can instantiate the singleton and access
|
||||
* its members like so:
|
||||
*
|
||||
* @code
|
||||
* void somefunc()
|
||||
* {
|
||||
* // instantiate the MyClassSingleton
|
||||
* MyClassSingleton::Instantiate();
|
||||
* // could also call MyClassSingleton::Instantiate(10);
|
||||
* // since we have a constructor of that form in MyClass.
|
||||
*
|
||||
* // access the methods in MyClass:
|
||||
* int data1 = MyClassSingleton::InstancePtr()->GetData();
|
||||
* // or...
|
||||
* int data2 = MyClassSingleton::InstanceRef().GetData();
|
||||
*
|
||||
* // now destroy the singleton
|
||||
* MyClassSingleton::Destroy();
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
template <class T>
|
||||
class SkySingleton : protected T
|
||||
{
|
||||
public:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Instantiate()
|
||||
* @brief Creates the singleton instance for class T.
|
||||
*
|
||||
* Assures (by assertion) that the instance will only be created once.
|
||||
* This works for default constructors.
|
||||
*/
|
||||
static void Instantiate()
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Destroy
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Destroy() { SAFE_DELETE(s_pInstance); }
|
||||
* @brief Destructor, deletes the instance
|
||||
*/
|
||||
static void Destroy() { SAFE_DELETE(s_pInstance); }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : InstancePtr
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn InstancePtr() { assert(s_pInstance); return s_pInstance; }
|
||||
* @brief Returns a pointer to the instance
|
||||
*/
|
||||
static T* InstancePtr() { assert(s_pInstance); return s_pInstance; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : InstanceRef
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn InstanceRef() { assert(s_pInstance); return *s_pInstance; }
|
||||
* @brief Returns a reference to the instance
|
||||
*/
|
||||
static T& InstanceRef() { assert(s_pInstance); return *s_pInstance; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : static void Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn static void Instantiate(const A& a)
|
||||
* @brief Instantiates class of type T that have constructors with an argument
|
||||
*
|
||||
* This might be a source of confusion. These templatized
|
||||
* functions are used to instantiate classes of type T that
|
||||
* have constructors with arguments. For n arguments, you
|
||||
* to add a function below with n arguments. Note, these will
|
||||
* only be created if they are used, since they are templates.
|
||||
* I've added 4 below, for 1-4 arguments. If you get a
|
||||
* compilation error, add one for the number of arguments you
|
||||
* need. Also need a SkySingleton protected constructor with
|
||||
* the same number of arguments.
|
||||
*/
|
||||
template<class A>
|
||||
static void Instantiate(const A& a)
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton(a);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Instantiate(const A& a, const B& b)
|
||||
* @brief Instantiates class of type T that have constructors with 2 args
|
||||
*/
|
||||
template<class A, class B>
|
||||
static void Instantiate(const A& a, const B& b)
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton(a, b);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Instantiate(const A& a, const B& b, const C& c)
|
||||
* @brief Instantiates class of type T that have constructors with 3 args
|
||||
*/
|
||||
template<class A, class B, class C>
|
||||
static void Instantiate(const A& a, const B& b, const C& c)
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton(a, b, c);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Instantiate
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Instantiate(const A& a, const B& b, const C& c, const D& d)
|
||||
* @brief Instantiates class of type T that have constructors with 4 args
|
||||
*/
|
||||
template<class A, class B, class C, class D>
|
||||
static void Instantiate(const A& a, const B& b, const C& c, const D& d)
|
||||
{
|
||||
assert(!s_pInstance);
|
||||
s_pInstance = new SkySingleton(a, b, c, d);
|
||||
}
|
||||
|
||||
protected:
|
||||
// although the instance is of type SkySingleton<T>, the Instance***() funcs
|
||||
// above implicitly cast it to type T.
|
||||
static SkySingleton* s_pInstance;
|
||||
|
||||
private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySingleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySingleton()
|
||||
* @brief Hidden so that the singleton can only be instantiated via public static Instantiate function.
|
||||
*/
|
||||
SkySingleton() : T() {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Singleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Singleton(const A& a)
|
||||
* @brief Used by the templatized public Instantiate() functions.
|
||||
*/
|
||||
template<class A>
|
||||
SkySingleton(const A& a) : T(a) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Singleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Singleton(const A& a, const B& b)
|
||||
* @brief Used by the templatized public Instantiate() functions.
|
||||
*/
|
||||
template<class A, class B>
|
||||
SkySingleton(const A& a, const B& b) : T(a, b) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Singleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Singleton(const A& a, const B& b, const C& c)
|
||||
* @brief Used by the templatized public Instantiate() functions.
|
||||
*/
|
||||
template<class A, class B, class C>
|
||||
SkySingleton(const A& a, const B& b, const C& c) : T(a, b, c) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : Singleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn Singleton(const A& a, const B& b, const C &c, const D& d)
|
||||
* @brief Used by the templatized public Instantiate() functions.
|
||||
*/
|
||||
template<class A, class B, class C, class D>
|
||||
SkySingleton(const A& a, const B& b, const C &c, const D& d) : T(a, b, c, d) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkySingleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkySingleton(const SkySingleton&)
|
||||
* @brief Hidden because you can't copy a singleton!
|
||||
*/
|
||||
SkySingleton(const SkySingleton&) {} // hide the copy ctor: singletons can'
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : ~SkySingleton
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn ~SkySingleton()
|
||||
* @brief Destructor, hidden, destroy via the public static Destroy() method.
|
||||
*/
|
||||
~SkySingleton() {} // hide the dtor:
|
||||
};
|
||||
|
||||
// declare the static instance pointer
|
||||
template<class T> SkySingleton<T>* SkySingleton<T>::s_pInstance = NULL;
|
||||
|
||||
#endif //__SKYSINGLETON_HPP__
|
||||
100
simgear/scene/sky/clouds3d/SkyTexture.hpp
Normal file
100
simgear/scene/sky/clouds3d/SkyTexture.hpp
Normal 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__
|
||||
883
simgear/scene/sky/clouds3d/SkyTextureManager.cpp
Normal file
883
simgear/scene/sky/clouds3d/SkyTextureManager.cpp
Normal file
@@ -0,0 +1,883 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyTextureManager.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
/**
|
||||
* @file SkyTextureManager.cpp
|
||||
*
|
||||
* Implementation of a manager that keeps track of texture resource locations and sharing.
|
||||
*/
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include "SkyTextureManager.hpp"
|
||||
#include "SkyContext.hpp"
|
||||
//#include "glvu.hpp"
|
||||
//#include "ppm.hpp"
|
||||
//#include "tga.hpp"
|
||||
//#include "fileutils.hpp"
|
||||
|
||||
bool SkyTextureManager::s_bSlice3DTextures = false;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::SkyTextureManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::SkyTextureManager(bool bSlice3DTextures)
|
||||
* @brief Constructor.
|
||||
*
|
||||
*/
|
||||
SkyTextureManager::SkyTextureManager(bool bSlice3DTextures /* = false */)
|
||||
{
|
||||
s_bSlice3DTextures = bSlice3DTextures;
|
||||
|
||||
// this should be put somewhere more safe -- like done once in the functions that actually
|
||||
// use these extensions.
|
||||
/*GraphicsContext::InstancePtr()->InitializeExtensions("GL_ARB_texture_cube_map "
|
||||
"GL_VERSION_1_2");*/
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::~SkyTextureManager
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::~SkyTextureManager()
|
||||
* @brief destructor.
|
||||
*
|
||||
* @todo <WRITE EXTENDED SkyTextureManager::~SkyTextureManager FUNCTION DOCUMENTATION>
|
||||
*/
|
||||
SkyTextureManager::~SkyTextureManager()
|
||||
{
|
||||
_texturePaths.clear();
|
||||
for ( TextureIterator iter = _textures.begin();
|
||||
iter != _textures.end();
|
||||
++iter)
|
||||
{
|
||||
DestroyTextureObject(iter->second);
|
||||
}
|
||||
_textures.clear();
|
||||
|
||||
for ( TextureList::iterator uncachedIter = _uncachedTextures.begin();
|
||||
uncachedIter != _uncachedTextures.end();
|
||||
++uncachedIter)
|
||||
{
|
||||
DestroyTextureObject(*uncachedIter);
|
||||
}
|
||||
_uncachedTextures.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::AddPath
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::AddPath(const string &path)
|
||||
* @brief Adds a texture path to the list of active search paths.
|
||||
*
|
||||
*/
|
||||
void SkyTextureManager::AddPath(const string &path)
|
||||
{
|
||||
_texturePaths.push_back(path);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Get2DTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Get2DTexture(const string& filename, SkyTexture& texture, bool bMipmap)
|
||||
* @brief Returns a 2D texture object from the texture set.
|
||||
*
|
||||
* If the texture is already loaded, it is returned. If it is not, the texture is loaded from
|
||||
* file, added to the texture set, and returned.
|
||||
*
|
||||
* If the image cannot be loaded, returns an error. Otherwise returns success.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::Get2DTexture(const string& filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap /* = false */)
|
||||
{
|
||||
TextureIterator iter = _textures.find(filename);
|
||||
|
||||
if (iter != _textures.end())
|
||||
{ // the texture is already loaded, just return it.
|
||||
texture = iter->second;
|
||||
}
|
||||
else
|
||||
{ // the texture is being requested for the first time, load and return it
|
||||
FAIL_RETURN(Clone2DTexture(filename, texture, bMipmap));
|
||||
|
||||
_textures.insert(make_pair(filename, texture));
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Get3DTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Get3DTexture(const string& filename, SkyTexture& texture, unsigned int iDepth, bool bMipmap, bool bLoadFromSliceFiles)
|
||||
* @brief Returns a 3D texture object from the texture set.
|
||||
*
|
||||
* If the texture is already loaded, it is returned. If it is not, the texture is loaded from
|
||||
* file, added to the texture set, and returned. If the image cannot be loaded, returns an error.
|
||||
* Otherwise returns success.
|
||||
*
|
||||
* For 3D textures, this simply loads a 2D image file, and duplicates it across each slice. The
|
||||
* parameter iDepth must be set in order to use a 2D texture image for a 3D texture.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::Get3DTexture(const string& filename,
|
||||
SkyTexture& texture,
|
||||
unsigned int iDepth,
|
||||
bool bMipmap /* = false */,
|
||||
bool bLoadFromSliceFiles /* = false */)
|
||||
{
|
||||
TextureIterator iter = _textures.find(filename);
|
||||
|
||||
if (iter != _textures.end())
|
||||
{ // the texture is already loaded, just return it.
|
||||
texture = iter->second;
|
||||
}
|
||||
else
|
||||
{ // the texture is being requested for the first time, load and return it
|
||||
FAIL_RETURN(Clone3DTexture(filename, texture, iDepth, bMipmap, bLoadFromSliceFiles));
|
||||
|
||||
_textures.insert(make_pair(filename, texture));
|
||||
}
|
||||
|
||||
return SKYRESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : roundPowerOf2
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
static int roundPowerOf2(int n)
|
||||
{
|
||||
int m;
|
||||
for (m = 1; m < n; m *= 2);
|
||||
|
||||
// m >= n
|
||||
if (m - n <= n - m/2)
|
||||
return m;
|
||||
else
|
||||
return m/2;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Clone2DTexture
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Clone2DTexture( const string &filename, SkyTexture& texture, bool bMipmap)
|
||||
* @brief Returns a 2D texture object.
|
||||
*
|
||||
* Ignores texture set. This always loads the file, if it exists, and creates and returns the texture.
|
||||
*
|
||||
* If the image cannot be loaded, returns an error. Otherwise returns success.
|
||||
*/
|
||||
SKYRESULT SkyTextureManager::Clone2DTexture(const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap /* = false */)
|
||||
{
|
||||
string pathFilename;
|
||||
unsigned char *pImageData = NULL;
|
||||
int iWidth = 0;
|
||||
int iHeight = 0;
|
||||
int iChannels = 0;
|
||||
|
||||
enum ImageType
|
||||
{
|
||||
IMAGE_PPM,
|
||||
IMAGE_TGA
|
||||
};
|
||||
ImageType eType;
|
||||
/****
|
||||
// first get the image type from its extension.
|
||||
if (filename.find(".tga") != string.npos || filename.find(".TGA") != string.npos)
|
||||
eType = IMAGE_TGA;
|
||||
else if (filename.find(".ppm") != string.npos || filename.find(".PPM") != string.npos)
|
||||
eType = IMAGE_PPM;
|
||||
else
|
||||
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureManager error: invalid image format");
|
||||
****/
|
||||
// first try the filename sent in in case it includes a path.
|
||||
//if (FileUtils::FileExists(filename.c_str()))
|
||||
//{
|
||||
// printf("Filename is %s\n", filename.c_str() );
|
||||
//eType = IMAGE_TGA;
|
||||
/* switch (eType)
|
||||
{
|
||||
case IMAGE_PPM:
|
||||
LoadPPM(filename.c_str(), pImageData, iWidth, iHeight);
|
||||
iChannels = 3;
|
||||
break;
|
||||
case IMAGE_TGA:
|
||||
LoadTGA(filename.c_str(), pImageData, iWidth, iHeight, iChannels);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}*/
|
||||
|
||||
//}
|
||||
|
||||
if (!pImageData) // image not found in current directory. Check the paths...
|
||||
{
|
||||
|
||||
for ( StringList::iterator iter = _texturePaths.begin();
|
||||
iter != _texturePaths.end();
|
||||
++iter)
|
||||
|
||||
{ // loop over all texture paths, looking for the filename
|
||||
// get just the filename without path.
|
||||
int iPos = filename.find_last_of("/");
|
||||
if (iPos == filename.npos)
|
||||
iPos = filename.find_last_of("/");
|
||||
|
||||
// tack on the paths from the texture path list.
|
||||
if (iPos != filename.npos)
|
||||
pathFilename = (*iter) + "/" + filename.substr(iPos+1);
|
||||
else
|
||||
pathFilename = (*iter) + "/" + filename;
|
||||
|
||||
//if (FileUtils::FileExists(pathFilename.c_str()))
|
||||
//{
|
||||
/* switch (eType)
|
||||
{
|
||||
case IMAGE_PPM:
|
||||
LoadPPM(pathFilename.c_str(), pImageData, iWidth, iHeight);
|
||||
break;
|
||||
case IMAGE_TGA:
|
||||
LoadTGA(pathFilename.c_str(), pImageData, iWidth, iHeight, iChannels);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}*/
|
||||
|
||||
//if (pImageData)
|
||||
//break;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pImageData)
|
||||
{
|
||||
char buffer[256];
|
||||
sprintf(buffer, "SkyTextureManager::Clone2DTexture(): Could not load image. %s.\n", filename.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;
|
||||
} */
|
||||
}
|
||||
208
simgear/scene/sky/clouds3d/SkyTextureManager.hpp
Normal file
208
simgear/scene/sky/clouds3d/SkyTextureManager.hpp
Normal file
@@ -0,0 +1,208 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyTextureManager.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
/**
|
||||
* @file SkyTextureManager.hpp
|
||||
*
|
||||
* Definition of a manager that keeps track of texture locations and sharing of texture files. |
|
||||
*/
|
||||
#ifndef SKYTEXTUREMANAGER_HPP
|
||||
#define SKYTEXTUREMANAGER_HPP
|
||||
|
||||
// #pragma warning( disable : 4786)
|
||||
|
||||
#include "SkySingleton.hpp"
|
||||
#include "SkyTexture.hpp"
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// forward declaration for singleton
|
||||
class SkyTextureManager;
|
||||
|
||||
//! A singleton of the SkyTextureManager. Can only create the TextureManager with TextureManager::Instantiate();
|
||||
typedef SkySingleton<SkyTextureManager> TextureManager;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SkyTextureManager
|
||||
* @brief A resource manager for textures.
|
||||
*
|
||||
* This manager allows textures to be shared. It keeps a mapping of
|
||||
* filenames to texture objects, and makes it easy to use the same texture
|
||||
* for multiple objects without the objects having to be aware of the
|
||||
* sharing. Supports cube map textures, and 2D textures. Can also be used
|
||||
* to "clone textures", which creates unmanaged texture objects from files
|
||||
* that are not kept in the mapping, and thus are not shared.
|
||||
*/
|
||||
class SkyTextureManager
|
||||
{
|
||||
public: // types
|
||||
typedef list<string> StringList;
|
||||
|
||||
public: // methods
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Paths to texture directories
|
||||
//.-------------------------------------------------------------------------.
|
||||
void AddPath(const string& path);
|
||||
//! Return the list of texture paths that will be searched by Get2DTexture() and Get3DTexture().
|
||||
const StringList& GetPaths() const { return _texturePaths; }
|
||||
//! Clear the list of texture paths that will be searched by Get2DTexture() and Get3DTexture().
|
||||
void ClearPaths() { _texturePaths.clear(); }
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Texture loading
|
||||
//.-------------------------------------------------------------------------.
|
||||
SKYRESULT Get2DTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap = false);
|
||||
SKYRESULT Get3DTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
unsigned int iDepth,
|
||||
bool bMipmap = false,
|
||||
bool bLoadFromSliceFiles = false);
|
||||
SKYRESULT GetCubeMapTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap = false);
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Texture cloning: create a duplicate texture object: not added to set!
|
||||
//.-------------------------------------------------------------------------.
|
||||
SKYRESULT Clone2DTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap = false);
|
||||
SKYRESULT Clone3DTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
unsigned int iDepth,
|
||||
bool bMipmap = false,
|
||||
bool bLoadFromSliceFiles = false );
|
||||
SKYRESULT CloneCubeMapTexture( const string &filename,
|
||||
SkyTexture& texture,
|
||||
bool bMipmap = false);
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Texture Object Creation: not added to the texture set (no filename!)
|
||||
//.-------------------------------------------------------------------------.
|
||||
inline SKYRESULT Create2DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData);
|
||||
inline SKYRESULT Create3DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iDepth,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData);
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Texture Object Destruction: use this because texture objects are structs
|
||||
//| that use shallow copies!
|
||||
//.-------------------------------------------------------------------------.
|
||||
static void DestroyTextureObject( SkyTexture &texture);
|
||||
|
||||
|
||||
protected:
|
||||
SkyTextureManager(bool bSlice3DTextures = false);
|
||||
~SkyTextureManager();
|
||||
|
||||
SKYRESULT _Create2DTextureObject( SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData);
|
||||
SKYRESULT _Create3DTextureObject( SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iDepth,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData);
|
||||
private:
|
||||
typedef list<SkyTexture> TextureList;
|
||||
typedef map<string, SkyTexture> TextureSet;
|
||||
typedef TextureSet::iterator TextureIterator;
|
||||
|
||||
//.-------------------------------------------------------------------------.
|
||||
//| Data
|
||||
//.-------------------------------------------------------------------------.
|
||||
|
||||
// paths searched for textures specified by filename.
|
||||
StringList _texturePaths;
|
||||
|
||||
// cached textures
|
||||
TextureSet _textures; // loaded textures
|
||||
// textures created directly, not loaded from file and cached.
|
||||
TextureList _uncachedTextures;
|
||||
|
||||
// if this is true, then 3D textures will be represented as a set of 2D slices.
|
||||
static bool s_bSlice3DTextures;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Create2DTextureObject
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Create2DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iFormat, unsigned char *pData)
|
||||
* @brief Creates a 2D texture.
|
||||
*
|
||||
* Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
|
||||
* This texture will be deleted by the texture manager at shutdown.
|
||||
*
|
||||
*/
|
||||
inline SKYRESULT SkyTextureManager::Create2DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData)
|
||||
{
|
||||
SKYRESULT retval = _Create2DTextureObject(texture, iWidth, iHeight, iFormat, pData);
|
||||
if SKYSUCCEEDED(retval)
|
||||
_uncachedTextures.push_back(texture);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTextureManager::Create3DTextureObject
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyTextureManager::Create3DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iDepth, unsigned int iFormat, unsigned char *pData)
|
||||
* @brief Creates a 3D texture.
|
||||
*
|
||||
* Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
|
||||
* This texture will be deleted by the texture manager at shutdown, and should not be destroyed
|
||||
* by the user.
|
||||
*
|
||||
*/
|
||||
inline SKYRESULT SkyTextureManager::Create3DTextureObject(SkyTexture &texture,
|
||||
unsigned int iWidth,
|
||||
unsigned int iHeight,
|
||||
unsigned int iDepth,
|
||||
unsigned int iFormat,
|
||||
unsigned char *pData)
|
||||
{
|
||||
SKYRESULT retval = _Create3DTextureObject(texture, iWidth, iHeight, iDepth, iFormat, pData);
|
||||
if SKYSUCCEEDED(retval)
|
||||
_uncachedTextures.push_back(texture);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif //QGLVUTEXTUREMANAGER_HPP
|
||||
351
simgear/scene/sky/clouds3d/SkyTextureState.cpp
Normal file
351
simgear/scene/sky/clouds3d/SkyTextureState.cpp
Normal 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;
|
||||
}
|
||||
|
||||
206
simgear/scene/sky/clouds3d/SkyTextureState.hpp
Normal file
206
simgear/scene/sky/clouds3d/SkyTextureState.hpp
Normal 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__
|
||||
50
simgear/scene/sky/clouds3d/SkyUtil.cpp
Normal file
50
simgear/scene/sky/clouds3d/SkyUtil.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyUtil.cpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyUtil.cpp
|
||||
*
|
||||
* Implemtation of global utility functions.
|
||||
*/
|
||||
#include "SkyUtil.hpp"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTrace
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* SkyTrace( char* strMsg, ... )
|
||||
* @brief Prints formatted output, debug only.
|
||||
*
|
||||
* Includes file and line number information automatically.
|
||||
*/
|
||||
void SkyTrace( char* strMsg, ... )
|
||||
{
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
|
||||
char strBuffer[512];
|
||||
|
||||
va_list args;
|
||||
va_start(args, strMsg);
|
||||
_vsnprintf( strBuffer, 512, strMsg, args );
|
||||
va_end(args);
|
||||
|
||||
fprintf(stderr, "[SkyTrace] %s(%d): %s\n",__FILE__, __LINE__, strBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
192
simgear/scene/sky/clouds3d/SkyUtil.hpp
Normal file
192
simgear/scene/sky/clouds3d/SkyUtil.hpp
Normal file
@@ -0,0 +1,192 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File : SkyUtil.hpp
|
||||
//------------------------------------------------------------------------------
|
||||
// SkyWorks : Copyright 2002 Mark J. Harris and
|
||||
// The University of North Carolina at Chapel Hill
|
||||
//------------------------------------------------------------------------------
|
||||
// Permission to use, copy, modify, distribute and sell this software and its
|
||||
// documentation for any purpose is hereby granted without fee, provided that
|
||||
// the above copyright notice appear in all copies and that both that copyright
|
||||
// notice and this permission notice appear in supporting documentation.
|
||||
// Binaries may be compiled with this software without any royalties or
|
||||
// restrictions.
|
||||
//
|
||||
// The author(s) and The University of North Carolina at Chapel Hill make no
|
||||
// representations about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or
|
||||
// implied warranty.
|
||||
/**
|
||||
* @file SkyUtil.hpp
|
||||
* @brief Safe deallocation functions, result codes, trace functions, and macros.
|
||||
*/
|
||||
#ifndef __SKYUTIL_HPP__
|
||||
#define __SKYUTIL_HPP__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Useful constants
|
||||
//-----------------------------------------------------------------------------
|
||||
//! Pi.
|
||||
const float SKY_PI = 4.0f * (float) atan(1.0f);
|
||||
//! 1.0 / Pi
|
||||
const float SKY_INV_PI = 1.0f / SKY_PI;
|
||||
//! 1.0 / (4.0 * Pi)
|
||||
const float SKY_INV_4PI = 1.0f / (4.0f * SKY_PI);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Safe deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
//! Delete and set pointer to NULL.
|
||||
#define SAFE_DELETE(p) { delete (p); (p)=NULL; }
|
||||
//! Delete an array and set pointer to NULL.
|
||||
#define SAFE_DELETE_ARRAY(p) { delete[] (p); (p)=NULL; }
|
||||
//#define SAFE_RELEASE(p) { (p) = NULL; }
|
||||
//{ if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Useful Macros
|
||||
//------------------------------------------------------------------------------
|
||||
//! Convert Degrees to Radians
|
||||
#define SKYDEGREESTORADS 0.01745329252f
|
||||
//! Convert Radians to Degrees
|
||||
#define SKYRADSTODEGREES 57.2957795131f
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyGetLogBaseTwo
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn SkyGetLogBaseTwo(int iNum)
|
||||
* @brief Returns the integer base two logarithm of the integer input.
|
||||
*/
|
||||
inline int SkyGetLogBaseTwo(int iNum)
|
||||
{
|
||||
int i, n;
|
||||
for(i = iNum-1, n = 0; i > 0; i >>= 1, n++ );
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : SkyTrace
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
void SkyTrace( char* strMsg, ... );
|
||||
|
||||
|
||||
//.----------------------------------------------------------------------------.
|
||||
//| Result Codes |
|
||||
//.----------------------------------------------------------------------------.
|
||||
//! SKYRESULTs are used for returning error information that can be used to trace bugs.
|
||||
typedef int SKYRESULT;
|
||||
|
||||
//! Returns true if the SKYRESULT is a success result.
|
||||
#define SKYSUCCEEDED(Status) ((SKYRESULT)(Status) >= 0)
|
||||
//! Returns true if the SKYRESULT is a failure result.
|
||||
#define SKYFAILED(Status) ((SKYRESULT)(Status) < 0)
|
||||
|
||||
//! SKYRESULTs are used for returning error information that can be used to trace bugs.
|
||||
enum SKYRESULT_CODES
|
||||
{
|
||||
// SUCCESS CODES: non-negative
|
||||
SKYRESULT_OK = 1,
|
||||
// FAILURE CODES: negative
|
||||
SKYRESULT_FAIL = -1
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FAIL_RETURN
|
||||
//-----------------------------------------------------------------------------
|
||||
// Print debug messages to the WIN32 debug window
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : FAIL_RETURN
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn FAIL_RETURN(p)
|
||||
* @brief Prints a trace message if @a p failed, and returns the failure code.
|
||||
*
|
||||
* Outputs in a format that can be double-clicked in DevStudio to open the
|
||||
* appropriate file and location.
|
||||
*/
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
#define FAIL_RETURN(p) \
|
||||
{ \
|
||||
SKYRESULT __SKYUTIL__result__; \
|
||||
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
|
||||
fprintf(stderr, "!!!! FAIL_RETURN TRAP !!!! %s: %d: %d\n",__FILE__, __LINE__, __SKYUTIL__result__); \
|
||||
return __SKYUTIL__result__; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define FAIL_RETURN(p) p
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : FAIL_RETURN_MSG
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn FAIL_RETURN_MSG(p,str)
|
||||
* @brief Similar to FAIL_RETURN, but also appends a user-supplied message.
|
||||
*
|
||||
* @see FAIL_RETURN, FAIL_RETURN_MSG
|
||||
*/
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
#define FAIL_RETURN_MSG(p,str) \
|
||||
{ \
|
||||
SKYRESULT __SKYUTIL__result__; \
|
||||
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
|
||||
fprintf(stderr, "!!!! FAIL_RETURN_MSG TRAP !!!! %s: %d: %d: %s\n",__FILE__,__LINE__,__SKYUTIL__result__,str); \
|
||||
return __SKYUTIL__result__; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define FAIL_RETURN_MSG(p,str) p
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Function : FAIL_RETURN_MSGBOX
|
||||
// Description :
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @fn FAIL_RETURN_MSGBOX(p,str)
|
||||
* @brief Similar to FAIL_RETURN_MSG, but also displays the error in a message box (in Windows).
|
||||
*
|
||||
* @see FAIL_RETURN_MSG, FAIL_RETURN
|
||||
*/
|
||||
#if defined(DEBUG) | defined(_DEBUG)
|
||||
#ifdef USEWINDOWSOUTPUT
|
||||
#define FAIL_RETURN_MSGBOX(p,str) \
|
||||
{ \
|
||||
SKYRESULT __SKYUTIL__result__; \
|
||||
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
|
||||
char msg[512]; \
|
||||
sprintf(msg, "%s: %d: %d: %s\n",__FILE__,__LINE__,__SKYUTIL__result__,str); \
|
||||
MessageBox(NULL, msg, "!!!! FAIL_RETURN_MSG TRAP !!!!", MB_OK); \
|
||||
return __SKYUTIL__result__; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define FAIL_RETURN_MSGBOX(p,str) \
|
||||
{ \
|
||||
SKYRESULT __SKYUTIL__result__; \
|
||||
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
|
||||
fprintf(stderr, "!!!! FAIL_RETURN_MSG TRAP !!!! %s: %d: %d: %s\n",__FILE__,__LINE__,__D3DUTIL__hres__,str); \
|
||||
return __SKYUTIL__result__; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#define FAIL_RETURN_MSGBOX(p,str) p
|
||||
#endif
|
||||
|
||||
#endif //__SKYUTIL_HPP__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user