Compare commits

...

116 Commits

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

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

Probably a good idea to add some user options to set cloud altitude, startup
position, etc, but for now this should suffice.
2002-10-04 16:44:23 +00:00
curt
c6832d2513 Fixes from Mark Harris. 2002-10-03 19:00:01 +00:00
curt
1fd63c30e9 Fix a texture state problem that caused clouds to occasionally flash all white. 2002-10-03 18:44:34 +00:00
curt
f08ae9f2ea John Wojnaroski:
Attached are the new files to transform the cloud field for local lat/lon.
2002-10-03 02:52:55 +00:00
curt
5c61e97358 ref() the cloud states before use so that if we are dyanmically creating and
deleting cloud layers we don't inadvertantly delete a cloud state.
2002-10-02 16:03:25 +00:00
curt
87e38e2617 Fix a tyop. 2002-09-22 03:42:26 +00:00
curt
92e1856caa Did I forget to commit John's loader patch?
Ran dos2unix on extgl.*
Include <simgear_config.h> from extgl.h so it properly picks up the WIN32
symbol.
2002-09-20 18:10:28 +00:00
curt
20c099b7ef Added extgl.c and extgl.h 2002-09-19 02:30:52 +00:00
curt
7eb74c7e2a Tweaks to build system following removal of interpreter subdir. 2002-09-18 20:38:40 +00:00
david
8d63c300e2 Removed simgear/interpreter directory; most likely we will use the new
PSL interpreted language in plib.
2002-09-18 20:27:17 +00:00
curt
01ccdd3ae1 Erik Hofman:
This patch fixes and STL problem, and adds (compile time) support for
architextures that don't support multitexturing.
2002-09-18 19:41:52 +00:00
curt
ab074726df Removed unnecessary files. 2002-09-18 18:47:47 +00:00
curt
ed26458a24 Norman's most recent 3d clouds code tweaks. 2002-09-18 14:24:19 +00:00
curt
fcf1d34e55 Latest changes from John. 2002-09-17 16:08:00 +00:00
curt
19f99ea273 Build with other simgear header files from source tree, not those that are
installed.
2002-09-17 01:16:18 +00:00
curt
fe5bb76def Latest changes from John Wojnaroski. 2002-09-16 14:55:31 +00:00
david
7ecf508453 Rolled Norm's change back out; update needs to be called earlier. 2002-09-16 13:13:49 +00:00
david
83e6e44eab Patches from Norm Vine to get clouds working (and add some debugging
information).
2002-09-16 02:26:20 +00:00
david
69a93342c0 Ignore generated files. 2002-09-15 10:42:54 +00:00
curt
e17338622a Change the header install directory.
Clean up a couple warnings.
2002-09-15 04:32:28 +00:00
david
a67fd7ea99 Added autom4te.cache. 2002-09-14 16:06:22 +00:00
david
cf2b8afbe9 Added stamp-h1. 2002-09-14 16:05:58 +00:00
david
a1e7761384 Removed /usr/local/include (as with plib). 2002-09-14 16:05:41 +00:00
david
d068915b42 Added newlines and did other clean-ups to eliminate errors and
minimize warnings compiling with g++ 3.2.
2002-09-14 16:03:39 +00:00
curt
adeb0d48fc Upgrade the version number. 2002-09-13 23:19:14 +00:00
curt
55c89ea865 Added simgear/sky/clouds3d to the build system. 2002-09-13 22:51:40 +00:00
curt
8bd07e358f Tweak lib name. 2002-09-13 20:36:19 +00:00
curt
01113e82f3 Initial revision. 2002-09-13 20:29:04 +00:00
curt
6d79582890 Initial revision 2002-09-07 02:58:19 +00:00
curt
2ae3c89406 For version 0.2.0 2002-09-07 01:45:46 +00:00
curt
1818102ffe Updated ... 2002-09-07 01:33:17 +00:00
curt
406d6dd6fc Getting ready for 0.2.0 stable release. 2002-09-07 01:25:02 +00:00
curt
c8ef854f01 Fixes to allow MingW compilation. 2002-09-06 20:05:40 +00:00
curt
87dcaf5a00 Fixes to better support the native irix compilers. 2002-09-06 15:30:11 +00:00
curt
c3bdd0e537 Automake version check is only done in autogen.sh and not in configure. 2002-09-03 21:44:44 +00:00
curt
c23fd6e66f Fix a typo in acinclude.m4 2002-09-03 02:52:39 +00:00
curt
e809eee896 Additional configure changes. 2002-09-02 22:18:31 +00:00
curt
c44ef2126c Tweaks for next prerelease. 2002-09-02 04:08:01 +00:00
curt
e2bfb5633b Minor tweaks. 2002-09-02 03:43:05 +00:00
curt
064ee8ba8f Make sure interpreters/ gets included with "make dist" 2002-09-02 03:41:39 +00:00
curt
a5c130446e Preparation for next pre-release. 2002-08-31 18:39:07 +00:00
curt
4162817c0b More clean ups. 2002-08-31 13:18:49 +00:00
curt
81cab6e089 Additional build system tweaks, regenerated the .dsp/.dsw's. 2002-08-30 15:03:30 +00:00
curt
d78204d147 Several fixes and tweaks. 2002-08-29 14:00:35 +00:00
curt
d8b523d067 Attempting more fixes to our autoconf/make scripts. 2002-08-28 14:08:12 +00:00
curt
c4cfad6069 Additional tweaks that got lost somehow. 2002-08-27 21:48:51 +00:00
curt
5bddb88ce2 Ooops, minor typo fixed. 2002-08-27 21:45:48 +00:00
curt
8c4ee69aeb Modernize the autoconf scripts a bit. 2002-08-27 21:44:39 +00:00
curt
b3a533f8ce Add #ifdef'd out support for plibs cheesy lens flare object. 2002-08-27 21:43:35 +00:00
curt
a885314a39 Tidy up the autoconf/automake configuration a bit.
- Removed some old cruft.

- Removed some support for older versions of automake which technically was
  correct, but caused the newer automakes to squawk warnings during an
  initial sanity check (which isn't done very intelligently.)

  NOTE: this fix is technically not correct for older version of automake.
  These older version use the variable "INCLUDES" internally and could have
  them already set to an important value.  That is why we were appending
  our values to them.  However, newer versions of automake don't set this
  value themselves so it is an error to append to a non-existant variable.
  We seem to "get away" with overwriting the value on older versions of
  automake, but if you have problems, consider upgrading to at least
  automake-1.5.
2002-08-25 17:31:47 +00:00
curt
0567a76445 It probably is better not to hide warning messages. Removed spaces from
AC_DEFINE( SYMBOL ) -> AC_DEFINE(SYMBOL)
2002-08-24 18:21:49 +00:00
curt
d6dc2d6eab Brandon Bergren:
2. I changed Simgear's autogen.sh so it is quieter, and errors out if
autoheader or autoconf fails.  It puts all error output in autogen.err, and
deletes it if nothing errored out.  The patch is in (sg.autogen.sh.patch.gz)
This patch applies to flightgear, too.  If someone doesn't like what I did
here, please speak up!  I really believe that this patch will help cause
less confusion among people new to compiling flightgear.
2002-08-24 03:54:45 +00:00
curt
b75a694682 Bernie Bright:
Here are some changes that gave me a significant frame rate increase of about 10 fps with random objects disabled.  The interesting thing is that these changes aren't in the main loop but are in tile loader.  My guess is that I've reduced the memory footprint just enough to reduce CPU cache misses, though I have no hard evidence of this.

Initially I modified all SGBinObject member functions to pass/return by reference instead of by-value.  This gives little or no speed up but allows for some optimizations in fgBinObjLoad().  It is these changes that reduce the number of memory allocations.  Needless copying of vectors, and vectors of vectors, can be very memory intensive, especially if they are large.

Anyway I would be interested to see if you get similar results.  I would emphasize that the frame rate increase only occurs with random objects disabled.  I lose about 10-15 fps on my GF2MX 32MB with random objects, probably a fill-rate limitation or texture memory thing.
2002-08-23 17:52:10 +00:00
david
2e7e9b73a0 Change from Norman Vine to add new random-number algorithm. 2002-08-05 18:43:28 +00:00
david
7a11523692 Random-number seed patch from Erik Hofman. 2002-07-31 17:14:29 +00:00
curt
f85a9866fe Remove efence support in favor of valgrind. 2002-07-30 14:10:08 +00:00
david
9b05c27938 Remove ECMAScript interpreter from the default build for now. It can
still be built from inside the directory.
2002-07-30 11:58:34 +00:00
david
fd96729362 Patch from Cameron Moore:
* Fixed (un)signed comparison
2002-07-18 20:30:18 +00:00
david
c57cc096f8 Patch from Cameron Moore:
* Rearranged member initializers to shut gcc -Wall up
2002-07-18 20:30:02 +00:00
david
c8efd0a465 Added JavaScript interpreter, repackaged by Tony Peden. It's not tied
into anything yet, but it builds OK inside SimGear.
2002-07-18 20:27:46 +00:00
david
db60139845 Downgrade cloud-base alert to a debug warning. 2002-07-18 20:23:30 +00:00
david
cadefd323a Quick fix for bug reported by Julian Foad, where the simplify flag was
not honoured after the first call.  This isn't all that efficient, and
the return type probably should change to string eventually, but this
fix avoids changing the headers for now.
2002-07-18 20:04:50 +00:00
david
baab88f42a Fix deletes in destructor. 2002-07-06 15:00:37 +00:00
david
767b74dd35 Added new getDisplayName method that gets the name with its index.
Suggested by Julian Foad.
2002-07-06 14:58:38 +00:00
david
90e8287f43 Made SGPropertyNode::getPath extremely efficient: it now caches its
result, so after the first call for any node, it simply tests and
returns a pointer.  This also fixes the problem of buffer conflicts
with make_string.

Added SGPropertyNode::hasChild(const char * name, int index = 0) to
provide a syntactically-cleaner way to test for the existence of a
child node, i.e.

  for (int i = 0; i < 9; i++) {
    if (node->hasChild("foo", i))
      foo[i] = node->getChild("foo", i)->getDoubleValue();
  }
2002-07-06 13:19:02 +00:00
david
d8b7e5b8fd Added simgear_config.h.in 2002-07-06 12:06:40 +00:00
curt
7769447283 Fixed a couple minor compiler warnings. 2002-07-03 17:35:49 +00:00
david
d6a790cf13 MSVC++ bug work-around from Frederic Bouvier. 2002-07-03 02:06:23 +00:00
curt
033c66363d Fixes for IA-64 with Intel compiler. 2002-07-02 18:44:20 +00:00
david
3ff1789963 Fixed an MSVC compilation problem reported by Frederic Bouvier. 2002-06-28 17:02:42 +00:00
david
9737c0c4dd Fixed bug reported by Julian Foad:
While investigating, I found that SGPropertyNode::getPath returns a
(char *) pointer to the character data of a string on its stack,
i.e. to undefined memory after it returns.  I remember someone was
changing strings to char* for efficiency.  Perhaps this bug was
introduced then.  I'll include a patch for it with my eventual patch
for the above, unless someone beats me to it.  I don't think it
affects any existing callers: they all want a string anyway.
2002-06-28 16:56:14 +00:00
david
b201383a80 Patch from Julian Foad:
Initialise a "possibly uninitialised" variable (which was already
functionally correct).

[Note from DPM: this patch will be blown away if we ever update to a
newer version of Expat.]
2002-06-28 15:55:11 +00:00
david
2253b82304 Patch from Julian Foad:
Remove a hack that originally worked around a buffer overflow
elsewhere in the file.  The buffer overflow was fixed long ago, but
the hack was not removed.
2002-06-28 15:54:34 +00:00
david
2581446d85 Patch from Julian Foad:
Remove trailing comma (unportable).
2002-06-28 15:54:15 +00:00
david
a6291b286c Patch from Julian Foad:
Remove unused static function (warning because it cannot possibly be used).
2002-06-28 15:53:58 +00:00
david
96a396bfcb Patch from Julian Foad:
This file should be removed from CVS because it is generated by
autogen.sh.
2002-06-28 15:53:31 +00:00
david
0833a11686 Significant improvements to the change-listener support. There are
now three different change events, and the listener base class removes
itself from the parent in the destructor.
2002-06-18 21:17:42 +00:00
david
9c7f7f3d32 Added a ptr() method to SGPropertyNode_ptr to get the raw pointer.
Added the SGPropertyChangeListener interface and addChangeListener and
firePropertyChange methods.
2002-06-18 01:26:09 +00:00
david
7847fe8074 Patch from Melchior Franz:
layer_span used uninitialized in SGCloudLayer::rebuild (line 162, 170, etc.)
2002-06-07 17:39:38 +00:00
david
c57d25ac51 Be more conservative and reuse SSG objects. 2002-06-05 19:12:50 +00:00
david
1341b5b9f8 Try to avoid some memory leaks. 2002-06-05 15:43:04 +00:00
curt
fb54e9e103 Include the autogen.sh script in the distribution. 2002-05-23 13:46:19 +00:00
david
3a835dde7d Skip drawing clear cloud layers. 2002-05-17 16:53:19 +00:00
curt
128a4a36ca Bernie Bright:
I've defined snprintf as _snprintf in compiler.h for MSVC and MINGW
targets and removed duplicate definitions from FG sources.
2002-05-17 14:38:03 +00:00
david
255bb6dd07 Preparation for making dynamic cloud layers -- moved cloud state out
of sky.[ch]xx and into cloud.[ch]xx, and added setters for modifying
the state of an existing layer.
2002-05-16 23:16:39 +00:00
curt
786b1e3a30 Removed SG_STATIC_CONST define. 2002-05-16 02:44:35 +00:00
curt
d5f38a558e Minor tweaks. 2002-05-16 02:30:06 +00:00
curt
ce5d4b7db8 Erik Hofman:
Some small patches to make the code Irix/Muli platform compatible and
one small fix to make it plib-1.4.2 compatible also.
2002-05-15 19:21:54 +00:00
curt
8c0b36fe9e Added SG_COMPILER macro. This is a string that identifies the build
compiler and version.  It might be useful to display it during program
startup.
2002-05-14 18:59:03 +00:00
david
c7e6459c64 Modified to work with the new SGPropertyNode_ptr class. 2002-05-10 22:58:03 +00:00
david
86e31e696d Patch from Frederic Bouvier:
I have modified the SGPropertyNode interface to support node removal
and address the issues you mention yesterday.

I added the SGPropertyNode_ptr class that is a smart pointer that
increment and decrement a counter in SGPropertyNode. The _children
vector is changed to a vector<SGPropertyNode_ptr> in order for the
node to hold a reference to its children. I also added a
_removedChildren vector of the same type. When removeChild is called
with the keep parameter set to true, the reference is removed from
_children and inserted in _removedChildren, and the attribute REMOVED
is set. When getChild is called with create set to true, the _children
vector is searched, then the _removedChildren and then a new node is
created. If a resurrected node is returned, the REMOVED bit is cleared.
The static const int LAST_USED_ATTRIBUTE is also added.

The footprint of this patch is light. SGPropertyNode is one int
longer in size, SGPropertyNode_ptr is one pointer large without
virtual functions. Some functions can be inlined if your current
policy change.

The FlightGear patch is to take account the change in the getChildren
function that now returns a vector<SGPropertyNode_ptr>. If the
removeChild functionnality is to be added in FlightGear, all those
SGPropertyNode * floating around should be changed to
SGPropertyNode_ptr.
2002-05-10 22:57:36 +00:00
david
be0b1bb994 Mac OS X fixes from Jonathan Polley. 2002-05-10 21:33:12 +00:00
david
03e74bfeb4 Ignore binaries. 2002-05-10 21:31:55 +00:00
david
972223cd50 Eliminate an unsigned-int comparison warning. 2002-05-10 21:31:15 +00:00
curt
761b7b9354 Bernie Bright:
Here's a first cut at SGSocket reimplemented using plib.net.  I've
maintained the same TCP server behaviour, that is only one client
connection at a time.  I don't think it is possible within the current
framework to handle simultaneous clients.

I've also added two simple test programs, tcp_client and tcp_server.
2002-05-10 13:53:22 +00:00
curt
6a3d1895d9 Bernie Bright:
Here is a total rewrite of the strutils package.  I've reimplemented the
trimleft(), trimright() and trim() functions as lstrip(), rstrip() and
strip() respectively.  Additionally I've added a split() function that
behaves like its perl/python equivalent.  Just the thing for splitting
comma separated option strings or space separated telnet commands and
arguments.  I've also enclosed the whole thing in a namespace
simgear::strutils.  Since I seem to be the only one who uses these
functions, SimGear and FlightGear compile without change.

PS It is no coincidence that the new function names bear an uncanny
resemblance to the python functions of the same name.
2002-05-10 13:32:44 +00:00
curt
d1178a26ce Updated MSVC project files. 2002-05-10 13:31:44 +00:00
curt
8ffdfa3cb1 Make the skydome interface a little more flexible so we can scale the dome
for other applications.
2002-04-27 03:19:45 +00:00
david
384e56b9b4 Patches from Erik Hoffman:
Tbis is a first patch in a series to clean up SimGear by removing
warning messages. Most of them are straight forwared, but in pops.hxx
the compile complaints about "type qualifier is meaningless on return
type". I think it's up to you to decide if you want that part applied.
2002-04-25 15:09:10 +00:00
david
d198e962b0 Patch from Melchior Franz:
From the cosmetics department ...
2002-04-25 14:56:03 +00:00
david
0136fdadbb Patch from Melchior Franz:
magvar and magdip are used before their initialization
2002-04-25 14:55:40 +00:00
curt
c616568830 Make sure README.MSVC goes in the distribution. 2002-04-23 01:56:51 +00:00
curt
995d2c1ede Make sure zlib.dsp goes in the distribution. 2002-04-23 01:55:48 +00:00
curt
051a5e9a38 Updated am2dsp.cfg file for creating MSVC project files.
New README.MSVC.
New src-libs/zlib.dsp for building zlib.
2002-04-22 20:37:31 +00:00
curt
60d89097de Bump up version number, remove boost from src-libs/Makefile.am 2002-04-20 22:03:35 +00:00
154 changed files with 22561 additions and 2171 deletions

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
EXTRA_DIST = \
acsite.m4 \
acconfig.h \
mksymlinks.sh \
acinclude.m4 \
autogen.sh \
README.MSVC \
README.metakit \
README.zlib \
SimGear.dsp \
@@ -9,6 +9,9 @@ EXTRA_DIST = \
SUBDIRS = src-libs simgear
dist-hook:
(cd $(top_srcdir); $(HOME)/projects/FlightGear-0.7/admin/am2dsp.pl)
#
# Rule to build RPM distribution package
#

36
NEWS
View File

@@ -1,3 +1,39 @@
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
* Modernized the autoconf/make scripts, plus lots of tweaks and enhancements.
* Removed efence support (in favor of valgrind.)
* Added a javascript interpreter.
* SGSocket reimplimented on top of plib/net libs.
* Added a new random number generation algorithm.
* Total rewrite of the strutils package.
* Patch for the random number seed.
* IA-64 w/ Intel compiler fixes.
* MSVC/MINGW fixes.
* Mac OS X fixes.
* Irix fixes.
* Code clean ups to remove warning messages.
* Optimizations in sg_binobj to reduce the amout of memory copying
needed when loading a binobj format file.
* Fixed a couple places where variables could be used before they were
initialized.
* Various property manager fixes and improvements.
* Fixes to cloud layer management code.
* Made the sky dome more flexible to facilitate use in other applications.
New in 0.0.18
* April 20, 2002

24
README.MSVC Normal file
View File

@@ -0,0 +1,24 @@
This document describes how to build SimGear using the supplied workspace and
project files.
Unpack the SimGear source file into your work directory. This creates a new
subdirectory called SimGear-X.Y.Z. Rename this to SimGear. Before we can
build SimGear you must unpack and build the third party libraries metakit and
zlib. Sources for these are included in the SimGear/src-libs directory.
Unpack these into the top level SimGear directory. At this point your
directory structure should look something like this:
<work_dir>/
SimGear/
metakit-x.y.z/
simgear/
src-libs/
zlib-x.y.z/
Now open the SimGear workspace. This workspace file contains projects for
building metakit(mklib), SimGear and zlib. Select each project as the active
project and build all. Order is unimportant since there are no dependencies
between the projects.
The workspace and project files are generated by a perl script with extra
input from the am2dsp.cfg file.

16
README.plib Normal file
View File

@@ -0,0 +1,16 @@
[This file is mirrored in both the FlightGear and SimGear packages.]
You *must* have plib version 1.6.0 or later installed on your system
to build FlightGear!" Flight Gear is no longer compatible with the
earlier versions of the library.
You can get the latest version of plib from:
http://plib.sourceforge.net
Build notes:
You should be able to just run "./configure" to configure the package
and use all of plib's defaults. Then run "make" followed by "make
install". By default, plib installs itself into /usr so if you don't
like this, be sure to specify an alternate prefix such as --prefix=/usr/local

View File

@@ -30,19 +30,12 @@ RSC=rc.exe
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "HAVE_CONFIG_H" /I "." /I ".." /I ".\SimGear" /D "HAVE_CONFIG_H" /D "NDEBUG" /D "WIN32" /D "_MBCS" /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /FD /c /MT /I "." /I ".." /I ".\SimGear" /I ".\SimGear\metakit-2.4.3\include" /I "..\SimGear\zlib-1.1.4" /D "HAVE_CONFIG_H"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
@@ -53,19 +46,12 @@ LINK32=link.exe -lib
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /GX /ZI /Od /D "HAVE_CONFIG_H" /I "." /I ".." /I ".\SimGear" /D "HAVE_CONFIG_H" /D "_DEBUG" /D "WIN32" /D "_MBCS" /FR /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD CPP /nologo /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /FR /FD /GZ /c /MT /I "." /I ".." /I ".\SimGear" /I ".\SimGear\metakit-2.4.3\include" /I "..\SimGear\zlib-1.1.4" /D "HAVE_CONFIG_H"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
@@ -409,6 +395,21 @@ SOURCE=.\simgear\io\sg_socket.cxx
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\io\sg_socket_udp.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgio"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgio"
!ENDIF
# End Source File
# End Group
# Begin Group "Lib_sgmagvar"
@@ -1131,6 +1132,325 @@ SOURCE=.\simgear\sky\stars.cxx
!ENDIF
# End Source File
# End Group
# Begin Group "Lib_sgclouds3d"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\vec3fv.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\mat16fv.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\tri.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\plane.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\camera.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\camutils.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\minmaxbox.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyMinMaxBox.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyLight.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyMaterial.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyTextureManager.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyTextureState.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyDynamicTextureManager.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyRenderableInstanceCloud.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyRenderableInstanceGroup.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyCloud.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyArchive.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyUtil.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkyContext.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkySceneManager.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\sky\clouds3d\SkySceneLoader.cpp
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgclouds3d"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgclouds3d"
!ENDIF
# End Source File
# End Group
# Begin Group "Lib_sgtiming"
@@ -1490,376 +1810,26 @@ SOURCE=.\simgear\xml\xmltok_impl.h
# End Source File
# End Group
# Begin Group "Lib_z"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\simgear\zlib\adler32.c
SOURCE=.\simgear\simgear_config.h.vc5
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\compress.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\crc32.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\deflate.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\deflate.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\gzio.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\infblock.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\infblock.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\infcodes.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\infcodes.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\inffast.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\inffast.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\inffixed.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\inflate.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\inftrees.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\inftrees.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\infutil.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\infutil.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\trees.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\trees.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\uncompr.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\zutil.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\zlib\zutil.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_z"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_z"
!ENDIF
# End Source File
# End Group
# Begin Source File
SOURCE = .\simgear\simgear_config.h.vc5
!IF "$(CFG)" == "FlightGear - Win32 Release"
# Begin Custom Build - Creating config.h
InputPath=.\simgear\simgear_config.h.vc5
".\simgear\simgear_config.h": $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
".\simgear\simgear_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy .\simgear\simgear_config.h.vc5 .\simgear\simgear_config.h
# End Custom Build
!ELSEIF "$(CFG)" == "FlightGear - Win32 Debug"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# Begin Custom Build - Creating config.h
InputPath=.\simgear\simgear_config.h.vc5
".\simgear\simgear_config.h": $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
".\simgear\simgear_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy .\simgear\simgear_config.h.vc5 .\simgear\simgear_config.h
# End Custom Build

View File

@@ -15,6 +15,30 @@ Package=<4>
###############################################################################
Project: "mklib"=".\SimGear\metakit-2.4.3\win\msvc60\mklib.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "zlib"=".\SimGear\zlib.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>

1
TODO Normal file
View File

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

View File

@@ -1,327 +0,0 @@
/* acconfig.h
This file is in the public domain.
Descriptive text for the C preprocessor macros that
the distributed Autoconf macros can define.
No software package will use all of them; autoheader copies the ones
your configure.in uses into your configuration header file templates.
The entries are in sort -df order: alphabetical, case insensitive,
ignoring punctuation (such as underscores). Although this order
can split up related entries, it makes it easier to check whether
a given entry is in the file.
Leave the following blank line there!! Autoheader needs it. */
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
#undef _ALL_SOURCE
#endif
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Define if type char is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
#undef __CHAR_UNSIGNED__
#endif
/* Define if the closedir function returns void instead of int. */
#undef CLOSEDIR_VOID
/* Define to empty if the keyword does not work. */
#undef const
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
/* Define for DGUX with <sys/dg_sys_info.h>. */
#undef DGUX
/* Define if you have <dirent.h>. */
#undef DIRENT
/* Define to enable audio support */
#undef ENABLE_AUDIO_SUPPORT
/* Define to enable GLUT joystick support (limited to 3 axes) */
#undef ENABLE_GLUT_JOYSTICK
/* Define to enable plib joystick support (recommended) */
#undef ENABLE_PLIB_JOYSTICK
/* Define to eliminate all trace of debugging messages such as for a
release build */
#undef FG_NDEBUG
/* Define to include Oliver's networking support */
#undef FG_NETWORK_OLK
/* Define to avoid Christian's new weather code */
#undef FG_OLD_WEATHER
/* Define if we are building FGFS (should always be defined) */
#undef FGFS
/* Define to enable 3dfx/glide render in a window hack under unix.
This probably won't work under windows. */
#undef XMESA
#undef FX
/* Define to the type of elements in the array set by `getgroups'.
Usually this is either `int' or `gid_t'. */
#undef GETGROUPS_T
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
#undef GETLOADAVG_PRIVILEGED
/* Define if the `getpgrp' function takes no argument. */
#undef GETPGRP_VOID
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
/* Define if you have alloca, as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* Define if you external variables daylight. */
#undef HAVE_DAYLIGHT
/* Define if you don't have vprintf but do have _doprnt. */
#undef HAVE_DOPRNT
/* Define if your system has a working fnmatch function. */
#undef HAVE_FNMATCH
/* Define if your system has its own `getloadavg' function. */
#undef HAVE_GETLOADAVG
/* Define if you have getrusage() */
#undef HAVE_GETRUSAGE
/* Define if you have the getmntent function. */
#undef HAVE_GETMNTENT
/* Define if you have the gpc library and headers installed. */
#undef HAVE_GPC_H
/* Define if the `long double' type works. */
#undef HAVE_LONG_DOUBLE
/* Define if you support file names longer than 14 characters. */
#undef HAVE_LONG_FILE_NAMES
/* Define if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define if system calls automatically restart after interruption
by a signal. */
#undef HAVE_RESTARTABLE_SYSCALLS
/* Define if you have rint() which rounds to closest int but returns
result as a double data type. */
#undef HAVE_RINT
/* Define if your struct stat has st_blksize. */
#undef HAVE_ST_BLKSIZE
/* Define if your struct stat has st_blocks. */
#undef HAVE_ST_BLOCKS
/* Define if you have the strcoll function and it is properly defined. */
#undef HAVE_STRCOLL
/* Define if your struct stat has st_rdev. */
#undef HAVE_ST_RDEV
/* Define if you have the stdint.h include. */
#undef HAVE_STDINT_H
/* Define if you have the strftime function. */
#undef HAVE_STRFTIME
/* Define if you have <sys/param.h> */
#undef HAVE_SYS_PARAM_H
/* Define if you have <sys/stat.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_STAT_H
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define if you have timegm() */
#undef HAVE_TIMEGM
/* Define if you external variables timezone. */
#undef HAVE_TIMEZONE
/* Define if your struct tm has tm_zone. */
#undef HAVE_TM_ZONE
/* Define if you don't have tm_zone but do have the external array
tzname. */
#undef HAVE_TZNAME
/* Define if you have <unistd.h>. */
#undef HAVE_UNISTD_H
/* Define if utime(file, NULL) sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL
/* Define if you have <vfork.h>. */
#undef HAVE_VFORK_H
/* Define if you have the vprintf function. */
#undef HAVE_VPRINTF
/* Define if you have the wait3 system call. */
#undef HAVE_WAIT3
/* Define as __inline if that's what the C compiler calls it. */
#undef inline
/* Define if int is 16 bits instead of 32. */
#undef INT_16_BITS
/* Define if long int is 64 bits. */
#undef LONG_64_BITS
/* Define if major, minor, and makedev are declared in <mkdev.h>. */
#undef MAJOR_IN_MKDEV
/* Define if major, minor, and makedev are declared in <sysmacros.h>. */
#undef MAJOR_IN_SYSMACROS
/* Define if on MINIX. */
#undef _MINIX
/* Define to `int' if <sys/types.h> doesn't define. */
#undef mode_t
/* Define if you don't have <dirent.h>, but have <ndir.h>. */
#undef NDIR
/* Define if you have <memory.h>, and <string.h> doesn't declare the
mem* functions. */
#undef NEED_MEMORY_H
/* Define if your struct nlist has an n_un member. */
#undef NLIST_NAME_UNION
/* Define if you have <nlist.h>. */
#undef NLIST_STRUCT
/* Define if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
/* Define to `long' if <sys/types.h> doesn't define. */
#undef off_t
/* Define to package name */
#undef PACKAGE
/* Define to `int' if <sys/types.h> doesn't define. */
#undef pid_t
/* Define if the system does not provide POSIX.1 features except
with this defined. */
#undef _POSIX_1_SOURCE
/* Define if you need to in order for stat and other things to work. */
#undef _POSIX_SOURCE
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define if the `setpgrp' function takes no argument. */
#undef SETPGRP_VOID
/* Define if the setvbuf function takes the buffering type as its second
argument and the buffer pointer as the third, as on System V
before release 3. */
#undef SETVBUF_REVERSED
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
#undef STAT_MACROS_BROKEN
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define on System V Release 4. */
#undef SVR4
/* Define if you don't have <dirent.h>, but have <sys/dir.h>. */
#undef SYSDIR
/* Define if you don't have <dirent.h>, but have <sys/ndir.h>. */
#undef SYSNDIR
/* Define if `sys_siglist' is declared by <signal.h>. */
#undef SYS_SIGLIST_DECLARED
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define if your <sys/time.h> declares struct tm. */
#undef TM_IN_SYS_TIME
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
/* Define for Encore UMAX. */
#undef UMAX
/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
instead of <sys/cpustats.h>. */
#undef UMAX4_3
/* Define if you do not have <strings.h>, index, bzero, etc.. */
#undef USG
/* Define to version number */
#undef VERSION
/* Define vfork as fork if vfork does not work. */
#undef vfork
/* Define if the closedir function returns void instead of int. */
#undef VOID_CLOSEDIR
/* Define if compiling on a Winbloze (95, NT, etc.) platform */
#undef WIN32
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
/* Define if the X Window System is missing or not being used. */
#undef X_DISPLAY_MISSING
/* Define if lex declares yytext as a char * by default, not a char[]. */
#undef YYTEXT_POINTER
/* Leave that blank line there!! Autoheader needs it.
If you're adding to this file, keep in mind:
The entries are in sort -df order: alphabetical, case insensitive,
ignoring punctuation (such as underscores). */

View File

@@ -102,7 +102,7 @@ for exdir in $exdirs ; do
mylibdir="${exdir}/lib${subexdir}"
wi_EXTRA_LDIR($mylibdir)
progdir="${exdir}/bin${subexdirr}"
progdir="${exdir}/bin${subexdir}"
wi_EXTRA_PDIR($progdir)
fi
done

View File

@@ -1,40 +1,39 @@
type = StaticLibrary,Multithreaded,
exclude_dir = threads
include_path = .
include_path = ..
include_path = .\SimGear
#include_path = \usr\include
include_path = .\SimGear\metakit-2.4.3\include
include_path = ..\SimGear\zlib-1.1.4
define = HAVE_CONFIG_H
#add_project = .\SimGear\simgear\metakit\win\msvc60\mklib.dsp
add_project = .\SimGear\metakit-2.4.3\win\msvc60\mklib.dsp,mklib
add_project = .\SimGear\zlib.dsp,zlib
# Rule to create simgear_config.h
add_source_file = \
# Begin Source File\
add_source_file = SOURCE=.\simgear\simgear_config.h.vc5\
\
SOURCE = .\simgear\simgear_config.h.vc5\
\
!IF "$(CFG)" == "FlightGear - Win32 Release"\
!IF "$(CFG)" == "SimGear - Win32 Release"\
\
# Begin Custom Build - Creating config.h\
InputPath=.\simgear\simgear_config.h.vc5\
\
".\simgear\simgear_config.h": $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\
".\simgear\simgear_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\
copy .\simgear\simgear_config.h.vc5 .\simgear\simgear_config.h\
\
# End Custom Build\
\
!ELSEIF "$(CFG)" == "FlightGear - Win32 Debug"\
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"\
\
# Begin Custom Build - Creating config.h\
InputPath=.\simgear\simgear_config.h.vc5\
\
".\simgear\simgear_config.h": $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\
".\simgear\simgear_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\
copy .\simgear\simgear_config.h.vc5 .\simgear\simgear_config.h\
\
# End Custom Build\
\
!ENDIF\
\
# End Source File

View File

@@ -2,45 +2,40 @@
OSTYPE=`uname -s`
MACHINE=`uname -m`
AUTO_MAKE_VERSION=`automake --version | head -1 | awk '{print $4}' | sed -e 's/\-p[0-9]$//' | sed -e 's/\.//'`
AUTO_MAKE_VERSION=`automake --version | head -1 | awk '{print $4}' | sed -e 's/\.\([0-9]*\).*/\1/'`
if test $AUTO_MAKE_VERSION -lt 15; then
echo ""
echo "You need to upgrade to automake version 1.5 or greater."
echo "Most distributions have packages available to install or you can"
echo "find the source for the most recent version at"
echo "ftp://ftp.gnu.org/gnu/automake"
exit 1
fi
echo "Host info: $OSTYPE $MACHINE"
echo -n " automake: `automake --version | head -1 | awk '{print $4}'`"
echo " ($AUTO_MAKE_VERSION)"
echo ""
ACLOCAL_OPTS=""
if [ $AUTO_MAKE_VERSION -ge 14 ]; then
if [ $OSTYPE = "IRIX" -o $OSTYPE = "IRIX64" ]; then echo " -I ."
ACLOCAL_OPTS="-I ."
fi
fi
echo "Running aclocal $ACLOCAL_OPTS"
aclocal $ACLOCAL_OPTS
echo "Running aclocal"
aclocal
echo "Running autoheader"
autoheader
if [ ! -e simgear/simgear_config.h.in ]; then
echo "ERROR: autoheader didn't create simgear/simgear_config.h.in!"
exit 1
fi
echo -n "Running automake"
if [ $OSTYPE = "IRIX" -o $OSTYPE = "IRIX64" ]; then
echo " --add-missing --include-deps"
automake --add-missing --include-deps
else
echo " --add-missing"
automake --add-missing
fi
echo "Running automake --add-missing"
automake --add-missing
echo "Running autoconf"
autoconf
# fixup Makefiles for Irix
if test "$OSTYPE" = "IRIX" -o "$OSTYPE" = "IRIX64"; then
echo "Fixing Makefiles for Irix"
for n in `find . -name Makefile.in`; do \
mv -f $n $n.ar-new; \
sed 's/$(AR) cru /$(AR) -o /g' $n.ar-new > $n; \
rm -f $n.ar-new; \
done;
if [ ! -e configure ]; then
echo "ERROR: configure was not created!"
exit 1
fi
echo ""

View File

@@ -3,13 +3,14 @@ dnl working configure script.
dnl
dnl $Id$
AC_INIT(simgear/bucket/newbucket.cxx)
AC_INIT
AC_CONFIG_SRCDIR([simgear/bucket/newbucket.cxx])
# Require at least automake 2.13
AC_PREREQ(2.13)
# Require at least automake 2.52
AC_PREREQ(2.52)
dnl Initialize the automake stuff
AM_INIT_AUTOMAKE(SimGear, 0.0.18pre1)
AM_INIT_AUTOMAKE(SimGear, 0.3.0)
dnl Specify KAI C++ compiler and flags.
dnl Borrowed with slight modification from blitz distribution.
@@ -37,14 +38,20 @@ AC_PROG_RANLIB
AC_PROG_INSTALL
AC_PROG_LN_S
# Used on the Irix platform
AR="ar"
ARFLAGS="cru"
OS=`uname -s`
if test "$OS" = "IRIX" -o "$OS" = "IRIX64"; then
if test "$CXX" = "CC"; then
AR="CC -ar"
AC_SUBST(AR)
ARFLAGS="-o"
fi
fi
AC_SUBST(AR)
AC_SUBST(ARFLAGS)
if echo $includedir | egrep "simgear$" > /dev/null; then
echo "includedir is" $includedir "libdir is" $libdir
@@ -53,25 +60,11 @@ else
echo "includedir changed to" $includedir "libdir is" $libdir
fi
# Determine version of automake ... important because of
# incompatibilities between versions
AUTO_MAKE_VERSION=`automake --version | head -1 | awk '{print $4}' | sed -e 's/\-p[[0-9]]$//' | sed -e 's/\.//'`
AM_CONDITIONAL(ANCIENT_AUTOMAKE, test $AUTO_MAKE_VERSION -lt 14)
AM_CONDITIONAL(OLD_AUTOMAKE, test $AUTO_MAKE_VERSION -lt 15)
# set logging default value
# with_logging=yes
AC_ARG_WITH(logging, [ --with-logging Include logging output (default)])
if test "x$with_logging" = "xno" ; then
AC_DEFINE(FG_NDEBUG)
fi
dnl specify if we are building with "electric fence"
AC_ARG_WITH(efence, [ --with-efence Specify if we are building with "electric-fence"])
if test "x$with_efence" = "xyes" ; then
echo "Building with efence"
LIBS="$LIBS -lefence"
AC_DEFINE([FG_NDEBUG], 1, [Define for no logging output])
fi
# Specify if we want to build with Norman's jpeg image server support.
@@ -120,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/local/plib /usr/X11R6"
EXTRA_DIRS="/usr/X11R6"
if test -d /opt/X11R6 ; then
EXTRA_DIRS="$EXTRA_DIRS /opt/X11R6"
@@ -136,9 +129,6 @@ dnl enough. AM_CONDITIONALS are then referenced to conditionally
dnl build a Makefile.in from a Makefile.am which lets us define custom
dnl includes, compile alternative source files, etc.
dnl Enable serial support on Unix type systems
AM_CONDITIONAL(ENABLE_UNIX_SERIAL, true)
dnl X11 might be installed on Mac OS X, don't want to use it if it is.
if test "x$HOSTTYPE" != "xmacintosh" ; then
dnl Check for X11 (fancy)
@@ -177,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"
@@ -200,8 +192,8 @@ elif test "x$ac_cv_header_windows_h" != "xyes" ; then
if test "x$ac_cv_lib_MesaGL_glNewList" = "xyes" ; then
AC_CHECK_HEADER(GL/fxmesa.h)
if test "x$ac_cv_header_GL_fxmesa_h" = "xyes"; then
AC_DEFINE( XMESA )
AC_DEFINE( FX )
AC_DEFINE([XMESA], 1, [Define for fxmesa])
AC_DEFINE([FX], 1, [Define for fxmesa])
fi
fi
@@ -223,10 +215,8 @@ else
dnl Win32 libs
echo Win32 specific hacks...
AC_DEFINE(WIN32)
dnl force a failed check since we will be building under windoze
AM_CONDITIONAL(ENABLE_XMESA_FX, test "no" = "yes")
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"
@@ -262,7 +252,9 @@ fi
if test "x$ac_cv_lib_glut_glutGameModeString" = "xno"; then
echo
echo "Your version of glut doesn't support game mode."
echo "You need to fetch and install the latest version of glut from:"
echo "You need to install the latest version of glut. If your"
echo "distribution doesn't provide a newer version, you can get the source"
echo "code from:"
echo
echo " http://reality.sgi.com/opengl/glut3/glut3.html"
exit 1
@@ -276,12 +268,17 @@ AC_SUBST(opengl_LIBS)
AM_CONDITIONAL(HAVE_XWINDOWS, test "x$ac_cv_lib_X11_XCreateWindow" = "xyes" )
# The following are C++ items that need to be tested for with the c++
# compiler
AC_LANG_PUSH(C++)
dnl Check for "plib" without which we cannot go on
AC_CHECK_HEADER(plib/pu.h)
if test "x$ac_cv_header_plib_pu_h" != "xyes"; then
AC_CHECK_HEADER(plib/ul.h)
if test "x$ac_cv_header_plib_ul_h" != "xyes"; then
echo
echo "You *must* have the plib library installed on your system to build"
echo "the FGFS simulator!"
echo "SimGear!"
echo
echo "Please see README.plib for more details."
echo
@@ -289,6 +286,29 @@ if test "x$ac_cv_header_plib_pu_h" != "xyes"; then
exit
fi
AC_MSG_CHECKING([for plib 1.6.0 or newer])
AC_TRY_RUN([
#include <plib/ul.h>
#define MIN_PLIB_VERSION 160
int main() {
int major, minor, micro;
if ( PLIB_VERSION < MIN_PLIB_VERSION ) {
return -1;
}
return 0;
}
],
AC_MSG_RESULT(yes),
[AC_MSG_RESULT(wrong version);
AC_MSG_ERROR([Install plib 1.6.0 or later first...])],
AC_MSG_RESULT(yes)
)
dnl Check for system installed metakit
AC_CHECK_HEADER(mk4.h)
if test "x$ac_cv_header_mk4_h" != "xyes"; then
@@ -298,6 +318,7 @@ if test "x$ac_cv_header_mk4_h" != "xyes"; then
exit
fi
AC_LANG_POP
dnl Specify if we want logging (testing build) or not (release build)
@@ -317,7 +338,7 @@ AC_CHECK_HEADERS( \
sys/stat.h sys/time.h sys/timeb.h unistd.h windows.h winbase.h values.h )
if test "x$ac_cv_header_stdint_h" = "xyes"; then
AC_DEFINE( HAVE_STDINT_H )
AC_DEFINE([HAVE_STDINT_H], 1, [Define if stdint.h exists])
fi
dnl Checks for typedefs, structures, and compiler characteristics.
@@ -330,11 +351,11 @@ dnl Checks for library functions.
AC_TYPE_SIGNAL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS( ftime gettimeofday timegm memcpy bcopy mktime strstr rand \
random setitimer getitimer signal GetLocalTime rint getrusage )
random drand48 setitimer getitimer signal GetLocalTime rint getrusage )
AM_CONFIG_HEADER(simgear/simgear_config.h)
AC_OUTPUT( \
AC_CONFIG_FILES([ \
Makefile \
SimGear.spec \
src-libs/Makefile \
@@ -352,13 +373,14 @@ AC_OUTPUT( \
simgear/screen/Makefile \
simgear/serial/Makefile \
simgear/sky/Makefile \
simgear/sky/clouds3d/Makefile \
simgear/threads/Makefile \
simgear/timing/Makefile \
simgear/xgl/Makefile \
simgear/xml/Makefile \
)
])
AC_OUTPUT
# AC_OUTPUT_COMMANDS([])
echo ""
echo "Configure Summary"
@@ -372,12 +394,6 @@ else
echo "Debug messages: yes"
fi
if test "x$with_efence" != "x"; then
echo "Electric fence: $with_efence"
else
echo "Electric fence: no"
fi
echo -n "Automake version: ($AUTO_MAKE_VERSION) "
automake --version | head -1

View File

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

View File

@@ -1,6 +1,8 @@
Makefile
Makefile.in
simgear_config.h
simgear_config.h.in
stamp-h
stamp-h.in
stamp-h1
version.h

View File

@@ -1,9 +1,3 @@
if ENABLE_UNIX_SERIAL
SERIAL_DIRS = serial
else
SERIAL_DIRS =
endif
if HAVE_THREADS
SGTHREAD_DIR = threads
else
@@ -30,9 +24,10 @@ SUBDIRS = \
$(METAR_DIRS) \
route \
screen \
$(SERIAL_DIRS) \
serial \
sky \
$(SGTHREAD_DIR) \
timing \
xgl
DIST_SUBDIRS = $(SUBDIRS)

View File

@@ -14,8 +14,4 @@ libsgbucket_a_SOURCES = newbucket.cxx
# $(top_builddir)/bucket/libsgbucket.a \
# $(top_builddir)/misc/libsgmisc.a
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif

View File

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

View File

@@ -71,6 +71,14 @@
#ifndef _SG_COMPILER_H
#define _SG_COMPILER_H
/*
* Helper macro SG_STRINGIZE:
* Converts the parameter X to a string after macro replacement
* on X has been performed.
*/
#define SG_STRINGIZE(X) SG_DO_STRINGIZE(X)
#define SG_DO_STRINGIZE(X) #X
#ifdef __GNUC__
# if __GNUC__ == 2
# if __GNUC_MINOR__ < 8
@@ -133,15 +141,18 @@
# define STL_STDEXCEPT <stdexcept>
# define STL_STRING <string>
# define STL_STRSTREAM <strstream>
# else
# error Time to upgrade. GNU compilers < 2.7 not supported
# endif
#endif
# define SG_COMPILER_STR "GNU C++ version " SG_STRINGIZE(__GNUC__) "." SG_STRINGIZE(__GNUC_MINOR__)
#endif // __GNUC__
#if defined( __MINGW32__ )
# define bcopy(from, to, n) memcpy(to, from, n)
# define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
# define snprintf _snprintf
#endif
/* KAI C++ */
@@ -162,7 +173,10 @@
# define STL_STDEXCEPT <stdexcept>
# define STL_STRING <string>
# define STL_STRSTREAM <strstream>
#endif
# define SG_COMPILER_STR "Kai C++ version " SG_STRINGIZE(__KCC_VERSION)
#endif // __KCC
//
// Metrowerks
@@ -193,7 +207,10 @@
// -dw- currently used glut has no game mode stuff
# define GLUT_WRONG_VERSION
#endif
# define SG_COMPILER_STR "Metrowerks CodeWarrior C++ version " SG_STRINGIZE(__MWERKS__)
#endif // __MWERKS__
//
// Microsoft compilers.
@@ -218,13 +235,19 @@
# define STL_STRING <string>
# define STL_STRSTREAM <strstream>
# define snprintf _snprintf
# pragma warning(disable: 4786) // identifier was truncated to '255' characters
# pragma warning(disable: 4244) // conversion from double to float
# pragma warning(disable: 4305) //
# else
# error What version of MSVC++ is this?
# endif
#endif
# define SG_COMPILER_STR "Microsoft Visual C++ version " SG_STRINGIZE(_MSC_VER)
#endif // _MSC_VER
#ifdef __BORLANDC__
# if defined(HAVE_SGI_STL_PORT)
@@ -256,6 +279,8 @@
# define SG_NAMESPACES
// # define SG_HAVE_STD
# define SG_COMPILER_STR "Borland C++ version " SG_STRINGIZE(__BORLANDC__)
#endif // __BORLANDC__
//
@@ -296,6 +321,8 @@
#pragma set woff 1682,3303
#endif
# define SG_COMPILER_STR "SGI Irix compiler version " SG_STRINGIZE(_COMPILER_VERSION)
#endif // Native SGI compilers
@@ -310,12 +337,15 @@
# else
extern void *memmove(void *, const void *, size_t);
# endif // __cplusplus
# define SG_COMPILER_STR "Sun compiler version " SG_STRINGIZE(__SUNPRO_CC)
#endif // sun
//
// Intel C++ Compiler
//
#if defined(__ICC)
#if defined(__ICC) || defined (__ECC)
# define SG_NAMESPACES
# define SG_HAVE_STD
# define SG_HAVE_STREAMBUF
@@ -331,6 +361,9 @@
# define STL_STDEXCEPT <stdexcept>
# define STL_STRING <string>
# define STL_STRSTREAM <strstream>
# define SG_COMPILER_STR "Intel C++ version " SG_STRINGIZE(__ICC)
#endif // __ICC
//

View File

@@ -8,8 +8,4 @@ include_HEADERS = debug_types.h logstream.hxx
libsgdebug_a_SOURCES = logstream.cxx
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif

View File

@@ -23,6 +23,8 @@
#include "logstream.hxx"
logstream *global_logstream = NULL;
bool logbuf::logging_enabled = true;
sgDebugClass logbuf::logClass = SG_NONE;
sgDebugPriority logbuf::logPriority = SG_INFO;

View File

@@ -256,6 +256,7 @@ logstream::operator<< ( const loglevel& l )
return *this;
}
extern logstream *global_logstream;
/**
* \relates logstream
@@ -267,8 +268,22 @@ logstream::operator<< ( const loglevel& l )
inline logstream&
sglog()
{
static logstream logstrm( cerr );
return logstrm;
if (global_logstream == NULL) {
#ifdef __APPLE__
/**
* There appears to be a bug in the C++ runtime in Mac OS X that
* will crash if certain funtions are called (in this case
* cerr.rdbuf()) during static initialization of a class. This
* print statement is hack to kick the library in the pants so it
* won't crash when cerr.rdbuf() is first called -DW
**/
cout << "Using Mac OS X hack for initializing C++ stdio..." << endl;
#endif
global_logstream = new logstream (cerr);
}
return *global_logstream;
}

View File

@@ -1,16 +1,32 @@
#include <string>
#include "Debug/logstream.hxx"
class Test {
public:
Test() {
//cout << "Cout seems to work" << endl;
//cerr << "Cerr seems to work" << endl;
sglog().setLogLevels( SG_ALL, SG_INFO );
SG_LOG(SG_EVENT, SG_INFO, "Test::Test" << "foo");
}
};
Test test;
int
main( int argc, char* argv[] )
{
fglog().setLogLevels( SG_ALL, SG_INFO );
sglog().setLogLevels( SG_ALL, SG_INFO );
SG_LOG( FG_TERRAIN, FG_BULK, "terrain::bulk" ); // shouldnt appear
SG_LOG( FG_TERRAIN, SG_DEBUG, "terrain::debug" ); // shouldnt appear
SG_LOG( FG_TERRAIN, SG_INFO, "terrain::info" );
SG_LOG( FG_TERRAIN, FG_WARN, "terrain::warn" );
SG_LOG( FG_TERRAIN, SG_ALERT, "terrain::alert" );
//SG_LOG( FG_TERRAIN, FG_BULK, "terrain::bulk" ); // shouldnt appear
//SG_LOG( FG_TERRAIN, SG_DEBUG, "terrain::debug" ); // shouldnt appear
//SG_LOG( FG_TERRAIN, SG_INFO, "terrain::info" );
//SG_LOG( FG_TERRAIN, FG_WARN, "terrain::warn" );
//SG_LOG( FG_TERRAIN, SG_ALERT, "terrain::alert" );
int i = 12345;
long l = 54321L;

View File

@@ -31,8 +31,4 @@ libsgephem_a_SOURCES = \
uranus.cxx \
venus.cxx
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif

View File

@@ -158,22 +158,112 @@ double CelestialBody::sgCalcEccAnom(double M, double e)
return eccAnom;
}
/*****************************************************************************
* inline CelestialBody::CelestialBody
* public constructor for a generic celestialBody object.
* initializes the 6 primary orbital elements. The elements are:
* N: longitude of the ascending node
* i: inclination to the ecliptic
* w: argument of perihelion
* a: semi-major axis, or mean distance from the sun
* e: eccenticity
* M: mean anomaly
* Each orbital element consists of a constant part and a variable part that
* gradually changes over time.
*
* Argumetns:
* the 13 arguments to the constructor constitute the first, constant
* ([NiwaeM]f) and the second variable ([NiwaeM]s) part of the orbital
* elements. The 13th argument is the current time. Note that the inclination
* is written with a capital (If, Is), because 'if' is a reserved word in the
* C/C++ programming language.
***************************************************************************/
CelestialBody::CelestialBody(double Nf, double Ns,
double If, double Is,
double wf, double ws,
double af, double as,
double ef, double es,
double Mf, double Ms, double mjd)
{
NFirst = Nf; NSec = Ns;
iFirst = If; iSec = Is;
wFirst = wf; wSec = ws;
aFirst = af; aSec = as;
eFirst = ef; eSec = es;
MFirst = Mf; MSec = Ms;
updateOrbElements(mjd);
}
CelestialBody::CelestialBody(double Nf, double Ns,
double If, double Is,
double wf, double ws,
double af, double as,
double ef, double es,
double Mf, double Ms)
{
NFirst = Nf; NSec = Ns;
iFirst = If; iSec = Is;
wFirst = wf; wSec = ws;
aFirst = af; aSec = as;
eFirst = ef; eSec = es;
MFirst = Mf; MSec = Ms;
}
/****************************************************************************
* inline void CelestialBody::updateOrbElements(double mjd)
* given the current time, this private member calculates the actual
* orbital elements
*
* Arguments: double mjd: the current modified julian date:
*
* return value: none
***************************************************************************/
void CelestialBody::updateOrbElements(double mjd)
{
double actTime = sgCalcActTime(mjd);
M = SGD_DEGREES_TO_RADIANS * (MFirst + (MSec * actTime));
w = SGD_DEGREES_TO_RADIANS * (wFirst + (wSec * actTime));
N = SGD_DEGREES_TO_RADIANS * (NFirst + (NSec * actTime));
i = SGD_DEGREES_TO_RADIANS * (iFirst + (iSec * actTime));
e = eFirst + (eSec * actTime);
a = aFirst + (aSec * actTime);
}
/*****************************************************************************
* inline double CelestialBody::sgCalcActTime(double mjd)
* this private member function returns the offset in days from the epoch for
* wich the orbital elements are calculated (Jan, 1st, 2000).
*
* Argument: the current time
*
* return value: the (fractional) number of days until Jan 1, 2000.
****************************************************************************/
double CelestialBody::sgCalcActTime(double mjd)
{
return (mjd - 36523.5);
}
/*****************************************************************************
* inline void CelestialBody::getPos(double* ra, double* dec)
* gives public access to Right Ascension and declination
*
****************************************************************************/
void CelestialBody::getPos(double* ra, double* dec)
{
*ra = rightAscension;
*dec = declination;
}
/*****************************************************************************
* inline void CelestialBody::getPos(double* ra, double* dec, double* magnitude
* gives public acces to the current Right ascension, declination, and
* magnitude
****************************************************************************/
void CelestialBody::getPos(double* ra, double* dec, double* magn)
{
*ra = rightAscension;
*dec = declination;
*magn = magnitude;
}

View File

@@ -87,113 +87,6 @@ public:
void updatePosition(double mjd, Star *ourSun);
};
/*****************************************************************************
* inline CelestialBody::CelestialBody
* public constructor for a generic celestialBody object.
* initializes the 6 primary orbital elements. The elements are:
* N: longitude of the ascending node
* i: inclination to the ecliptic
* w: argument of perihelion
* a: semi-major axis, or mean distance from the sun
* e: eccenticity
* M: mean anomaly
* Each orbital element consists of a constant part and a variable part that
* gradually changes over time.
*
* Argumetns:
* the 13 arguments to the constructor constitute the first, constant
* ([NiwaeM]f) and the second variable ([NiwaeM]s) part of the orbital
* elements. The 13th argument is the current time. Note that the inclination
* is written with a capital (If, Is), because 'if' is a reserved word in the
* C/C++ programming language.
***************************************************************************/
inline CelestialBody::CelestialBody(double Nf, double Ns,
double If, double Is,
double wf, double ws,
double af, double as,
double ef, double es,
double Mf, double Ms, double mjd)
{
NFirst = Nf; NSec = Ns;
iFirst = If; iSec = Is;
wFirst = wf; wSec = ws;
aFirst = af; aSec = as;
eFirst = ef; eSec = es;
MFirst = Mf; MSec = Ms;
updateOrbElements(mjd);
}
inline CelestialBody::CelestialBody(double Nf, double Ns,
double If, double Is,
double wf, double ws,
double af, double as,
double ef, double es,
double Mf, double Ms)
{
NFirst = Nf; NSec = Ns;
iFirst = If; iSec = Is;
wFirst = wf; wSec = ws;
aFirst = af; aSec = as;
eFirst = ef; eSec = es;
MFirst = Mf; MSec = Ms;
}
/****************************************************************************
* inline void CelestialBody::updateOrbElements(double mjd)
* given the current time, this private member calculates the actual
* orbital elements
*
* Arguments: double mjd: the current modified julian date:
*
* return value: none
***************************************************************************/
inline void CelestialBody::updateOrbElements(double mjd)
{
double actTime = sgCalcActTime(mjd);
M = SGD_DEGREES_TO_RADIANS * (MFirst + (MSec * actTime));
w = SGD_DEGREES_TO_RADIANS * (wFirst + (wSec * actTime));
N = SGD_DEGREES_TO_RADIANS * (NFirst + (NSec * actTime));
i = SGD_DEGREES_TO_RADIANS * (iFirst + (iSec * actTime));
e = eFirst + (eSec * actTime);
a = aFirst + (aSec * actTime);
}
/*****************************************************************************
* inline double CelestialBody::sgCalcActTime(double mjd)
* this private member function returns the offset in days from the epoch for
* wich the orbital elements are calculated (Jan, 1st, 2000).
*
* Argument: the current time
*
* return value: the (fractional) number of days until Jan 1, 2000.
****************************************************************************/
inline double CelestialBody::sgCalcActTime(double mjd)
{
return (mjd - 36523.5);
}
/*****************************************************************************
* inline void CelestialBody::getPos(double* ra, double* dec)
* gives public access to Right Ascension and declination
*
****************************************************************************/
inline void CelestialBody::getPos(double* ra, double* dec)
{
*ra = rightAscension;
*dec = declination;
}
/*****************************************************************************
* inline void CelestialBody::getPos(double* ra, double* dec, double* magnitude
* gives public acces to the current Right ascension, declination, and
* magnitude
****************************************************************************/
inline void CelestialBody::getPos(double* ra, double* dec, double* magn)
{
*ra = rightAscension;
*dec = declination;
*magn = magnitude;
}
inline double CelestialBody::getRightAscension() { return rightAscension; }
inline double CelestialBody::getDeclination() { return declination; }
inline double CelestialBody::getMagnitude() { return magnitude; }
@@ -210,14 +103,3 @@ inline double CelestialBody::getLat()
#endif // _CELESTIALBODY_H_

View File

@@ -4,3 +4,5 @@ Makefile.in
decode_binobj
lowtest
socktest
tcp_client
tcp_server

View File

@@ -20,11 +20,7 @@ libsgio_a_SOURCES = \
sg_socket.cxx \
sg_socket_udp.cxx
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif
if IS_MINGW
NETWORK_LIB = -lwsock32
@@ -32,7 +28,27 @@ else
NETWORK_LIB =
endif
noinst_PROGRAMS = decode_binobj socktest lowtest
noinst_PROGRAMS = decode_binobj socktest lowtest tcp_server tcp_client
tcp_server_SOURCES = tcp_server.cxx
tcp_server_LDADD = \
$(top_builddir)/simgear/io/libsgio.a \
$(top_builddir)/simgear/debug/libsgdebug.a \
$(top_builddir)/simgear/bucket/libsgbucket.a \
$(top_builddir)/simgear/misc/libsgmisc.a \
$(top_builddir)/simgear/xml/libsgxml.a \
-lplibnet -lplibul -lz $(NETWORK_LIB)
tcp_client_SOURCES = tcp_client.cxx
tcp_client_LDADD = \
$(top_builddir)/simgear/io/libsgio.a \
$(top_builddir)/simgear/debug/libsgdebug.a \
$(top_builddir)/simgear/bucket/libsgbucket.a \
$(top_builddir)/simgear/misc/libsgmisc.a \
$(top_builddir)/simgear/xml/libsgxml.a \
-lplibnet -lplibul -lz $(NETWORK_LIB)
socktest_SOURCES = socktest.cxx
@@ -42,7 +58,7 @@ socktest_LDADD = \
$(top_builddir)/simgear/debug/libsgdebug.a \
$(top_builddir)/simgear/misc/libsgmisc.a \
$(top_builddir)/simgear/xml/libsgxml.a \
-lz
-lplibnet -lplibul -lz $(NETWORK_LIB)
lowtest_SOURCES = lowtest.cxx
@@ -57,4 +73,4 @@ decode_binobj_LDADD = \
$(top_builddir)/simgear/misc/libsgmisc.a \
$(top_builddir)/simgear/debug/libsgdebug.a \
$(top_builddir)/simgear/xml/libsgxml.a \
$(NETWORK_LIB) -lz
-lz

View File

@@ -22,8 +22,6 @@
#include "iochannel.hxx"
// #include "garmin.hxx"
// #include "nmea.hxx"
// constructor

View File

@@ -22,6 +22,10 @@
//
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <simgear/compiler.h>
#include <stdio.h>
@@ -316,7 +320,7 @@ bool SGBinObject::read_bin( const string& file ) {
fans_c.clear();
fans_tc.clear();
fan_materials.clear();
gzFile fp;
if ( (fp = gzopen( file.c_str(), "rb" )) == NULL ) {
string filegz = file + ".gz";
@@ -347,10 +351,11 @@ bool SGBinObject::read_bin( const string& file ) {
}
// read creation time
time_t calendar_time;
sgReadLong( fp, &calendar_time );
unsigned int foo_calendar_time;
sgReadUInt( fp, &foo_calendar_time );
#if 0
time_t calendar_time = foo_calendar_time;
// The following code has a global effect on the host application
// and can screws up the time elsewhere. It should be avoided
// unless you need this for debugging in which case you should
@@ -439,15 +444,14 @@ bool SGBinObject::read_bin( const string& file ) {
sgReadBytes( fp, nbytes, ptr );
int count = nbytes / (sizeof(float) * 3);
float *fptr = (float *)ptr;
wgs84_nodes.reserve( count );
for ( k = 0; k < count; ++k ) {
if ( sgIsBigEndian() ) {
sgEndianSwap( (unsigned int *)&(fptr[0]) );
sgEndianSwap( (unsigned int *)&(fptr[1]) );
sgEndianSwap( (unsigned int *)&(fptr[2]) );
}
p = Point3D( fptr[0], fptr[1], fptr[2] );
// cout << "node = " << p << endl;
wgs84_nodes.push_back( p );
wgs84_nodes.push_back( Point3D(fptr[0], fptr[1], fptr[2]) );
fptr += 3;
}
}
@@ -473,6 +477,7 @@ bool SGBinObject::read_bin( const string& file ) {
sgReadBytes( fp, nbytes, ptr );
int count = nbytes / (sizeof(float) * 4);
float *fptr = (float *)ptr;
colors.reserve(count);
for ( k = 0; k < count; ++k ) {
if ( sgIsBigEndian() ) {
sgEndianSwap( (unsigned int *)&(fptr[0]) );
@@ -480,9 +485,7 @@ bool SGBinObject::read_bin( const string& file ) {
sgEndianSwap( (unsigned int *)&(fptr[2]) );
sgEndianSwap( (unsigned int *)&(fptr[3]) );
}
p = Point3D( fptr[0], fptr[1], fptr[2] );
// cout << "node = " << p << endl;
colors.push_back( p );
colors.push_back( Point3D( fptr[0], fptr[1], fptr[2] ) );
fptr += 4;
}
}
@@ -507,6 +510,7 @@ bool SGBinObject::read_bin( const string& file ) {
unsigned char *ptr = (unsigned char *)(buf.get_ptr());
sgReadBytes( fp, nbytes, ptr );
int count = nbytes / 3;
normals.reserve( count );
for ( k = 0; k < count; ++k ) {
sgdVec3 normal;
sgdSetVec3( normal,
@@ -515,9 +519,7 @@ bool SGBinObject::read_bin( const string& file ) {
(ptr[2]) / 127.5 - 1.0 );
sgdNormalizeVec3( normal );
p = Point3D( normal[0], normal[1], normal[2] );
// cout << "normal = " << p << endl;
normals.push_back( p );
normals.push_back(Point3D(normal[0], normal[1], normal[2]));
ptr += 3;
}
}
@@ -543,14 +545,13 @@ bool SGBinObject::read_bin( const string& file ) {
sgReadBytes( fp, nbytes, ptr );
int count = nbytes / (sizeof(float) * 2);
float *fptr = (float *)ptr;
texcoords.reserve(count);
for ( k = 0; k < count; ++k ) {
if ( sgIsBigEndian() ) {
sgEndianSwap( (unsigned int *)&(fptr[0]) );
sgEndianSwap( (unsigned int *)&(fptr[1]) );
}
p = Point3D( fptr[0], fptr[1], 0 );
// cout << "texcoord = " << p << endl;
texcoords.push_back( p );
texcoords.push_back( Point3D( fptr[0], fptr[1], 0 ) );
fptr += 2;
}
}

View File

@@ -125,67 +125,69 @@ public:
inline unsigned short get_version() const { return version; }
inline Point3D get_gbs_center() const { return gbs_center; }
inline void set_gbs_center( Point3D p ) { gbs_center = p; }
inline const Point3D& get_gbs_center() const { return gbs_center; }
inline void set_gbs_center( const Point3D& p ) { gbs_center = p; }
inline float get_gbs_radius() const { return gbs_radius; }
inline void set_gbs_radius( float r ) { gbs_radius = r; }
inline point_list get_wgs84_nodes() const { return wgs84_nodes; }
inline void set_wgs84_nodes( point_list n ) { wgs84_nodes = n; }
inline const point_list& get_wgs84_nodes() const { return wgs84_nodes; }
inline void set_wgs84_nodes( const point_list& n ) { wgs84_nodes = n; }
inline point_list get_colors() const { return colors; }
inline void set_colors( point_list c ) { colors = c; }
inline const point_list& get_colors() const { return colors; }
inline void set_colors( const point_list& c ) { colors = c; }
inline point_list get_normals() const { return normals; }
inline void set_normals( point_list n ) { normals = n; }
inline const point_list& get_normals() const { return normals; }
inline void set_normals( const point_list& n ) { normals = n; }
inline point_list get_texcoords() const { return texcoords; }
inline void set_texcoords( point_list t ) { texcoords = t; }
inline const point_list& get_texcoords() const { return texcoords; }
inline void set_texcoords( const point_list& t ) { texcoords = t; }
inline group_list get_pts_v() const { return pts_v; }
inline void set_pts_v( group_list g ) { pts_v = g; }
inline group_list get_pts_n() const { return pts_n; }
inline void set_pts_n( group_list g ) { pts_n = g; }
inline group_list get_pts_c() const { return pts_c; }
inline void set_pts_c( group_list g ) { pts_c = g; }
inline group_list get_pts_tc() const { return pts_tc; }
inline void set_pts_tc( group_list g ) { pts_tc = g; }
inline string_list get_pt_materials() const { return pt_materials; }
inline void set_pt_materials( string_list s ) { pt_materials = s; }
inline const group_list& get_pts_v() const { return pts_v; }
inline void set_pts_v( const group_list& g ) { pts_v = g; }
inline const group_list& get_pts_n() const { return pts_n; }
inline void set_pts_n( const group_list& g ) { pts_n = g; }
inline const group_list& get_pts_c() const { return pts_c; }
inline void set_pts_c( const group_list& g ) { pts_c = g; }
inline const group_list& get_pts_tc() const { return pts_tc; }
inline void set_pts_tc( const group_list& g ) { pts_tc = g; }
inline const string_list& get_pt_materials() const { return pt_materials; }
inline void set_pt_materials( const string_list& s ) { pt_materials = s; }
inline group_list get_tris_v() const { return tris_v; }
inline void set_tris_v( group_list g ) { tris_v = g; }
inline group_list get_tris_n() const { return tris_n; }
inline void set_tris_n( group_list g ) { tris_n = g; }
inline group_list get_tris_c() const { return tris_c; }
inline void set_tris_c( group_list g ) { tris_c = g; }
inline group_list get_tris_tc() const { return tris_tc; }
inline void set_tris_tc( group_list g ) { tris_tc = g; }
inline string_list get_tri_materials() const { return tri_materials; }
inline void set_tri_materials( string_list s ) { tri_materials = s; }
inline const group_list& get_tris_v() const { return tris_v; }
inline void set_tris_v( const group_list& g ) { tris_v = g; }
inline const group_list& get_tris_n() const { return tris_n; }
inline void set_tris_n( const group_list& g ) { tris_n = g; }
inline const group_list& get_tris_c() const { return tris_c; }
inline void set_tris_c( const group_list& g ) { tris_c = g; }
inline const group_list& get_tris_tc() const { return tris_tc; }
inline void set_tris_tc( const group_list& g ) { tris_tc = g; }
inline const string_list& get_tri_materials() const { return tri_materials; }
inline void set_tri_materials( const string_list& s ) { tri_materials = s; }
inline group_list get_strips_v() const { return strips_v; }
inline void set_strips_v( group_list g ) { strips_v = g; }
inline group_list get_strips_n() const { return strips_n; }
inline void set_strips_n( group_list g ) { strips_n = g; }
inline group_list get_strips_c() const { return strips_c; }
inline void set_strips_c( group_list g ) { strips_c = g; }
inline group_list get_strips_tc() const { return strips_tc; }
inline void set_strips_tc( group_list g ) { strips_tc = g; }
inline string_list get_strip_materials() const { return strip_materials; }
inline void set_strip_materials( string_list s ) { strip_materials = s; }
inline const group_list& get_strips_v() const { return strips_v; }
inline void set_strips_v( const group_list& g ) { strips_v = g; }
inline const group_list& get_strips_n() const { return strips_n; }
inline void set_strips_n( const group_list& g ) { strips_n = g; }
inline const group_list& get_strips_c() const { return strips_c; }
inline void set_strips_c( const group_list& g ) { strips_c = g; }
inline const group_list& get_strips_tc() const { return strips_tc; }
inline void set_strips_tc( const group_list& g ) { strips_tc = g; }
inline const string_list& get_strip_materials() const { return strip_materials; }
inline void set_strip_materials( const string_list& s ) { strip_materials = s; }
inline group_list get_fans_v() const { return fans_v; }
inline void set_fans_v( group_list g ) { fans_v = g; }
inline group_list get_fans_n() const { return fans_n; }
inline void set_fans_n( group_list g ) { fans_n = g; }
inline group_list get_fans_c() const { return fans_c; }
inline void set_fans_c( group_list g ) { fans_c = g; }
inline group_list get_fans_tc() const { return fans_tc; }
inline void set_fans_tc( group_list g ) { fans_tc = g; }
inline string_list get_fan_materials() const { return fan_materials; }
inline void set_fan_materials( string_list s ) { fan_materials = s; }
inline const group_list& get_fans_v() const { return fans_v; }
inline void set_fans_v( const group_list& g ) { fans_v = g; }
inline const group_list& get_fans_n() const { return fans_n; }
inline void set_fans_n( const group_list& g ) { fans_n = g; }
inline const group_list& get_fans_c() const { return fans_c; }
inline void set_fans_c( const group_list& g ) { fans_c = g; }
inline const group_list& get_fans_tc() const { return fans_tc; }
inline void set_fans_tc( const group_list& g ) { fans_tc = g; }
inline const string_list& get_fan_materials() const { return fan_materials; }
inline void set_fan_materials( const string_list& s ) { fan_materials = s; }
/**
* Read a binary file object and populate the provided structures.

View File

@@ -1,6 +1,7 @@
// sg_socket.cxx -- Socket I/O routines
//
// Written by Curtis Olson, started November 1999.
// Modified by Bernie Bright <bbright@bigpond.net.au>, May 2002.
//
// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org
//
@@ -23,16 +24,6 @@
#include <simgear/compiler.h>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
# include <sys/time.h> // select()
# include <sys/types.h> // socket(), bind(), select(), accept()
# include <sys/socket.h> // socket(), bind(), listen(), accept()
# include <netinet/in.h> // struct sockaddr_in
# include <netdb.h> // gethostbyname()
# include <unistd.h> // select(), fsync()/fdatasync(), fcntl()
# include <fcntl.h> // fcntl()
#endif
#if defined( sgi )
#include <strings.h>
#endif
@@ -41,25 +32,30 @@
#include "sg_socket.hxx"
bool SGSocket::init = false;
SGSocket::SGSocket( const string& host, const string& port,
SGSocket::SGSocket( const string& host, const string& port_,
const string& style ) :
hostname(host),
port_str(port),
save_len(0)
port_str(port_),
save_len(0),
client(0),
is_tcp(false),
is_server(false),
first_read(false)
{
#if defined(_MSC_VER) || defined(__MINGW32__)
if (!wsock_init && !wsastartup()) {
SG_LOG( SG_IO, SG_ALERT, "Winsock not available");
if (!init)
{
netInit(NULL, NULL); // plib-1.4.2 compatible
init = true;
}
#endif
if ( style == "udp" ) {
sock_style = SOCK_DGRAM;
} else if ( style == "tcp" ) {
sock_style = SOCK_STREAM;
} else {
sock_style = SOCK_DGRAM;
if ( style == "tcp" )
{
is_tcp = true;
}
else if ( style != (string)"udp" )
{
SG_LOG( SG_IO, SG_ALERT,
"Error: SGSocket() unknown style = " << style );
}
@@ -68,126 +64,65 @@ SGSocket::SGSocket( const string& host, const string& port,
}
SGSocket::~SGSocket() {
SGSocket::~SGSocket()
{
this->close();
}
SGSocket::SocketType SGSocket::make_server_socket () {
struct sockaddr_in name;
#if defined( __CYGWIN__ ) || defined( __CYGWIN32__ ) || defined( sgi ) || defined( _MSC_VER ) || defined(__MINGW32__) || defined( __APPLE__ )
int length;
#else
socklen_t length;
#endif
// Create the socket.
sock = socket (PF_INET, sock_style, 0);
if (sock == INVALID_SOCKET) {
SG_LOG( SG_IO, SG_ALERT,
"Error: socket() failed in make_server_socket()" );
return INVALID_SOCKET;
}
// Give the socket a name.
name.sin_family = AF_INET;
name.sin_addr.s_addr = INADDR_ANY;
name.sin_port = htons(port); // set port to zero to let system pick
name.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) != 0) {
SG_LOG( SG_IO, SG_ALERT,
"Error: bind() failed in make_server_socket()" );
return INVALID_SOCKET;
}
// Find the assigned port number
length = sizeof(struct sockaddr_in);
if ( getsockname(sock, (struct sockaddr *) &name, &length) ) {
SG_LOG( SG_IO, SG_ALERT,
"Error: getsockname() failed in make_server_socket()" );
return INVALID_SOCKET;
}
port = ntohs(name.sin_port);
return sock;
}
SGSocket::SocketType SGSocket::make_client_socket () {
struct sockaddr_in name;
struct hostent *hp;
SG_LOG( SG_IO, SG_INFO, "Make client socket()" );
// Create the socket.
sock = socket (PF_INET, sock_style, 0);
if (sock == INVALID_SOCKET) {
SG_LOG( SG_IO, SG_ALERT,
"Error: socket() failed in make_server_socket()" );
return INVALID_SOCKET;
}
// specify address family
name.sin_family = AF_INET;
// get the hosts official name/info
hp = gethostbyname( hostname.c_str() );
if (hp == NULL) {
SG_LOG( SG_IO, SG_ALERT, "Error: hostname lookup failed" );
return INVALID_SOCKET;
}
// Connect this socket to the host and the port specified on the
// command line
#if defined( __CYGWIN__ ) || defined( __CYGWIN32__ )
bcopy(hp->h_addr, (char *)(&(name.sin_addr.s_addr)), hp->h_length);
#else
bcopy(hp->h_addr, &(name.sin_addr.s_addr), hp->h_length);
#endif
name.sin_port = htons(port);
if ( connect(sock, (struct sockaddr *) &name,
sizeof(struct sockaddr_in)) != 0 )
bool
SGSocket::make_server_socket()
{
if (!sock.open( is_tcp ))
{
SG_LOG( SG_IO, SG_ALERT,
"Error: socket() failed in make_server_socket()" );
return false;
}
if (sock.bind( "", port ) < 0)
{
SG_LOG( SG_IO, SG_ALERT,
"Error: bind() failed in make_server_socket()" );
sock.close();
return false;
}
return true;
}
bool
SGSocket::make_client_socket()
{
if (!sock.open( is_tcp ))
{
SG_LOG( SG_IO, SG_ALERT,
"Error: socket() failed in make_client_socket()" );
return false;
}
if (sock.connect( hostname.c_str(), port ) < 0)
{
closesocket(sock);
SG_LOG( SG_IO, SG_ALERT,
"Error: connect() failed in make_client_socket()" );
return INVALID_SOCKET;
sock.close();
return false;
}
return sock;
return true;
}
// Wrapper functions
size_t SGSocket::readsocket( int fd, void *buf, size_t count ) {
#if defined(_MSC_VER) || defined(__MINGW32__)
return ::recv( fd, (char *)buf, count, 0 );
#else
return ::read( fd, buf, count );
#endif
}
size_t SGSocket::writesocket( int fd, const void *buf, size_t count ) {
#if defined(_MSC_VER) || defined(__MINGW32__)
return ::send( fd, (const char*)buf, count, 0 );
#else
return ::write( fd, buf, count );
#endif
}
#if !defined(_MSC_VER) && !defined(__MINGW32__)
int SGSocket::closesocket( int fd ) {
return ::close( fd );
}
#endif
// If specified as a server (in direction for now) open the master
// listening socket. If specified as a client (out direction), open a
// connection to a server.
bool SGSocket::open( const SGProtocolDir d ) {
set_dir( d );
bool
SGSocket::open( SGProtocolDir direction )
{
set_dir( direction );
is_server = is_tcp &&
(direction == SG_IO_IN || direction == SG_IO_BI);
if ( port_str == "" || port_str == "any" ) {
port = 0;
@@ -195,69 +130,71 @@ bool SGSocket::open( const SGProtocolDir d ) {
port = atoi( port_str.c_str() );
}
// client_connections.clear();
if ( get_dir() == SG_IO_IN ) {
if (direction == SG_IO_IN)
{
// this means server for now
// Setup socket to listen on. Set "port" before making this
// call. A port of "0" indicates that we want to let the os
// pick any available port.
sock = make_server_socket();
if ( sock == INVALID_SOCKET ) {
SG_LOG( SG_IO, SG_ALERT, "socket creation failed" );
if (!make_server_socket())
{
SG_LOG( SG_IO, SG_ALERT, "SG_IO_IN socket creation failed" );
return false;
}
SG_LOG( SG_IO, SG_INFO, "socket is connected to port = " << port );
if ( sock_style == SOCK_DGRAM ) {
if ( !is_tcp )
{
// Non-blocking UDP
nonblock();
} else {
}
else
{
// Blocking TCP
// Specify the maximum length of the connection queue
listen( sock, SG_MAX_SOCKET_QUEUE );
sock.listen( SG_MAX_SOCKET_QUEUE );
}
} else if ( get_dir() == SG_IO_OUT ) {
}
else if (direction == SG_IO_OUT)
{
// this means client for now
sock = make_client_socket();
// TODO: check for error.
if (!make_client_socket())
{
SG_LOG( SG_IO, SG_ALERT, "SG_IO_OUT socket creation failed" );
return false;
}
if ( sock_style == SOCK_DGRAM ) {
if ( !is_tcp )
{
// Non-blocking UDP
nonblock();
}
} else if ( get_dir() == SG_IO_BI && sock_style == SOCK_STREAM ) {
}
else if (direction == SG_IO_BI && is_tcp)
{
// this means server for TCP sockets
// Setup socket to listen on. Set "port" before making this
// call. A port of "0" indicates that we want to let the os
// pick any available port.
sock = make_server_socket();
// TODO: check for error.
SG_LOG( SG_IO, SG_INFO, "socket is connected to port = " << port );
if (!make_server_socket())
{
SG_LOG( SG_IO, SG_ALERT, "SG_IO_BI socket creation failed" );
return false;
}
// Blocking TCP
// Specify the maximum length of the connection queue
listen( sock, SG_MAX_SOCKET_QUEUE );
} else {
sock.listen( SG_MAX_SOCKET_QUEUE );
}
else
{
SG_LOG( SG_IO, SG_ALERT,
"Error: bidirection mode not available for UDP sockets." );
return false;
}
if ( sock < 0 ) {
SG_LOG( SG_IO, SG_ALERT, "Error opening socket: " << hostname
<< ":" << port );
return false;
}
// extra SOCK_STREAM stuff
msgsock = INVALID_SOCKET;
first_read = false;
return true;
@@ -266,40 +203,25 @@ bool SGSocket::open( const SGProtocolDir d ) {
// read data from socket (server)
// read a block of data of specified size
int SGSocket::read( char *buf, int length ) {
if ( sock == INVALID_SOCKET ) {
int
SGSocket::read( char *buf, int length )
{
if (sock.getHandle() == -1 &&
(client == 0 || client->getHandle() == -1))
{
return 0;
}
int result = 0;
// check for potential input
fd_set ready;
FD_ZERO(&ready);
FD_SET(sock, &ready);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
// test for any input available on sock (returning immediately, even if
// nothing)
select(32, &ready, 0, 0, &tv);
int result = poll();
if ( FD_ISSET(sock, &ready) ) {
// cout << "data ready" << endl;
if (result > 0)
{
result = sock.recv( buf, length );
if ( sock_style == SOCK_STREAM ) {
if ( msgsock == INVALID_SOCKET ) {
msgsock = accept(sock, 0, 0);
closesocket(sock);
sock = msgsock;
} else {
result = readsocket( sock, buf, length );
}
} else {
result = readsocket( sock, buf, length );
}
if ( result != length ) {
if ( result != length )
{
SG_LOG( SG_IO, SG_INFO,
"Warning: read() not enough bytes." );
}
@@ -310,92 +232,74 @@ int SGSocket::read( char *buf, int length ) {
// read a line of data, length is max size of input buffer
int SGSocket::readline( char *buf, int length ) {
if ( sock == INVALID_SOCKET ) {
int
SGSocket::readline( char *buf, int length )
{
if (sock.getHandle() == -1 &&
(client == 0 || client->getHandle() == -1))
{
return 0;
}
// cout << "sock = " << sock << endl;
// check for potential input
fd_set ready;
FD_ZERO(&ready);
FD_SET(sock, &ready);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
// test for any input read on sock (returning immediately, even if
// nothing)
int result = select(32, &ready, 0, 0, &tv);
// cout << "result = " << result << endl;
int result = this->poll();
if ( FD_ISSET(sock, &ready) ) {
// cout << "fd change state\n";
if (result > 0)
{
// read a chunk, keep in the save buffer until we have the
// requested amount read
if ( sock_style == SOCK_STREAM ) {
// cout << "sock_stream\n";
if ( msgsock == INVALID_SOCKET ) {
// cout << "msgsock == invalid\n";
msgsock = sock;
sock = accept(msgsock, 0, 0);
} else {
// cout << "ready to read\n";
char *buf_ptr = save_buf + save_len;
result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE
- save_len );
// cout << "read result = " << result << endl;
if ( result > 0 ) {
first_read = true;
}
save_len += result;
// Try and detect that the remote end died. This
// could cause problems so if you see connections
// dropping for unexplained reasons, LOOK HERE!
if ( result == 0 && save_len == 0 && first_read == true ) {
SG_LOG( SG_IO, SG_ALERT,
"Connection closed by foreign host." );
close();
}
}
} else {
if (is_tcp)
{
char *buf_ptr = save_buf + save_len;
result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
result = client->recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
if ( result > 0 )
{
first_read = true;
}
save_len += result;
// Try and detect that the remote end died. This
// could cause problems so if you see connections
// dropping for unexplained reasons, LOOK HERE!
if (result == 0 && save_len == 0 && first_read == true)
{
SG_LOG( SG_IO, SG_ALERT,
"Connection closed by foreign host." );
delete client;
client = 0;
}
}
else
{
char *buf_ptr = save_buf + save_len;
result = sock.recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
save_len += result;
}
// cout << "current read = " << buf_ptr << endl;
// cout << "current save_buf = " << save_buf << endl;
// cout << "save_len = " << save_len << endl;
} else {
// cout << "no data ready\n";
}
// look for the end of line in save_buf
int i;
for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i );
for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i )
;
if ( save_buf[i] == '\n' ) {
result = i + 1;
} else {
// no end of line yet
// cout << "no eol found" << endl;
return 0;
}
// cout << "line length = " << result << endl;
// we found an end of line
// copy to external buffer
strncpy( buf, save_buf, result );
buf[result] = '\0';
// cout << "sg_socket line = " << buf << endl;
// shift save buffer
//memmove( save_buf+, save_buf+, ? );
for ( i = result; i < save_len; ++i ) {
save_buf[ i - result ] = save_buf[i];
}
@@ -406,66 +310,23 @@ int SGSocket::readline( char *buf, int length ) {
// write data to socket (client)
int SGSocket::write( const char *buf, const int length ) {
if ( sock == INVALID_SOCKET ) {
int
SGSocket::write( const char *buf, const int length )
{
netSocket* s = client == 0 ? &sock : client;
if (s->getHandle() == -1)
{
return 0;
}
bool error_condition = false;
if ( writesocket(sock, buf, length) < 0 ) {
if ( s->send( buf, length ) < 0 )
{
SG_LOG( SG_IO, SG_ALERT, "Error writing to socket: " << port );
error_condition = true;
}
#if 0
// check for any new client connection requests
fd_set ready;
FD_ZERO(&ready);
FD_SET(sock, &ready);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
// test for any input on sock (returning immediately, even if
// nothing)
select(32, &ready, 0, 0, &tv);
// any new connections?
if ( FD_ISSET(sock, &ready) ) {
int msgsock = accept(sock, 0, 0);
if ( msgsock < 0 ) {
SG_LOG( SG_IO, SG_ALERT,
"Error: accept() failed in write()" );
return 0;
} else {
client_connections.push_back( msgsock );
}
}
SG_LOG( SG_IO, SG_INFO, "Client connections = " <<
client_connections.size() );
for ( int i = 0; i < (int)client_connections.size(); ++i ) {
int msgsock = client_connections[i];
// read and junk any possible incoming messages.
// char junk[ SG_IO_MAX_MSG_SIZE ];
// std::read( msgsock, junk, SG_IO_MAX_MSG_SIZE );
// write the interesting data to the socket
if ( writesocket(msgsock, buf, length) == SOCKET_ERROR ) {
SG_LOG( SG_IO, SG_ALERT, "Error writing to socket: " << port );
error_condition = true;
} else {
#ifdef _POSIX_SYNCHRONIZED_IO
// fdatasync(msgsock);
#else
// fsync(msgsock);
#endif
}
}
#endif
if ( error_condition ) {
return 0;
}
@@ -475,79 +336,62 @@ int SGSocket::write( const char *buf, const int length ) {
// write null terminated string to socket (server)
int SGSocket::writestring( const char *str ) {
if ( sock == INVALID_SOCKET ) {
return 0;
}
int
SGSocket::writestring( const char *str )
{
int length = strlen( str );
return write( str, length );
return this->write( str, length );
}
// close the port
bool SGSocket::close() {
if ( sock == INVALID_SOCKET ) {
return 0;
}
bool
SGSocket::close()
{
delete client;
client = 0;
closesocket( sock );
if ( sock_style == SOCK_STREAM && msgsock != INVALID_SOCKET ) {
sock = msgsock;
msgsock = INVALID_SOCKET;
}
sock.close();
return true;
}
// configure the socket as non-blocking
bool SGSocket::nonblock() {
if ( sock == INVALID_SOCKET ) {
bool
SGSocket::nonblock()
{
if (sock.getHandle() == -1) {
return false;
}
sock.setBlocking( false );
return true;
}
int
SGSocket::poll()
{
netSocket* readers[2];
readers[0] = client != 0 ? client : &sock;
readers[1] = 0;
netSocket* writers[1];
writers[0] = 0;
int result = netSocket::select( readers, writers, 0 );
if (result > 0 && is_server && client == 0)
{
// Accept a new client connection
netAddress addr;
int new_fd = sock.accept( &addr );
SG_LOG( SG_IO, SG_INFO, "Accepted connection from "
<< addr.getHost() << ":" << addr.getPort() );
client = new netSocket();
client->setHandle( new_fd );
return 0;
}
#if defined(_MSC_VER) || defined(__MINGW32__)
u_long arg = 1;
if (ioctlsocket( sock, FIONBIO, &arg ) != 0) {
int error_code = WSAGetLastError();
SG_LOG( SG_IO, SG_ALERT,
"Error " << error_code << ": unable to set non-blocking mode"
);
return false;
}
#else
fcntl( sock, F_SETFL, O_NONBLOCK );
#endif
return true;
return result;
}
#if defined(_MSC_VER) || defined(__MINGW32__)
bool SGSocket::wsock_init = false;
bool
SGSocket::wsastartup() {
WORD wVersionRequested;
WSADATA wsaData;
//wVersionRequested = MAKEWORD( 2, 2 );
wVersionRequested = MAKEWORD( 1, 1 );
int err = WSAStartup( wVersionRequested, &wsaData );
if (err != 0)
{
SG_LOG( SG_IO, SG_ALERT, "Error: Couldn't load winsock" );
return false;
}
#if 0
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
SG_LOG( SG_IO, SG_ALERT, "Couldn't load a suitable winsock");
WSACleanup( );
return false;
}
#endif
wsock_init = true;
return true;
}
#endif

View File

@@ -39,11 +39,9 @@
#include <simgear/math/sg_types.hxx>
#include <simgear/io/iochannel.hxx>
SG_USING_STD(string);
#include <plib/netSocket.h>
#if defined(_MSC_VER) || defined(__MINGW32__)
# include <winsock.h>
#endif
SG_USING_STD(string);
#define SG_MAX_SOCKET_QUEUE 32
@@ -53,13 +51,6 @@ SG_USING_STD(string);
*/
class SGSocket : public SGIOChannel {
public:
#if defined(_MSC_VER) || defined(__MINGW32__)
typedef SOCKET SocketType;
#else
typedef int SocketType;
# define INVALID_SOCKET (-1)
#endif
private:
string hostname;
string port_str;
@@ -67,31 +58,23 @@ private:
char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ];
int save_len;
SocketType sock;
SocketType msgsock;
short unsigned int port;
int sock_style; // SOCK_STREAM or SOCK_DGRAM
netSocket sock;
netSocket* client;
unsigned short port;
bool is_tcp;
bool is_server;
bool first_read;
static bool init;
// make a server (master listening) socket
SocketType make_server_socket();
bool make_server_socket();
// make a client socket
SocketType make_client_socket();
bool make_client_socket();
// wrapper functions
size_t readsocket( int fd, void *buf, size_t count );
size_t writesocket( int fd, const void *buf, size_t count );
#if !defined(_MSC_VER) && !defined(__MINGW32__)
int closesocket(int fd);
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
// Ensure winsock has been initialised.
static bool wsock_init;
static bool wsastartup();
#endif
// Poll for new connections or data to read.
int poll();
public:

89
simgear/io/tcp_client.cxx Normal file
View File

@@ -0,0 +1,89 @@
#include <simgear/compiler.h>
#include STL_IOSTREAM
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <simgear/debug/logstream.hxx>
#include "sg_socket.hxx"
#ifndef SG_HAVE_NATIVE_SGI_COMPILERS
using std::cout;
#endif
class TcpClient
{
public:
TcpClient( const char* host, const char* port );
~TcpClient();
bool open();
bool process();
bool close();
private:
SGIOChannel* channel;
};
TcpClient::TcpClient( const char* host, const char* port )
{
channel = new SGSocket( host, port, "tcp" );
}
TcpClient::~TcpClient()
{
delete channel;
}
bool
TcpClient::open()
{
return channel->open( SG_IO_OUT );
}
bool
TcpClient::process()
{
char wbuf[1024];
sprintf( wbuf, "hello world\n" );
int length = channel->writestring( wbuf );
cout << "writestring returned " << length << "\n";
return true;
}
bool
TcpClient::close()
{
return channel->close();
}
int
main()
{
sglog().setLogLevels( SG_ALL, SG_INFO );
TcpClient client( "localhost", "5500" );
if (!client.open())
{
cout << "client open failed\n";
return 0;
}
for (int i = 0; i < 3; ++i)
{
client.process();
#ifdef _WIN32
Sleep(1000);
#else
sleep(1);
#endif
}
//client.close();
return 0;
}

72
simgear/io/tcp_server.cxx Normal file
View File

@@ -0,0 +1,72 @@
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
#include STL_STRING
#include STL_IOSTREAM
#include "sg_socket.hxx"
using std::string;
#ifndef SG_HAVE_NATIVE_SGI_COMPILERS
using std::cout;
#endif
class TcpServer
{
public:
TcpServer();
bool open();
bool process();
bool close();
private:
SGIOChannel* channel;
};
TcpServer::TcpServer()
{
channel = new SGSocket( "", "5500", "tcp" );
}
bool
TcpServer::open()
{
channel->open( SG_IO_BI );
return true;
}
bool
TcpServer::process()
{
char buf[1024];
int len;
while ((len = channel->readline( buf, sizeof(buf) )) > 0)
{
cout << len << ": " << buf;
}
return true;
}
bool
TcpServer::close()
{
return channel->close();
}
int
main()
{
sglog().setLogLevels( SG_ALL, SG_INFO );
TcpServer server;
server.open();
SG_LOG( SG_IO, SG_INFO, "Created TCP server" );
while (1)
{
server.process();
}
server.close();
return 0;
}

View File

@@ -14,8 +14,4 @@ testmagvar_SOURCES = testmagvar.cxx
testmagvar_LDADD = $(top_builddir)/simgear/magvar/libsgmagvar.a
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif

View File

@@ -29,7 +29,10 @@
#include "magvar.hxx"
SGMagVar::SGMagVar() {
SGMagVar::SGMagVar()
: magvar(0.0),
magdip(0.0)
{
}
SGMagVar::~SGMagVar() {

View File

@@ -24,8 +24,4 @@ libsgmath_a_SOURCES = \
sg_random.c \
vector.cxx
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif

View File

@@ -22,6 +22,51 @@
// $Id$
/*
A C-program for MT19937, with initialization improved 2002/2/10.
Coded by Takuji Nishimura and Makoto Matsumoto.
This is a faster version by taking Shawn Cokus's optimization,
Matthe Bellew's simplification, Isaku Wada's real version.
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Any feedback is very welcome.
http://www.math.keio.ac.jp/matumoto/emt.html
email: matumoto@math.keio.ac.jp
*/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
@@ -32,50 +77,87 @@
#include "sg_random.h"
#ifndef HAVE_RAND
# ifdef sgi
# undef RAND_MAX
# define RAND_MAX 2147483647
# endif
#endif
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
#define UMASK 0x80000000UL /* most significant w-r bits */
#define LMASK 0x7fffffffUL /* least significant r bits */
#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
#ifdef __SUNPRO_CC
extern "C" {
long int random();
void srandom(unsigned int seed);
static unsigned long state[N]; /* the array for the state vector */
static int left = 1;
static int initf = 0;
static unsigned long *next;
/* initializes state[N] with a seed */
void init_genrand(unsigned long s)
{
int j;
state[0]= s & 0xffffffffUL;
for (j=1; j<N; j++) {
state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array state[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
state[j] &= 0xffffffffUL; /* for >32 bit machines */
}
#endif
left = 1; initf = 1;
}
static void next_state(void)
{
unsigned long *p=state;
int j;
/* if init_genrand() has not been called, */
/* a default initial seed is used */
if (initf==0) init_genrand(5489UL);
left = N;
next = state;
for (j=N-M+1; --j; p++)
*p = p[M] ^ TWIST(p[0], p[1]);
for (j=M; --j; p++)
*p = p[M-N] ^ TWIST(p[0], p[1]);
*p = p[M-N] ^ TWIST(p[0], state[0]);
}
// Seed the random number generater with time() so we don't see the
// same sequence every time
void sg_srandom_time() {
#ifdef HAVE_RAND
srand(time(NULL));
#else
srandom(time(NULL));
#endif
init_genrand(time(NULL));
}
// Seed the random number generater with your own seed so can set up
// repeatable randomization.
void sg_srandom( unsigned int seed ) {
#ifdef HAVE_RAND
srand( seed );
#else
srandom( seed );
#endif
init_genrand( seed );
}
// return a random number between [0.0, 1.0)
double sg_random() {
#ifdef HAVE_RAND
return(rand() / (double)RAND_MAX);
#else
return(random() / (double)RAND_MAX);
#endif
unsigned long y;
if (--left == 0)
next_state();
y = *next++;
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return (double)y * (1.0/4294967295.0);
/* divided by 2^32-1 */
}

View File

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

View File

@@ -1293,6 +1293,7 @@ static bool isVisibility( char **visblty, Decoded_METAR *Mptr,
/* None. */
/* */
/********************************************************************/
#if 0
static bool vrblVsby( char *string1, char *string2,
Decoded_METAR *Mptr, int *NDEX )
{
@@ -1368,6 +1369,7 @@ static bool vrblVsby( char *string1, char *string2,
}
}
#endif
/********************************************************************/

View File

@@ -11,8 +11,4 @@ libsgmetar_a_SOURCES = \
MetarStation.cpp \
Prtdmetr.cpp Stspack2.cpp Stspack3.cpp
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif

View File

@@ -30,8 +30,4 @@ noinst_PROGRAMS = props_test
props_test_SOURCES = props_test.cxx
props_test_LDADD = libsgmisc.a ../xml/libsgxml.a ../debug/libsgdebug.a
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif

View File

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

View File

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

View File

@@ -17,7 +17,9 @@
#include <iostream>
using std::cerr;
using std::endl;
using std::find;
using std::sort;
using std::vector;
#else
@@ -25,6 +27,15 @@ using std::sort;
#include <simgear/debug/logstream.hxx>
SG_USING_STD(sort);
SG_USING_STD(find);
SG_USING_STD(vector);
#ifdef _MSC_VER
// MSVC is buggy, and needs something strange here
SG_USING_STD(vector<SGPropertyNode_ptr>);
SG_USING_STD(vector<SGPropertyChangeListener *>);
SG_USING_STD(vector<SGPropertyNode *>);
#endif
#endif
@@ -40,7 +51,7 @@ SG_USING_STD(sort);
class CompareIndices
{
public:
int operator() (const SGPropertyNode * n1, const SGPropertyNode *n2) const {
int operator() (const SGPropertyNode_ptr n1, const SGPropertyNode_ptr n2) const {
return (n1->getIndex() < n2->getIndex());
}
};
@@ -236,7 +247,7 @@ compare_strings (const char * s1, const char * s2)
* Locate a child node by name and index.
*/
static int
find_child (const char * name, int index, vector<SGPropertyNode *> nodes)
find_child (const char * name, int index, vector<SGPropertyNode_ptr> nodes)
{
int nNodes = nodes.size();
for (int i = 0; i < nNodes; i++) {
@@ -360,9 +371,15 @@ inline bool
SGPropertyNode::set_bool (bool val)
{
if (_tied) {
return _value.bool_val->setValue(val);
if (_value.bool_val->setValue(val)) {
fireValueChanged();
return true;
} else {
return false;
}
} else {
_local_val.bool_val = val;
fireValueChanged();
return true;
}
}
@@ -371,9 +388,15 @@ inline bool
SGPropertyNode::set_int (int val)
{
if (_tied) {
return _value.int_val->setValue(val);
if (_value.int_val->setValue(val)) {
fireValueChanged();
return true;
} else {
return false;
}
} else {
_local_val.int_val = val;
fireValueChanged();
return true;
}
}
@@ -382,9 +405,15 @@ inline bool
SGPropertyNode::set_long (long val)
{
if (_tied) {
return _value.long_val->setValue(val);
if (_value.long_val->setValue(val)) {
fireValueChanged();
return true;
} else {
return false;
}
} else {
_local_val.long_val = val;
fireValueChanged();
return true;
}
}
@@ -393,9 +422,15 @@ inline bool
SGPropertyNode::set_float (float val)
{
if (_tied) {
return _value.float_val->setValue(val);
if (_value.float_val->setValue(val)) {
fireValueChanged();
return true;
} else {
return false;
}
} else {
_local_val.float_val = val;
fireValueChanged();
return true;
}
}
@@ -404,9 +439,15 @@ inline bool
SGPropertyNode::set_double (double val)
{
if (_tied) {
return _value.double_val->setValue(val);
if (_value.double_val->setValue(val)) {
fireValueChanged();
return true;
} else {
return false;
}
} else {
_local_val.double_val = val;
fireValueChanged();
return true;
}
}
@@ -415,10 +456,16 @@ inline bool
SGPropertyNode::set_string (const char * val)
{
if (_tied) {
return _value.string_val->setValue(val);
if (_value.string_val->setValue(val)) {
fireValueChanged();
return true;
} else {
return false;
}
} else {
delete [] _local_val.string_val;
_local_val.string_val = copy_string(val);
fireValueChanged();
return true;
}
}
@@ -551,23 +598,51 @@ SGPropertyNode::trace_read () const
#endif
}
/**
* Increment reference counter
*/
void
SGPropertyNode::incrementRef()
{
++_count;
}
/**
* Decrement reference counter
*/
int
SGPropertyNode::decrementRef()
{
return --_count;
}
////////////////////////////////////////////////////////////////////////
// Public methods from SGPropertyNode.
////////////////////////////////////////////////////////////////////////
/**
* Last used attribute
* Update as needed when enum Attribute is changed
*/
const int SGPropertyNode::LAST_USED_ATTRIBUTE = TRACE_WRITE;
/**
* Default constructor: always creates a root node.
*/
SGPropertyNode::SGPropertyNode ()
: _name(copy_string("")),
_display_name(0),
_index(0),
_parent(0),
_path(0),
_path_cache(0),
_type(NONE),
_tied(false),
_attr(READ|WRITE)
_attr(READ|WRITE),
_count(0),
_listeners(0)
{
_local_val.string_val = 0;
}
@@ -577,12 +652,16 @@ SGPropertyNode::SGPropertyNode ()
* Copy constructor.
*/
SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
: _index(node._index),
: _display_name(0),
_index(node._index),
_parent(0), // don't copy the parent
_path(0),
_path_cache(0),
_type(node._type),
_tied(node._tied),
_attr(node._attr)
_attr(node._attr),
_count(0),
_listeners(0) // CHECK!!
{
_name = copy_string(node._name);
_local_val.string_val = 0;
@@ -658,12 +737,16 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
SGPropertyNode::SGPropertyNode (const char * name,
int index,
SGPropertyNode * parent)
: _index(index),
: _display_name(0),
_index(index),
_parent(parent),
_path(0),
_path_cache(0),
_type(NONE),
_tied(false),
_attr(READ|WRITE)
_attr(READ|WRITE),
_count(0),
_listeners(0)
{
_name = copy_string(name);
_local_val.string_val = 0;
@@ -676,11 +759,11 @@ SGPropertyNode::SGPropertyNode (const char * name,
SGPropertyNode::~SGPropertyNode ()
{
delete [] _name;
for (int i = 0; i < (int)_children.size(); i++) {
delete _children[i];
}
delete [] _display_name;
delete [] _path;
delete _path_cache;
clear_value();
delete _listeners;
}
@@ -776,8 +859,20 @@ SGPropertyNode::getChild (const char * name, int index, bool create)
if (pos >= 0) {
return _children[pos];
} else if (create) {
_children.push_back(new SGPropertyNode(name, index, this));
return _children[_children.size()-1];
SGPropertyNode_ptr node;
pos = find_child(name, index, _removedChildren);
if (pos >= 0) {
vector<SGPropertyNode_ptr>::iterator it = _removedChildren.begin();
it += pos;
node = _removedChildren[pos];
_removedChildren.erase(it);
node->setAttribute(REMOVED, false);
} else {
node = new SGPropertyNode(name, index, this);
}
_children.push_back(node);
fireChildAdded(node);
return node;
} else {
return 0;
}
@@ -801,10 +896,10 @@ SGPropertyNode::getChild (const char * name, int index) const
/**
* Get all children with the same name (but different indices).
*/
vector<SGPropertyNode *>
SGPropertyNode::getChildren (const char * name)
vector<SGPropertyNode_ptr>
SGPropertyNode::getChildren (const char * name) const
{
vector<SGPropertyNode *> children;
vector<SGPropertyNode_ptr> children;
int max = _children.size();
for (int i = 0; i < max; i++)
@@ -817,38 +912,60 @@ SGPropertyNode::getChildren (const char * name)
/**
* Get all children const with the same name (but different indices).
* Remove a child node
*/
vector<const SGPropertyNode *>
SGPropertyNode::getChildren (const char * name) const
SGPropertyNode_ptr
SGPropertyNode::removeChild (const char * name, int index, bool keep)
{
vector<const SGPropertyNode *> children;
int max = _children.size();
SGPropertyNode_ptr ret;
int pos = find_child(name, index, _children);
if (pos >= 0) {
vector<SGPropertyNode_ptr>::iterator it = _children.begin();
it += pos;
SGPropertyNode_ptr node = _children[pos];
_children.erase(it);
if (keep) {
_removedChildren.push_back(node);
}
node->setAttribute(REMOVED, true);
ret = node;
fireChildRemoved(node);
}
return ret;
}
for (int i = 0; i < max; i++)
if (compare_strings(_children[i]->getName(), name))
children.push_back(_children[i]);
sort(children.begin(), children.end(), CompareIndices());
return children;
const char *
SGPropertyNode::getDisplayName (bool simplify) const
{
string display = _name;
if (_index != 0 || !simplify) {
char buffer[64];
sprintf(buffer, "[%d]", _index);
display += buffer;
}
_display_name = copy_string(display.c_str());
return _display_name;
}
const char *
SGPropertyNode::getPath (bool simplify) const
{
if (_parent == 0)
return "";
string path = _parent->getPath(simplify);
path += '/';
path += _name;
if (_index != 0 || !simplify) {
char buffer[128];
sprintf(buffer, "[%d]", _index);
path += buffer;
// Calculate the complete path only once.
if (_path == 0) {
string path;
if (_parent == 0) {
path = "";
} else {
path = _parent->getPath(simplify);
path += '/';
path += getDisplayName(simplify);
}
_path = copy_string(path.c_str());
}
return path.c_str();
return _path;
}
SGPropertyNode::Type
@@ -1899,6 +2016,87 @@ SGPropertyNode::untie (const char * relative_path)
return (node == 0 ? false : node->untie());
}
void
SGPropertyNode::addChangeListener (SGPropertyChangeListener * listener)
{
if (_listeners == 0)
_listeners = new vector<SGPropertyChangeListener *>;
_listeners->push_back(listener);
listener->register_property(this);
}
void
SGPropertyNode::removeChangeListener (SGPropertyChangeListener * listener)
{
vector<SGPropertyChangeListener *>::iterator it =
find(_listeners->begin(), _listeners->end(), listener);
if (it != _listeners->end()) {
_listeners->erase(it);
listener->unregister_property(this);
if (_listeners->empty()) {
vector<SGPropertyChangeListener *> * tmp = _listeners;
_listeners = 0;
delete tmp;
}
}
}
void
SGPropertyNode::fireValueChanged ()
{
fireValueChanged(this);
}
void
SGPropertyNode::fireChildAdded (SGPropertyNode * child)
{
fireChildAdded(this, child);
}
void
SGPropertyNode::fireChildRemoved (SGPropertyNode * child)
{
fireChildRemoved(this, child);
}
void
SGPropertyNode::fireValueChanged (SGPropertyNode * node)
{
if (_listeners != 0) {
for (unsigned int i = 0; i < _listeners->size(); i++) {
(*_listeners)[i]->valueChanged(node);
}
}
if (_parent != 0)
_parent->fireValueChanged(node);
}
void
SGPropertyNode::fireChildAdded (SGPropertyNode * parent,
SGPropertyNode * child)
{
if (_listeners != 0) {
for (unsigned int i = 0; i < _listeners->size(); i++) {
(*_listeners)[i]->childAdded(parent, child);
}
}
if (_parent != 0)
_parent->fireChildAdded(parent, child);
}
void
SGPropertyNode::fireChildRemoved (SGPropertyNode * parent,
SGPropertyNode * child)
{
if (_listeners != 0) {
for (unsigned int i = 0; i < _listeners->size(); i++) {
(*_listeners)[i]->childRemoved(parent, child);
}
}
if (_parent != 0)
_parent->fireChildRemoved(parent, child);
}
////////////////////////////////////////////////////////////////////////
@@ -1917,7 +2115,7 @@ SGPropertyNode::hash_table::entry::~entry ()
{
// Don't delete the value; we don't own
// the pointer.
delete _key;
delete [] _key;
}
void
@@ -1957,7 +2155,7 @@ SGPropertyNode::hash_table::bucket::get_entry (const char * key, bool create)
for (i = 0; i < _length; i++) {
new_entries[i] = _entries[i];
}
delete _entries;
delete [] _entries;
_entries = new_entries;
_entries[_length] = new entry;
_entries[_length]->set_key(key);
@@ -1977,7 +2175,7 @@ SGPropertyNode::hash_table::hash_table ()
SGPropertyNode::hash_table::~hash_table ()
{
for (int i = 0; i < _data_length; i++)
for (unsigned int i = 0; i < _data_length; i++)
delete _data[i];
}
@@ -2024,4 +2222,153 @@ SGPropertyNode::hash_table::hashcode (const char * key)
return hash;
}
/**
* Default constructor
*/
SGPropertyNode_ptr::SGPropertyNode_ptr()
{
_ptr = 0;
}
/**
* Copy constructor
*/
SGPropertyNode_ptr::SGPropertyNode_ptr( const SGPropertyNode_ptr &r )
{
_ptr = r._ptr;
if (_ptr)
_ptr->incrementRef();
}
/**
* Constructor from a pointer to a node
*/
SGPropertyNode_ptr::SGPropertyNode_ptr( SGPropertyNode *p )
{
_ptr = p;
if (_ptr)
_ptr->incrementRef();
}
/**
* Destructor
*/
SGPropertyNode_ptr::~SGPropertyNode_ptr()
{
if (_ptr && _ptr->decrementRef() == 0)
delete _ptr;
}
/**
* Assignement operator
*/
SGPropertyNode_ptr &
SGPropertyNode_ptr::operator=( const SGPropertyNode_ptr &r )
{
if (_ptr && _ptr->decrementRef() == 0)
delete _ptr;
_ptr = r._ptr;
if (_ptr)
_ptr->incrementRef();
return *this;
}
/**
* Pointer access operator
*/
SGPropertyNode *
SGPropertyNode_ptr::operator->()
{
return _ptr;
}
/**
* Pointer access operator (const)
*/
const SGPropertyNode *
SGPropertyNode_ptr::operator->() const
{
return _ptr;
}
/**
* Conversion to SGPropertyNode * operator
*/
SGPropertyNode_ptr::operator SGPropertyNode *()
{
return _ptr;
}
/**
* Conversion to const SGPropertyNode * operator
*/
SGPropertyNode_ptr::operator const SGPropertyNode *() const
{
return _ptr;
}
/**
* Validity test
*/
bool
SGPropertyNode_ptr::valid() const
{
return _ptr != 0;
}
////////////////////////////////////////////////////////////////////////
// Implementation of SGPropertyChangeListener.
////////////////////////////////////////////////////////////////////////
SGPropertyChangeListener::~SGPropertyChangeListener ()
{
// This will come back and remove
// the current item each time. Is
// that OK?
vector<SGPropertyNode *>::iterator it;
for (it = _properties.begin(); it != _properties.end(); it++)
(*it)->removeChangeListener(this);
}
void
SGPropertyChangeListener::valueChanged (SGPropertyNode * node)
{
// NO-OP
}
void
SGPropertyChangeListener::childAdded (SGPropertyNode * node,
SGPropertyNode * child)
{
// NO-OP
}
void
SGPropertyChangeListener::childRemoved (SGPropertyNode * parent,
SGPropertyNode * child)
{
// NO-OP
}
void
SGPropertyChangeListener::register_property (SGPropertyNode * node)
{
_properties.push_back(node);
}
void
SGPropertyChangeListener::unregister_property (SGPropertyNode * node)
{
vector<SGPropertyNode *>::iterator it =
find(_properties.begin(), _properties.end(), node);
if (it != _properties.end())
_properties.erase(it);
}
// end of props.cxx

View File

@@ -449,6 +449,100 @@ private:
setter_t _setter;
};
/**
* The smart pointer that manage reference counting
*/
class SGPropertyNode;
class SGPropertyNode_ptr
{
public:
/**
* Default constructor
*/
SGPropertyNode_ptr();
/**
* Copy constructor
*/
SGPropertyNode_ptr( const SGPropertyNode_ptr &r );
/**
* Constructor from a pointer to a node
*/
SGPropertyNode_ptr( SGPropertyNode *p );
/**
* Destructor
*/
~SGPropertyNode_ptr();
/**
* Assignement operator
*/
SGPropertyNode_ptr &operator=( const SGPropertyNode_ptr &r );
/**
* Pointer access operator
*/
SGPropertyNode *operator->();
/**
* Pointer access operator (const)
*/
const SGPropertyNode *operator->() const;
/**
* Conversion to SGPropertyNode * operator
*/
operator SGPropertyNode *();
/**
* Conversion to const SGPropertyNode * operator
*/
operator const SGPropertyNode *() const;
/**
* Return the pointer.
*/
SGPropertyNode * ptr () { return _ptr; }
/**
* Validity test
*/
bool valid() const;
private:
SGPropertyNode *_ptr;
};
/**
* The property change listener interface.
*
* <p>Any class that needs to listen for property changes must implement
* this interface.</p>
*/
class SGPropertyChangeListener
{
public:
virtual ~SGPropertyChangeListener ();
virtual void valueChanged (SGPropertyNode * node);
virtual void childAdded (SGPropertyNode * parent, SGPropertyNode * child);
virtual void childRemoved (SGPropertyNode * parent, SGPropertyNode * child);
protected:
friend class SGPropertyNode;
virtual void register_property (SGPropertyNode * node);
virtual void unregister_property (SGPropertyNode * node);
private:
vector<SGPropertyNode *> _properties;
};
/**
@@ -491,11 +585,19 @@ public:
READ = 1,
WRITE = 2,
ARCHIVE = 4,
TRACE_READ = 8,
TRACE_WRITE = 16
REMOVED = 8,
TRACE_READ = 16,
TRACE_WRITE = 32
};
/**
* Last used attribute
* Update as needed when enum Attribute is changed
*/
static const int LAST_USED_ATTRIBUTE;
/**
* Default constructor.
*/
@@ -531,10 +633,16 @@ public:
const char * getName () const { return _name; }
/**
* Get the node's pretty display name, with subscript when needed.
*/
const char * getDisplayName (bool simplify = false) const;
/**
* Get the node's integer index.
*/
const int getIndex () const { return _index; }
int getIndex () const { return _index; }
/**
@@ -557,7 +665,7 @@ public:
/**
* Get the number of child nodes.
*/
const int nChildren () const { return _children.size(); }
int nChildren () const { return _children.size(); }
/**
@@ -572,6 +680,15 @@ public:
const SGPropertyNode * getChild (int position) const;
/**
* Test whether a named child exists.
*/
bool hasChild (const char * name, int index = 0) const
{
return (getChild(name, index) != 0);
}
/**
* Get a child node by name and index.
*/
@@ -588,13 +705,14 @@ public:
/**
* Get a vector of all children with the specified name.
*/
vector<SGPropertyNode *> getChildren (const char * name);
vector<SGPropertyNode_ptr> getChildren (const char * name) const;
/**
* Get a vector all all children (const) with the specified name.
* Remove a child node
*/
vector<const SGPropertyNode *> getChildren (const char * name) const;
SGPropertyNode_ptr removeChild (const char * name, int index = 0,
bool keep = true);
//
@@ -1026,8 +1144,41 @@ public:
bool untie (const char * relative_path);
/**
* Add a change listener to the property.
*/
void addChangeListener (SGPropertyChangeListener * listener);
/**
* Remove a change listener from the property.
*/
void removeChangeListener (SGPropertyChangeListener * listener);
/**
* Fire a value change event to all listeners.
*/
void fireValueChanged ();
/**
* Fire a child-added event to all listeners.
*/
void fireChildAdded (SGPropertyNode * child);
/**
* Fire a child-removed event to all listeners.
*/
void fireChildRemoved (SGPropertyNode * child);
protected:
void fireValueChanged (SGPropertyNode * node);
void fireChildAdded (SGPropertyNode * parent, SGPropertyNode * child);
void fireChildRemoved (SGPropertyNode * parent, SGPropertyNode * child);
/**
* Protected constructor for making new nodes on demand.
@@ -1077,18 +1228,36 @@ private:
*/
void trace_write () const;
/**
* Increment reference counter
*/
void incrementRef();
/**
* Decrement reference counter
*/
int decrementRef();
friend class SGPropertyNode_ptr;
mutable char _buffer[MAX_STRING_LEN+1];
class hash_table;
char * _name;
mutable char * _display_name;
int _index;
SGPropertyNode * _parent;
vector<SGPropertyNode *> _children;
vector<SGPropertyNode_ptr> _children;
vector<SGPropertyNode_ptr> _removedChildren;
mutable char * _path;
hash_table * _path_cache;
Type _type;
bool _tied;
int _attr;
int _count;
// The right kind of pointer...
union {
@@ -1110,6 +1279,8 @@ private:
char * string_val;
} _local_val;
vector <SGPropertyChangeListener *> * _listeners;
/**

View File

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

View File

@@ -313,7 +313,7 @@ test_property_nodes ()
cout << endl;
cout << "Looking for all /hack[0]/bar children" << endl;
vector<SGPropertyNode *> bar = child->getChildren("bar");
vector<SGPropertyNode_ptr> bar = child->getChildren("bar");
cout << "There are " << bar.size() << " matches" << endl;
for (int i = 0; i < (int)bar.size(); i++)
cout << bar[i]->getName() << '[' << bar[i]->getIndex() << ']' << endl;

View File

@@ -1,8 +1,8 @@
// String utilities.
//
// Written by Bernie Bright, 1998
// Written by Bernie Bright, started 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
// Copyright (C) 1998 Bernie Bright - bbright@bigpond.net.au
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -21,48 +21,163 @@
//
// $Id$
#include <ctype.h>
#include "strutils.hxx"
const string whitespace = " \n\r\t";
namespace simgear {
namespace strutils {
//
string
trimleft( const string& s, const string& trimmings )
{
string result;
string::size_type pos = s.find_first_not_of( trimmings );
if ( pos != string::npos )
{
result.assign( s.substr( pos ) );
}
/**
*
*/
static vector<string>
split_whitespace( const string& str, int maxsplit )
{
vector<string> result;
string::size_type len = str.length();
string::size_type i = 0;
string::size_type j;
int countsplit = 0;
return result;
}
while (i < len)
{
while (i < len && isspace(str[i]))
{
++i;
}
//
string
trimright( const string& s, const string& trimmings )
{
string result;
j = i;
string::size_type pos = s.find_last_not_of( trimmings );
if ( pos == string::npos )
{
// Not found, return the original string.
result = s;
}
else
{
result.assign( s.substr( 0, pos+1 ) );
}
while (i < len && !isspace(str[i]))
{
++i;
}
return result;
}
if (j < i)
{
result.push_back( str.substr(j, i-j) );
++countsplit;
while (i < len && isspace(str[i]))
{
++i;
}
//
string
trim( const string& s, const string& trimmings )
{
return trimright( trimleft( s, trimmings ), trimmings );
}
if (maxsplit && (countsplit >= maxsplit) && i < len)
{
result.push_back( str.substr( i, len-i ) );
i = len;
}
}
}
return result;
}
/**
*
*/
vector<string>
split( const string& str, const char* sep, int maxsplit )
{
if (sep == 0)
return split_whitespace( str, maxsplit );
vector<string> result;
int n = strlen( sep );
if (n == 0)
{
// Error: empty separator string
return result;
}
const char* s = str.c_str();
string::size_type len = str.length();
string::size_type i = 0;
string::size_type j = 0;
int splitcount = 0;
while (i+n <= len)
{
if (s[i] == sep[0] && (n == 1 || memcmp(s+i, sep, n) == 0))
{
result.push_back( str.substr(j,i-j) );
i = j = i + n;
++splitcount;
if (maxsplit && (splitcount >= maxsplit))
break;
}
else
{
++i;
}
}
result.push_back( str.substr(j,len-j) );
return result;
}
/**
* The lstrip(), rstrip() and strip() functions are implemented
* in do_strip() which uses an additional parameter to indicate what
* type of strip should occur.
*/
const int LEFTSTRIP = 0;
const int RIGHTSTRIP = 1;
const int BOTHSTRIP = 2;
static string
do_strip( const string& s, int striptype )
{
// if (s.empty())
// return s;
string::size_type len = s.length();
string::size_type i = 0;
if (striptype != RIGHTSTRIP)
{
while (i < len && isspace(s[i]))
{
++i;
}
}
string::size_type j = len;
if (striptype != LEFTSTRIP)
{
do
{
--j;
}
while (j >= 1 && isspace(s[j]));
++j;
}
if (i == 0 && j == len)
{
return s;
}
else
{
return s.substr( i, j - i );
}
}
string
lstrip( const string& s )
{
return do_strip( s, LEFTSTRIP );
}
string
rstrip( const string& s )
{
return do_strip( s, RIGHTSTRIP );
}
string
strip( const string& s )
{
return do_strip( s, BOTHSTRIP );
}
} // end namespace strutils
} // end namespace simgear

View File

@@ -3,9 +3,9 @@
* String utilities.
*/
// Written by Bernie Bright, 1998
// Written by Bernie Bright, started 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
// Copyright (C) 1998 Bernie Bright - bbright@bigpond.net.au
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -32,6 +32,9 @@
#include STL_STRING
#include <vector>
SG_USING_STD(vector);
#ifdef SG_HAVE_STD_INCLUDES
# include <cstdlib>
#else
@@ -40,32 +43,54 @@
SG_USING_STD(string);
namespace simgear {
namespace strutils {
/** Default characters to remove. */
extern const string whitespace;
// /**
// * atof() wrapper for "string" type
// */
// inline double
// atof( const string& str )
// {
// return ::atof( str.c_str() );
// }
/** Returns a string with trailing characters removed. */
string trimleft( const string& s, const string& trimmings = whitespace );
// /**
// * atoi() wrapper for "string" type
// */
// inline int
// atoi( const string& str )
// {
// return ::atoi( str.c_str() );
// }
/** Returns a string with leading characters removed. */
string trimright( const string& s, const string& trimmings = whitespace );
/**
* Strip leading and/or trailing whitespace from s.
* @param s String to strip.
* @return The stripped string.
*/
string lstrip( const string& s );
string rstrip( const string& s );
string strip( const string& s );
/** Returns a string with leading and trailing characters removed. */
string trim( const string& s, const string& trimmings = whitespace );
/**
* Split a string into a words using 'sep' as the delimiter string.
* Produces a result similar to the perl and python functions of the
* same name.
*
* @param s The string to split into words,
* @param sep Word delimiters. If not specified then any whitespace is a separator,
* @param maxsplit If given, splits at no more than maxsplit places,
* resulting in at most maxsplit+1 words.
* @return Array of words.
*/
vector<string>
split( const string& s,
const char* sep = 0,
int maxsplit = 0 );
/** atof() wrapper for "string" type */
inline double
atof( const string& str )
{
return ::atof( str.c_str() );
}
/** atoi() wrapper for "string" type */
inline int
atoi( const string& str )
{
return ::atoi( str.c_str() );
}
} // end namespace strutils
} // end namespace simgear
#endif // STRUTILS_H

View File

@@ -8,11 +8,7 @@ libsgroute_a_SOURCES = \
route.cxx \
waypoint.cxx
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif
noinst_PROGRAMS = waytest routetest

View File

@@ -1,5 +1,7 @@
includedir = @includedir@/sky
SUBDIRS = clouds3d
lib_LIBRARIES = libsgsky.a
include_HEADERS = \
@@ -20,8 +22,4 @@ libsgsky_a_SOURCES = \
sphere.cxx \
stars.cxx
if OLD_AUTOMAKE
INCLUDES += -I$(top_srcdir)
else
INCLUDES = -I$(top_srcdir)
endif

View File

@@ -28,35 +28,135 @@
#include <simgear/math/polar3d.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include "cloud.hxx"
ssgSimpleState *
SGCloudLayer::layer_states[SGCloudLayer::SG_MAX_CLOUD_TYPES];
// Constructor
SGCloudLayer::SGCloudLayer( void ) {
SGCloudLayer::SGCloudLayer( const string &tex_path )
: layer_root(new ssgRoot),
layer_transform(new ssgTransform),
layer(0),
texture_path(tex_path),
layer_span(0),
layer_asl(0),
layer_thickness(0),
layer_transition(0),
layer_type(SG_CLOUD_CLEAR)
{
layer_root->addKid(layer_transform);
rebuild();
}
// Destructor
SGCloudLayer::~SGCloudLayer( void ) {
SGCloudLayer::~SGCloudLayer()
{
delete layer_root; // deletes layer_transform and layer as well
}
float
SGCloudLayer::getSpan_m () const
{
return layer_span;
}
void
SGCloudLayer::setSpan_m (float span_m)
{
if (span_m != layer_span) {
layer_span = span_m;
rebuild();
}
}
float
SGCloudLayer::getElevation_m () const
{
return layer_asl;
}
void
SGCloudLayer::setElevation_m (float elevation_m)
{
layer_asl = elevation_m;
}
float
SGCloudLayer::getThickness_m () const
{
return layer_thickness;
}
void
SGCloudLayer::setThickness_m (float thickness_m)
{
layer_thickness = thickness_m;
}
float
SGCloudLayer::getTransition_m () const
{
return layer_transition;
}
void
SGCloudLayer::setTransition_m (float transition_m)
{
layer_transition = transition_m;
}
SGCloudLayer::Type
SGCloudLayer::getType () const
{
return layer_type;
}
void
SGCloudLayer::setType (Type type)
{
if (type != layer_type) {
layer_type = type;
rebuild();
}
}
// build the cloud object
void SGCloudLayer::build( double s, double asl, double thickness,
double transition, ssgSimpleState *state )
void
SGCloudLayer::rebuild()
{
// Initialize states and sizes if necessary.
if (layer_states[0] == 0) {
SGPath cloud_path;
cloud_path.set(texture_path.str());
cloud_path.append("overcast.rgb");
layer_states[SG_CLOUD_OVERCAST] = SGCloudMakeState(cloud_path.str());
cloud_path.set(texture_path.str());
cloud_path.append("mostlycloudy.rgba");
layer_states[SG_CLOUD_MOSTLY_CLOUDY] =
SGCloudMakeState(cloud_path.str());
cloud_path.set(texture_path.str());
cloud_path.append("mostlysunny.rgba");
layer_states[SG_CLOUD_MOSTLY_SUNNY] = SGCloudMakeState(cloud_path.str());
cloud_path.set(texture_path.str());
cloud_path.append("cirrus.rgba");
layer_states[SG_CLOUD_CIRRUS] = SGCloudMakeState(cloud_path.str());
layer_states[SG_CLOUD_CLEAR] = 0;
}
scale = 4000.0;
layer_asl = asl;
layer_thickness = thickness;
layer_transition = transition;
size = s;
last_lon = last_lat = -999.0f;
layer_state = state;
cl = new ssgColourArray( 4 );
vl = new ssgVertexArray( 4 );
tl = new ssgTexCoordArray( 4 );
@@ -67,7 +167,7 @@ void SGCloudLayer::build( double s, double asl, double thickness,
sgVec2 tc;
sgSetVec4( color, 1.0f, 1.0f, 1.0f, 1.0f );
sgSetVec3( vertex, -size, -size, 0.0f );
sgSetVec3( vertex, -layer_span, -layer_span, 0.0f );
sgVec2 base;
sgSetVec2( base, sg_random(), sg_random() );
sgSetVec2( tc, base[0], base[1] );
@@ -75,40 +175,35 @@ void SGCloudLayer::build( double s, double asl, double thickness,
vl->add( vertex );
tl->add( tc );
sgSetVec3( vertex, size, -size, 0.0f );
sgSetVec2( tc, base[0] + size / scale, base[1] );
sgSetVec3( vertex, layer_span, -layer_span, 0.0f );
sgSetVec2( tc, base[0] + layer_span / scale, base[1] );
cl->add( color );
vl->add( vertex );
tl->add( tc );
sgSetVec3( vertex, -size, size, 0.0f );
sgSetVec2( tc, base[0], base[1] + size / scale );
sgSetVec3( vertex, -layer_span, layer_span, 0.0f );
sgSetVec2( tc, base[0], base[1] + layer_span / scale );
cl->add( color );
vl->add( vertex );
tl->add( tc );
sgSetVec3( vertex, size, size, 0.0f );
sgSetVec2( tc, base[0] + size / scale, base[1] + size / scale );
sgSetVec3( vertex, layer_span, layer_span, 0.0f );
sgSetVec2( tc, base[0] + layer_span / scale, base[1] + layer_span / scale );
cl->add( color );
vl->add( vertex );
tl->add( tc );
ssgLeaf *layer =
new ssgVtxTable ( GL_TRIANGLE_STRIP, vl, NULL, tl, cl );
layer->setState( layer_state );
if (layer != 0)
layer_transform->removeKid(layer); // automatic delete
layer = new ssgVtxTable ( GL_TRIANGLE_STRIP, vl, NULL, tl, cl );
if (layer_states[layer_type] != 0)
layer->setState( layer_states[layer_type] );
// force a repaint of the moon colors with arbitrary defaults
repaint( color );
// build the ssg scene graph sub tree for the sky and connected
// into the provide scene graph branch
layer_transform = new ssgTransform;
// moon_transform->addKid( halo );
layer_transform->addKid( layer );
layer_root = new ssgRoot;
layer_root->addKid( layer_transform );
}
@@ -214,7 +309,7 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat,
base[0] -= (int)base[0];
} else {
base[0] = 0.0;
SG_LOG(SG_ASTRO, SG_ALERT,
SG_LOG(SG_ASTRO, SG_DEBUG,
"Error: base = " << base[0] << "," << base[1]);
}
@@ -234,13 +329,13 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat,
// cout << "base = " << base[0] << "," << base[1] << endl;
tc = tl->get( 1 );
sgSetVec2( tc, base[0] + size / scale, base[1] );
sgSetVec2( tc, base[0] + layer_span / scale, base[1] );
tc = tl->get( 2 );
sgSetVec2( tc, base[0], base[1] + size / scale );
sgSetVec2( tc, base[0], base[1] + layer_span / scale );
tc = tl->get( 3 );
sgSetVec2( tc, base[0] + size / scale, base[1] + size / scale );
sgSetVec2( tc, base[0] + layer_span / scale, base[1] + layer_span / scale );
last_lon = lon;
last_lat = lat;
@@ -251,7 +346,8 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat,
void SGCloudLayer::draw() {
ssgCullAndDraw( layer_root );
if (layer_type != SG_CLOUD_CLEAR)
ssgCullAndDraw( layer_root );
}
@@ -272,5 +368,9 @@ ssgSimpleState *SGCloudMakeState( const string &path ) {
state->enable( GL_ALPHA_TEST );
state->setAlphaClamp( 0.01 );
// ref() the state so it doesn't get deleted if the last layer of
// it's type is deleted.
state->ref();
return state;
}

View File

@@ -33,53 +33,42 @@
SG_USING_STD(string);
#define SG_MAX_CLOUD_TYPES 4 // change this if we add/remove cloud
// types en the enum below
enum SGCloudType {
SG_CLOUD_OVERCAST = 0,
SG_CLOUD_MOSTLY_CLOUDY,
SG_CLOUD_MOSTLY_SUNNY,
SG_CLOUD_CIRRUS
};
class SGCloudLayer {
private:
ssgRoot *layer_root;
ssgTransform *layer_transform;
ssgSimpleState *layer_state;
ssgColourArray *cl;
ssgVertexArray *vl;
ssgTexCoordArray *tl;
// height above sea level (meters)
float layer_asl;
float layer_thickness;
float layer_transition;
float size;
float scale;
// for handling texture coordinates to simulate cloud movement
// from winds, and to simulate the clouds being tied to ground
// position, not view position
// double xoff, yoff;
double last_lon, last_lat;
public:
// Constructor
SGCloudLayer( void );
enum Type {
SG_CLOUD_OVERCAST = 0,
SG_CLOUD_MOSTLY_CLOUDY,
SG_CLOUD_MOSTLY_SUNNY,
SG_CLOUD_CIRRUS,
SG_CLOUD_CLEAR,
SG_MAX_CLOUD_TYPES
};
// Constructors
SGCloudLayer( const string &tex_path );
// Destructor
~SGCloudLayer( void );
float getSpan_m () const;
void setSpan_m (float span_m);
float getElevation_m () const;
void setElevation_m (float elevation_m);
float getThickness_m () const;
void setThickness_m (float thickness_m);
float getTransition_m () const;
void setTransition_m (float transition_m);
Type getType () const;
void setType (Type type);
// build the cloud object
void build( double size, double asl, double thickness,
double transition, ssgSimpleState *state );
void rebuild();
// repaint the cloud colors based on current value of sun_angle,
// sky, and fog colors. This updates the color arrays for
@@ -101,9 +90,34 @@ public:
// draw the cloud layer
void draw();
inline float get_asl() const { return layer_asl; }
inline float get_thickness() const { return layer_thickness; }
inline float get_transition() const { return layer_transition; }
private:
static ssgSimpleState *layer_states[SG_MAX_CLOUD_TYPES];
static int layer_sizes[SG_MAX_CLOUD_TYPES];
ssgRoot *layer_root;
ssgTransform *layer_transform;
ssgLeaf * layer;
ssgColourArray *cl;
ssgVertexArray *vl;
ssgTexCoordArray *tl;
// height above sea level (meters)
SGPath texture_path;
float layer_span;
float layer_asl;
float layer_thickness;
float layer_transition;
Type layer_type;
float scale;
// for handling texture coordinates to simulate cloud movement
// from winds, and to simulate the clouds being tied to ground
// position, not view position
// double xoff, yoff;
double last_lon, last_lat;
};

View File

@@ -0,0 +1,3 @@
.deps
Makefile
Makefile.in

View File

@@ -0,0 +1,42 @@
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 \
mat16fv.cpp \
tri.cpp \
plane.cpp \
camera.cpp \
camutils.cpp \
minmaxbox.cpp \
SkyMinMaxBox.cpp \
SkyLight.cpp \
SkyMaterial.cpp \
SkyTextureManager.cpp \
SkyTextureState.cpp \
SkyDynamicTextureManager.cpp \
SkyRenderableInstanceCloud.cpp \
SkyRenderableInstanceGroup.cpp \
SkyCloud.cpp \
SkyArchive.cpp \
SkyUtil.cpp \
SkyContext.cpp \
SkySceneManager.cpp \
SkySceneLoader.cpp
INCLUDES = -I$(top_srcdir)

View File

@@ -0,0 +1,19 @@
//============================================================================
// File : SkyAABBTree.hpp
//
// Author : Wesley Hunt
//
// Content : axis-aligned bounding box tree
//
//============================================================================
#ifndef __SKYAABBTREE_HPP__
#define __SKYAABBTREE_HPP__
#include "SkyBVTree.hpp"
#include "SkyBVTreeSplitter.hpp"
template <class object>
class SkyAABBTree : public SkyBVTree<object, SkyMinMaxBox, SkyAABBTreeSplitter<object> >
{};
#endif //__SKYAABBTREE_HPP__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,243 @@
//------------------------------------------------------------------------------
// File : SkyArchive.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyArchive.hpp
*
* A hierarchical archive Class for storing data.
*/
#ifndef __SKYARCHIVE_HPP__
#define __SKYARCHIVE_HPP__
// #pragma warning( disable : 4786 )
#include "vec2f.hpp"
#include "vec3f.hpp"
#include "vec4f.hpp"
#include "SkyUtil.hpp"
#include <map> // for std::multimap
//! Types supported by the archive system
enum SkyArchiveTypeCode
{
BOOL_TYPE,
INT8_TYPE,
INT16_TYPE,
INT32_TYPE,
UINT8_TYPE,
UINT16_TYPE,
UINT32_TYPE,
FLOAT32_TYPE,
FLOAT64_TYPE,
STRING_TYPE,
VEC2F_TYPE,
VEC3F_TYPE,
VEC4F_TYPE,
ARCHIVE_TYPE,
ANY_TYPE,
NULL_TYPE
};
struct SkyArchiveEntry;
struct StringLessFunctor
{
bool operator() (const char* p1, const char* p2) const
{
return ::strcmp( p1, p2) < 0;
}
};
//============================================================================
//
// Class : SkyArchive
//
//! A simple hierarchical archive file useful for loading and saving data.
//
/*! SkyArchive bundles information so that an application can store,
manipulate, and retrieve data in a storage-independent manner. Information
stored in an SkyArchive file can be modified without breaking
compatibility with the code that retrieves the data. In essence, it can be
thought of as a very basic database mechanism.
A SkyArchive is simply a container. The class defines methods that allow
you to put information in a SkyArchive, determine the information in a
SkyArchive, and retrieve information from a SkyArchive. It's important
to note that the SkyArchive is a recursive storage mechanism; a
SkyArchive itself can hold one or more other SkyArchives.
Data are added to an archive in fields. The datum in a field is associated
with a name, number of bytes, and a type code. The name can be anything you
choose and is not required to be unique. The number of bytes must be accurate.
The type code must be one of the SkyArchiveTypeCode enums. Several of the Add
functions have been specialized for the common base types. It isn't necessary
to provide the number of bytes when using the specialized functions, since it can be
inferred from the type code.
The functions that retrieve fields from an archive are similar to the ones
that add data, only their roles are reversed. As with the Add functions,
there are several specialized functions for the common base types while
custom information can be retrieved using the generic FindData function.
Querying the contents of an archive is provided through the GetInfo
functions. These functions are important as they allow you to write
code that can intelligently determine how to retrieve information at
run-time: you no longer have to hardcode the order in which you retrieve
data from your files.
archive data fields are held in using an STL multimap. The multimap key
is a QString (field name) and the data is held in a SkyArchiveEntry
structure (see SkyArchive.cpp for details of this structure).
The fields are stored in alphabetical order based on the key names.
*/
class SkyArchive
{
public:
//=========================================================================
// Creation & Destruction
//=========================================================================
// Empty archive: no name, no data fields.
SkyArchive();
// Creates a named archive with no data fields.
SkyArchive( const char* pName);
// Deep copy the contents of one archive to another.
SkyArchive( const SkyArchive& src);
// Deep copy the contents of one archive to another.
SkyArchive& operator=( const SkyArchive& src);
~SkyArchive();
//=========================================================================
// Basic SkyArchive Information
//=========================================================================
// Returns true if the archive contains no data fields.
bool IsEmpty() const;
//! Returns the archive's name.
const char* GetName() const { return _pName; };
//=========================================================================
// Adding Content to SkyArchive
//=========================================================================
// Adds a new datafield to the archive.
SKYRESULT AddData(const char* pName,
SkyArchiveTypeCode eType,
const void* pData,
unsigned int iNumBytes,
unsigned int iNumItems = 1);
SKYRESULT AddBool( const char* pName, bool aBool);
SKYRESULT AddInt8( const char* pName, char anInt8);
SKYRESULT AddInt16( const char* pName, short anInt16);
SKYRESULT AddInt32( const char* pName, int anInt32);
SKYRESULT AddUInt8( const char* pName, unsigned char anUInt8);
SKYRESULT AddUInt16( const char* pName, unsigned short anUInt16);
SKYRESULT AddUInt32( const char* pName, unsigned int anUInt32);
SKYRESULT AddFloat32( const char* pName, float aFloat32);
SKYRESULT AddFloat64( const char* pName, double aFloat64);
SKYRESULT AddString( const char* pName, const char* pString);
SKYRESULT AddArchive( const SkyArchive& anArchive);
// Vector types (MJH:: only supports float versions for now!!!)
SKYRESULT AddVec2f( const char* pName, const Vec2f& aPoint2f);
SKYRESULT AddVec3f( const char* pName, const Vec3f& aPoint3f);
SKYRESULT AddVec4f( const char* pName, const Vec4f& aPoint4f);
//=========================================================================
// Retrieving Content from SkyArchive
//=========================================================================
// Retrieves the specified datafield the archive, if it exists.
SKYRESULT FindData( const char* pName,
SkyArchiveTypeCode eType,
void** const pData,
unsigned int* pNumBytes,
unsigned int index = 0) const;
SKYRESULT FindBool( const char* pName, bool* pBool, unsigned int index = 0) const;
SKYRESULT FindInt8( const char* pName, char* pInt8, unsigned int index = 0) const;
SKYRESULT FindInt16( const char* pName, short* pInt16, unsigned int index = 0) const;
SKYRESULT FindInt32( const char* pName, int* pInt32, unsigned int index = 0) const;
SKYRESULT FindUInt8( const char* pName, unsigned char* pUInt8, unsigned int index = 0) const;
SKYRESULT FindUInt16( const char* pName, unsigned short* pUInt16, unsigned int index = 0) const;
SKYRESULT FindUInt32( const char* pName, unsigned int* pUInt32, unsigned int index = 0) const;
SKYRESULT FindFloat32(const char* pName, float* pFloat32, unsigned int index = 0) const;
SKYRESULT FindFloat64(const char* pName, double* pFloat64, unsigned int index = 0) const;
SKYRESULT FindString( const char* pName, char** const pString, unsigned int index = 0) const;
SKYRESULT FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index = 0) const;
SKYRESULT FindVec2f( const char* pName, Vec2f* pVec2f, unsigned int index = 0) const;
SKYRESULT FindVec3f( const char* pName, Vec3f* pVec3f, unsigned int index = 0) const;
SKYRESULT FindVec4f( const char* pName, Vec4f* pVec4f, unsigned int index = 0) const;
SKYRESULT AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index = 0) const;
//=========================================================================
// Querying Contents of SkyArchive
//=========================================================================
// Computes the number of fields that contain the given name and type.
SKYRESULT GetInfo(const char* pName,
SkyArchiveTypeCode eType,
unsigned int* pNumFound = NULL) const;
// Returns information about the key at the specified index.
SKYRESULT GetInfo(unsigned int iNameIndex,
char** pNameFound,
SkyArchiveTypeCode* pTypeCode,
unsigned int* pNumFound);
// Computes the number of unique key names in _dataTableable.
unsigned int GetNumUniqueNames() const;
// Remove the contents of the SkyArchive.
SKYRESULT MakeEmpty();
// Loads the contents from a file.
SKYRESULT Load(const char* pFileName);
// Commits the contents of a SkyArchive to file storage.
SKYRESULT Save(const char* pFileName) const;
private:
char* _pName; // this archive's name
//=========================================================================
// Data storage
//=========================================================================
typedef std::multimap<char*, SkyArchiveEntry*, StringLessFunctor> SkyArchiveMMap;
typedef SkyArchiveMMap::const_iterator SkyMMapConstIter;
typedef SkyArchiveMMap::iterator SkyMMapIter;
SkyArchiveMMap _dataTable; // this is where the data reside.
// Performs a deep-copy of one archive's archive_mmap_t to another.
void _CopyDataTable( const SkyArchiveMMap& src);
// Locates an archive entry in _dataTable
const SkyArchiveEntry* _FindEntry( const char* pName,
unsigned int index,
SkyArchiveTypeCode eType) const;
// Saves the archive to a file stream.
SKYRESULT _Save(FILE* pDestFile) const;
// Initializes the archive from a file stream.
SKYRESULT _Load(FILE* pSrcFile);
};
#endif //__SKYARCHIVE_HPP__

View File

@@ -0,0 +1,297 @@
//------------------------------------------------------------------------------
// File : SkyBVTree.hpp
//------------------------------------------------------------------------------
// Empyrean / SkyWorks : Copyright 2002 Mark J. Harris
//------------------------------------------------------------------------------
/**
* @file SkyBVTree.hpp
*
* This source was written by Wesley Hunt. Many thanks to him for providing it.
*/
//-----------------------------------------------------------------------------
// SkyBVTree.hpp
//
// Author: Wesley Hunt (hunt@cs.unc.edu)
// Date: 2000/12/19
//-----------------------------------------------------------------------------
// Overview
// --------
// declare an SkyBVTree with whatever object type and bounding volume type you
// want. The hard part is to pass in a NodeSplitter class that determines how
// to split a node up. See below for a description of its requirements.
// Finally, use that tree like so:
// * BeginTree()
// * AddObject(Object, ObjectBV)
// * ...
// * EndTree()
// < Do whatever you want with GetRoot() >
// < Use GetLeftChild() and GetRightChild() to traverse the nodes >
//
// The class hierarchy is designed for a flexible, simple public interface.
// This pushes some extra complexity into the class hierarchy, but there are two
// main advantages to the final approach:
// 1. There are no interface requirements for the Object and BoundingVolume
// template parameters. This means you don't have to modify your existing
// class interfaces to use them with the tree.
// 2. All the dependent logic for dealing with the bounding volumes is pushed
// into the NodeSplitter class. So there is one centralized location for
// adapting your bounding volume classes to work with the tree. See the
// description of the NodeSplitter template requirements for more details.
//
// Class Descriptions
// ------------------
//
// SkyBaseBVTree
// -------------
// declares the node class that the tree holds. It exposes
// the public functions of the nodes and defines protected accessors that
// the derived tree class can use to manipulate nodes and build the tree.
//
// Node
// ----
// This is the class that gives access to the tree. You can access each
// object and bounding volume owned by a node, along with that node's
// children.
//
// NodeObject
// ----------------
// An aggregation of an object and its associated bounding volume.
// Each node in the tree essentially owns an array of NodeObjects. This
// array is passed to the NodeSplitter class to allow it to examine a
// node's contained objects before making a decision on how to split the
// node up.
//
// SkyBVTree
// ---------
// The main tree class. To use it, supply and object type, a bounding volume
// type, and a NodeSplitter class that is used to split the nodes up during
// tree construction.
//
// Template class requirements
// ---------------------------
//
// Object
// ------
// None
//
// BoundingVolume
// --------------
// None
//
// NodeSplitter
// ------------
// This is the user-supplied class that decides how to split a node during
// tree construction. It is given an array of NodeObjects that the node owns and
// is responsible for determining the node's bounding volume as well as how to
// split the node up into left and right children.
// The required API is as follows:
//
// * a constructor that takes an array of NodeObject and an unsigned int giving
// the size of the array. These are the objects owned by the node to be split.
// * a method GetNodeBV() that returns the BoundingVolume of the node.
// Typically this is the union of the bounding volumes of the objects owned
// by the node.
// * A unary function operator used to partition the objects in the node. The
// operator must take a single NodeObject as a parameter and return as
// a bool whether to place the NodeObject in the left or right child.
// Basically, it should be compatible with std::partition using NodeObjects.
// * A binary function operator used to sort the objects. If a partition fails,
// the nodes are then sorted based on this function and half are sent to each child.
// This operator must define a total ordering of the NodeObjects.
// Basically, it should be compatible with std::sort using NodeObjects.
//
// Example:
// struct NodeSplitter
// {
// NodeSplitter(const NodeObject* objs, unsigned int numObjs);
// BoundingVolume& GetNodeBV() const;
// // Partition predicate
// bool operator()(const NodeObject& obj) const;
// // Sort predicate
// bool operator()(const NodeObject& obj1, const NodeObject& obj2) const;
// };
//
//-----------------------------------------------------------------------------
#ifndef __SKYBVTREE_HPP__
#define __SKYBVTREE_HPP__
#include <algorithm>
#include <vector>
//-----------------------------------------------------------------------------
// SkyBaseBVTree<Object, BoundingVolume>
//-----------------------------------------------------------------------------
// See header description for details.
//-----------------------------------------------------------------------------
template <class Object, class BoundingVolume>
class SkyBaseBVTree
{
public:
typedef BoundingVolume BV;
class NodeObject;
public:
class Node
{
friend class SkyBaseBVTree<Object, BoundingVolume>;
public:
Node() : _pObjs(NULL), _iNumObjs(0) {}
Node(NodeObject* pObjs, unsigned int iNumObjs) : _pObjs(pObjs), _iNumObjs(iNumObjs) {}
// Public interface
const Object& GetObj(unsigned int index) const { assert(_iNumObjs != 0 && _pObjs != NULL && index < _iNumObjs); return _pObjs[index].GetObj(); }
const BV& GetBV(unsigned int index) const { assert(_iNumObjs != 0 && _pObjs != NULL && index < _iNumObjs); return _pObjs[index].GetBV(); }
unsigned int GetNumObjs() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _iNumObjs; }
const BV& GetNodeBV() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _volume; }
const Node* GetLeftChild() const { assert(_iNumObjs != 0 && _pObjs != NULL); return this+1; }
const Node* GetRightChild() const { assert(_iNumObjs != 0 && _pObjs != NULL); return this+(GetLeftChild()->GetNumObjs()<<1); }
bool IsLeaf() const { assert(_iNumObjs != 0 && _pObjs != NULL); return _iNumObjs == 1; }
private:
// List of Objects owned by the node
NodeObject *_pObjs;
unsigned int _iNumObjs;
BV _volume;
};
public:
class NodeObject
{
public:
NodeObject(const Object& o, const BV& v) : _obj(o), _volume(v) {}
const Object& GetObj() const { return _obj; }
const BV& GetBV() const { return _volume; }
private:
Object _obj;
BV _volume;
};
protected:
// Give non-const access to the node for descendant classes to build the tree
BV& GetNodeBV(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode->_volume; }
Node* GetLeftChild(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode+1; }
Node* GetRightChild(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode+(GetLeftChild(pNode)->GetNumObjs()<<1); }
NodeObject* GetObjs(Node* pNode) { assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL); return pNode->_pObjs; }
// Links a node's children by assigning the given number of objects to each child
// assumes the node has already had it's objects partitioned
void LinkNodeChildren(Node* pNode, unsigned int iLeftNumObjs)
{
assert(pNode->_iNumObjs != 0 && pNode->_pObjs != NULL);
GetLeftChild(pNode)->_pObjs = pNode->_pObjs;
GetLeftChild(pNode)->_iNumObjs = iLeftNumObjs;
GetRightChild(pNode)->_pObjs = pNode->_pObjs + iLeftNumObjs;
GetRightChild(pNode)->_iNumObjs = pNode->_iNumObjs - iLeftNumObjs;
}
};
//------------------------------------------------------------------------------
// Function : ClearVector
// Description :
//------------------------------------------------------------------------------
/**
* @fn ClearVector(std::vector<T>& vec)
* @brief This utility function uses the std::vector::swap trick to free the memory of a vector
*
* This is necessary since clear() doesn't actually free anything.
*/
template<class T>
void ClearVector(std::vector<T>& vec)
{
std::vector<T>().swap(vec);
}
//-----------------------------------------------------------------------------
// SkyBVTree<Object, BoundingVolume, NodeSplitter>
//-----------------------------------------------------------------------------
// See header description for details.
//-----------------------------------------------------------------------------
template <class Object, class BoundingVolume, class NodeSplitter>
class SkyBVTree : public SkyBaseBVTree<Object, BoundingVolume>
{
public:
typedef SkyBaseBVTree<Object, BoundingVolume> BaseTree;
typedef BaseTree::BV BV;
typedef BaseTree::NodeObject NodeObject;
typedef BaseTree::Node Node;
void Clear()
{
BeginTree();
}
void BeginTree(unsigned int iNumObjs = 0)
{
ClearVector(_objList);
ClearVector(_nodes);
if (iNumObjs > 0) _objList.reserve(iNumObjs);
}
void AddObject(const Object &obj, const BV& volume)
{
_objList.push_back(NodeObject(obj, volume));
}
void EndTree()
{
if (_objList.size() == 0) return;
// Initialize the root node with all the objects
_nodes.push_back(Node(&_objList[0], _objList.size()));
// create room for the other nodes. They are initialized in BuildTree().
_nodes.reserve(_objList.size()*2-1);
_nodes.resize(_objList.size()*2-1);
BuildTree(&_nodes[0]);
}
const Node *GetRoot() const { return _nodes.empty() ? NULL : &_nodes[0]; }
// Memory usage info
unsigned int CalcMemUsage() const
{
unsigned int usage = 0;
usage += sizeof(*this);
usage += _objList.capacity() * sizeof(_objList[0]);
usage += _nodes.capacity() * sizeof(_nodes[0]);
return usage;
}
public:
private:
// Does the real work
void BuildTree(Node *pCurNode)
{
int iLeftNumObjs;
{
// Initialize the node splitter with the current node
NodeSplitter splitter(GetObjs(pCurNode), pCurNode->GetNumObjs());
// set the node's bounding volume using the splitter
GetNodeBV(pCurNode) = splitter.GetNodeBV();
// When a node has one object we can stop
if (pCurNode->GetNumObjs() == 1) return;
// Try and partition the objects
iLeftNumObjs = std::partition(GetObjs(pCurNode), &GetObjs(pCurNode)[pCurNode->GetNumObjs()], splitter) - GetObjs(pCurNode);
if ((iLeftNumObjs == 0) || (iLeftNumObjs == pCurNode->GetNumObjs()))
{
// Partition failed. Sort and split again to force a complete tree
std::sort(GetObjs(pCurNode), &GetObjs(pCurNode)[pCurNode->GetNumObjs()], splitter);
iLeftNumObjs = pCurNode->GetNumObjs() / 2;
}
}
LinkNodeChildren(pCurNode, iLeftNumObjs);
BuildTree(GetLeftChild(pCurNode));
BuildTree(GetRightChild(pCurNode));
}
std::vector<Node> _nodes;
std::vector<NodeObject> _objList;
};
#endif //__SKYBVTREE_HPP__

View File

@@ -0,0 +1,242 @@
//============================================================================
// File : SkyBVTreeSplitter.hpp
//
// Author : Wesley Hunt
//
// Content : NodeSplitter classes for SkyBVTrees using SkyBoundingBox or
// SkyBoundingSphere (not implemented).
//
//============================================================================
#ifndef __SKYBVTREESPLITTER_HPP__
#define __SKYBVTREESPLITTER_HPP__
//----------------------------------------------------------------------------
//-- Includes ----------------------------------------------------------------
//----------------------------------------------------------------------------
#include "SkyBVTree.hpp"
#include "SkyMinMaxBox.hpp"
//#include <Mlx/MlxBoundingSphere.hpp>
//#if _MSC_VER == 1200
//#include <Auxlib/AuxCompileTimeChecker.hpp>
//#endif
//----------------------------------------------------------------------------
//-- Forward Declarations ----------------------------------------------------
//----------------------------------------------------------------------------
// A strategy for splitting nodes compatible with bounding boxes and spheres.
template<class Object> class SkyBoundingBoxSplitter;
// SkyBVTree compatible node splitters implemented using the above strategy.
template<class Object> class SkyAABBTreeSplitter;
//template<class Object> class SkySphereTreeSplitter;
//----------------------------------------------------------------------------
//-- Defines, Constants, Enumerated Types ------------------------------------
//----------------------------------------------------------------------------
const float rLongObjectPercentageTolerance = 0.75f;
//----------------------------------------------------------------------------
// SkyBoundingBoxSplitter
//----------------------------------------------------------------------------
// This class defines a NodeSplitter strategy that has the functionality
// required by SkyBVTree's NodeSplitter template class. Can be used with
// SkyMinMaxBox and SkyBoundingSphere.
//
// It defines a two-tiered split strategy:
//
// * First it tries to separate large objects from any smaller objects.
// * If there are no large objects, it splits along the midpoint of the longest
// axis defined by the objects.
// * Finally, if all else fails, it defines a total ordering along the longest
// axis based on the center of each node.
//----------------------------------------------------------------------------
template<class Object>
class SkyBoundingBoxSplitter
{
public:
typedef SkyBaseBVTree<Object, SkyMinMaxBox>::NodeObject NodeObjectBox;
//typedef SkyBaseBVTree<Object, SkyBoundingSphere>::NodeObject NodeObjectSphere;
#if _MSC_VER == 1200
// !!! WRH HACK MSVC++6 SP5 Workaround.
// VC6 can't disambiguate this constructor because it doesn't consider the two
// NodeObject templates to be different classes for the purposes of
// overloading. It won't recognize that the second template parameters are
// different. Forcing them to be explicit template specializations fixes
// the problem.
template<class BV>
SkyBoundingBoxSplitter(const SkyBaseBVTree<Object, BV>::NodeObject*, unsigned int)
{
//AUX_STATIC_CHECK(false, VisualC_6_WorkAround); ???
}
template<>
#endif
SkyBoundingBoxSplitter(const NodeObjectBox* pObjs, unsigned int iNumObjs)
{
for (unsigned int i = 0; i < iNumObjs; ++i)
{
_nodeBBox.Union(pObjs[i].GetBV());
}
Init(pObjs, iNumObjs);
}
/*#if _MSC_VER == 1200
template<>
#endif
SkyBoundingBoxSplitter(const NodeObjectSphere* objs,
#ifdef _PLATFORM_XBOX
Int32
#else
UInt32
#endif
numObjs)
{
for (int i=0; i<numObjs; ++i)
{
SkyMinMaxBox box;
box.AddPoint(objs[i].GetBV().GetCenter());
box.Bloat(objs[i].GetBV().GetRadius());
_nodeBBox.Union(box);
}
Init(objs, numObjs);
}*/
template<class nodeObj>
bool SplitLeft(const nodeObj& obj) const
{
if (_bIsolateLongObjects)
return GetSplitAxisLength(obj.GetBV()) < _rMaxObjectLength;
else
return GetSplitAxisCenter(obj.GetBV()) < _rSplitValue;
}
template<class nodeObj>
bool LessThan(const nodeObj& obj1, const nodeObj& obj2) const
{
return GetSplitAxisCenter(obj1.GetBV()) < GetSplitAxisCenter(obj2.GetBV());
}
const SkyMinMaxBox& GetNodeBBox() const { return _nodeBBox; }
private:
template<class nodeObj>
void Init(const nodeObj* pObjs, unsigned int iNumObjs)
{
_iSplitAxis = FindSplitAxis(_nodeBBox);
_rSplitValue = FindSplitValue(_nodeBBox, _iSplitAxis);
_rMaxObjectLength = GetSplitAxisLength(_nodeBBox) * rLongObjectPercentageTolerance;
_bIsolateLongObjects = false;
for (unsigned int i = 0; i < iNumObjs; ++i)
{
if (GetSplitAxisLength(pObjs[i].GetBV()) > _rMaxObjectLength)
{
_bIsolateLongObjects = true;
break;
}
}
}
int FindSplitAxis(const SkyMinMaxBox& bbox)
{
int iAxis = 0, i;
Vec3f vecExt = bbox.GetMax() - bbox.GetMin();
for (i = 1; i < 3; ++i) if (vecExt[i] > vecExt[iAxis]) iAxis = i;
return iAxis;
}
float FindSplitValue(const SkyMinMaxBox& bbox, int iSplitAxis)
{
return (bbox.GetMin()[iSplitAxis] + bbox.GetMax()[iSplitAxis])*0.5f;
}
/*float GetSplitAxisLength(const SkyBoundingSphere& sphere) const
{
return 2.f*sphere.GetRadius();
}*/
float GetSplitAxisLength(const SkyMinMaxBox& bbox) const
{
return bbox.GetMax()[_iSplitAxis] - bbox.GetMin()[_iSplitAxis];
}
float GetSplitAxisCenter(const SkyMinMaxBox& bbox) const
{
return (bbox.GetMin()[_iSplitAxis] + bbox.GetMax()[_iSplitAxis]) * 0.5f;
}
/*float GetSplitAxisCenter(const SkyBoundingSphere& sphere) const
{
return sphere.GetCenter()[SplitAxis];
}*/
int _iSplitAxis;
float _rSplitValue;
bool _bIsolateLongObjects;
float _rMaxObjectLength;
SkyMinMaxBox _nodeBBox;
};
//----------------------------------------------------------------------------
// SkyAABBTreeSplitter
//----------------------------------------------------------------------------
// A NodeSplitter that is compatible with SkyBVTree for SkyMinMaxBox.
// Implemented using the SkyBoundingBoxSplitter strategy.
//----------------------------------------------------------------------------
template<class Object>
class SkyAABBTreeSplitter
{
public:
typedef SkyMinMaxBox BV;
typedef SkyBaseBVTree<Object, BV>::NodeObject NodeObject;
SkyAABBTreeSplitter(const NodeObject* pObjs, unsigned int iNumObjs) : _splitter(pObjs, iNumObjs) {}
const BV& GetNodeBV() const { return _splitter.GetNodeBBox(); }
bool operator()(const NodeObject& obj) const
{
return _splitter.SplitLeft(obj);
}
bool operator()(const NodeObject& obj1, const NodeObject& obj2) const
{
return _splitter.LessThan(obj1, obj2);
}
private:
SkyBoundingBoxSplitter<Object> _splitter;
};
//----------------------------------------------------------------------------
// SkySphereTreeSplitter
//----------------------------------------------------------------------------
// A NodeSplitter that is compatible with SkyBVTree for SkyBoundingSphere.
// Implemented using the SkyBoundingBoxSplitter strategy.
//----------------------------------------------------------------------------
/*template<class Object>
class SkySphereTreeSplitter
{
public:
typedef SkyBoundingSphere BV;
typedef SkyBaseBVTree<Object, BV>::NodeObject NodeObject;
MlxSphereTreeSplitter(const NodeObject* pObjs, unsigned int iNumObjs) : _splitter(pObjs, iNumObjs)
{
_nodeBV = pObjs[0].GetBV();
for (unsigned int i = 1; i < iNumObjs; ++i) _nodeBV.Union(pObjs[i].GetBV());
}
const BV& GetNodeBV() const { return _nodeBV; }
bool operator()(const NodeObject& obj) const
{
return _splitter.SplitLeft(obj);
}
bool operator()(const NodeObject& obj1, const NodeObject& obj2) const
{
return _splitter.LessThan(obj1, obj2);
}
private:
BV _nodeBV;
SkyBoundingBoxSplitter<Object> _splitter;
};*/
#endif //__SKYBVTREESPLITTER_HPP__

View File

@@ -0,0 +1,151 @@
//------------------------------------------------------------------------------
// File : SkyBoundingVolume.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyBoundingVolume.hpp
*
* Base class interface definition for a bounding volume.
*/
#ifndef __SKYBOUNDINGVOLUME_HPP__
#define __SKYBOUNDINGVOLUME_HPP__
#include "vec3f.hpp"
#include "mat44.hpp"
// forward to reduce unnecessary dependencies
class Camera;
//------------------------------------------------------------------------------
/**
* @class SkyBoundingVolume
* @brief An abstract base class for bounding volumes (AABB,OBB,Sphere,etc.)
*
* This base class maintains a center and a radius, so it is effectively a bounding
* sphere. Derived classes may represent other types of bounding volumes, but they
* should be sure to update the radius and center, because some objects will treat
* all bounding volumes as spheres.
*
*/
class SkyBoundingVolume
{
public:
//! Constructor
SkyBoundingVolume() : _vecCenter(0, 0, 0), _rRadius(0) {}
//! Destructor
virtual ~SkyBoundingVolume() {}
//------------------------------------------------------------------------------
// Function : SetCenter
// Description :
//------------------------------------------------------------------------------
/**
* @fn SetCenter(const Vec3f &center)
* @brief Sets the center of the bounding volume.
*/
virtual void SetCenter(const Vec3f &center) { _vecCenter = center; }
//------------------------------------------------------------------------------
// Function : SetRadius
// Description :
//------------------------------------------------------------------------------
/**
* @fn SetRadius(float radius)
* @brief Sets the radius of the bounding volume.
*/
virtual void SetRadius(float radius) { _rRadius = radius; }
//------------------------------------------------------------------------------
// Function : Vec3f& GetCenter
// Description :
//------------------------------------------------------------------------------
/**
* @fn Vec3f& GetCenter() const
* @brief Returns the center of the bounding volume.
*/
virtual const Vec3f& GetCenter() const { return _vecCenter; }
//------------------------------------------------------------------------------
// Function : GetRadius
// Description :
//------------------------------------------------------------------------------
/**
* @fn GetRadius() const
* @brief Returns the radius ofthe bounding volume.
*/
virtual float GetRadius() const { return _rRadius; }
//------------------------------------------------------------------------------
// Function : ViewFrustumCull
// Description :
//------------------------------------------------------------------------------
/**
* @fn ViewFrustumCull( const Camera &cam, const Mat44f &mat )
* @brief Cull a bounding volume.
*
* Returns false if the bounding volume is entirely outside the camera's frustum,
* true otherwise.
*/
virtual bool ViewFrustumCull( const Camera &cam, const Mat44f &mat ) = 0;
//------------------------------------------------------------------------------
// Function : AddPoint
// Description :
//------------------------------------------------------------------------------
/*
* @fn AddPoint( const Vec3f &pt )
* @brief Add a point to a bounding volume.
*
* One way to create a bounding volume is to add points. What should/could happen
* is that the BV will store an object space BV and then when a call to SetPosition
* is called, the stored values will be transformed and stored separately, so that
* the original values always exist.
*
*/
//virtual void AddPoint( const Vec3f &point ) = 0;
//------------------------------------------------------------------------------
// Function : AddPoint
// Description :
//------------------------------------------------------------------------------
/*
* @fn AddPoint( float x, float y, float z )
* @brief Add a point to a bounding volume.
*
* @see AddPoint(const Vec3f &pt)
*/
//virtual void AddPoint( float x, float y, float z ) = 0;
//------------------------------------------------------------------------------
// Function : Clear
// Description :
//------------------------------------------------------------------------------
/*
* @fn Clear()
* @brief Clear all data from the bounding volume.
*/
//virtual void Clear() = 0;
protected:
Vec3f _vecCenter;
float _rRadius;
};
#endif //__SKYBOUNDINGVOLUME_HPP__

View File

@@ -0,0 +1,980 @@
//------------------------------------------------------------------------------
// File : SkyCloud.cpp
//------------------------------------------------------------------------------
// SkyWorks : Adapted from skyworks program writen by Mark J. Harris and
// The University of North Carolina at Chapel Hill
// : by J. Wojnaroski Sep 2002
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyCloud.cpp
*
* Implementation of class SkyCloud.
*/
// warning for truncation of template name for browse info
#pragma warning( disable : 4786)
#include "SkyCloud.hpp"
#include "SkyRenderableInstance.hpp"
#include "SkyContext.hpp"
#include "SkyMaterial.hpp"
#include "SkyLight.hpp"
#include "SkyTextureManager.hpp"
#include "SkySceneManager.hpp"
#include <algorithm>
//! The version used for cloud archive files.
#define CLOUD_ARCHIVE_VERSION 0.1f
//------------------------------------------------------------------------------
// Static initialization
//------------------------------------------------------------------------------
SkyMaterial* SkyCloud::s_pMaterial = NULL;
SkyMaterial* SkyCloud::s_pShadeMaterial = NULL;
unsigned int SkyCloud::s_iShadeResolution = 32;
float SkyCloud::s_rAlbedo = 0.9f;
float SkyCloud::s_rExtinction = 80.0f;
float SkyCloud::s_rTransparency = exp(-s_rExtinction);
float SkyCloud::s_rScatterFactor = s_rAlbedo * s_rExtinction * SKY_INV_4PI;
float SkyCloud::s_rSortAngleErrorTolerance = 0.8f;
float SkyCloud::s_rSortSquareDistanceTolerance = 100;
//------------------------------------------------------------------------------
// Function : SkyCloud::SkyCloud
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::SkyCloud()
* @brief Constructor.
*/
SkyCloud::SkyCloud()
: SkyRenderable(),
_bUsePhaseFunction(true),
_vecLastSortViewDir(Vec3f::ZERO),
_vecLastSortCamPos(Vec3f::ZERO)
{
if (!s_pShadeMaterial)
{
s_pShadeMaterial = new SkyMaterial;
s_pShadeMaterial->SetAmbient(Vec4f(0.1f, 0.1f, 0.1f, 1));
s_pShadeMaterial->EnableDepthTest(false);
s_pShadeMaterial->SetBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
s_pShadeMaterial->EnableBlending(true);
s_pShadeMaterial->SetAlphaFunc(GL_GREATER);
s_pShadeMaterial->SetAlphaRef(0);
s_pShadeMaterial->EnableAlphaTest(true);
s_pShadeMaterial->SetColorMaterialMode(GL_DIFFUSE);
s_pShadeMaterial->EnableColorMaterial(true);
s_pShadeMaterial->EnableLighting(false);
s_pShadeMaterial->SetTextureApplicationMode(GL_MODULATE);
}
if (!s_pMaterial)
{
s_pMaterial = new SkyMaterial;
s_pMaterial->SetAmbient(Vec4f(0.3f, 0.3f, 0.3f, 1));
s_pMaterial->SetDepthMask(false);
s_pMaterial->SetBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
s_pMaterial->EnableBlending(true);
s_pMaterial->SetAlphaFunc(GL_GREATER);
s_pMaterial->SetAlphaRef(0);
s_pMaterial->EnableAlphaTest(true);
s_pMaterial->SetColorMaterialMode(GL_DIFFUSE);
s_pMaterial->EnableColorMaterial(true);
s_pMaterial->EnableLighting(false);
s_pMaterial->SetTextureApplicationMode(GL_MODULATE);
_CreateSplatTexture(32); // will assign the texture to both static materials
}
}
//------------------------------------------------------------------------------
// Function : SkyCloud::~SkyCloud
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::~SkyCloud()
* @brief Destructor.
*/
SkyCloud::~SkyCloud()
{
}
//------------------------------------------------------------------------------
// Function : SkyCloud::Update
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::Update(const Camera &cam, SkyRenderableInstance* pInstance)
* @brief Currently does nothing.
*/
SKYRESULT SkyCloud::Update(const Camera &cam, SkyRenderableInstance* pInstance)
{
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : DrawQuad
// Description :
//------------------------------------------------------------------------------
/**
* @fn DrawQuad(Vec3f pos, Vec3f x, Vec3f y, Vec4f color)
* @brief Draw a quad.
*/
inline void DrawQuad(Vec3f pos, Vec3f x, Vec3f y, Vec4f color)
{
glColor4fv(&(color.x));
Vec3f left = pos; left -= y;
Vec3f right = left; right += x;
left -= x;
glTexCoord2f(0, 0); glVertex3fv(&(left.x));
glTexCoord2f(1, 0); glVertex3fv(&(right.x));
left += y; left += y;
right += y; right += y;
glTexCoord2f(1, 1); glVertex3fv(&(right.x));
glTexCoord2f(0, 1); glVertex3fv(&(left.x));
}
//------------------------------------------------------------------------------
// Function : SkyCloud::Display
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::Display(const Camera &camera, SkyRenderableInstance *pInstance)
* @brief Renders the cloud.
*
* The cloud is rendered by splatting the particles from back to front with respect
* to @a camera. Since instances of clouds each have their own particles, which
* are pre-transformed into world space, @a pInstance is not used.
*
* An alternative method is to store the particles untransformed, and transform the
* camera and light into cloud space for rendering. This is more complicated,
* and not as straightforward. Since I have to store the particles with each instance
* anyway, I decided to pre-transform them instead.
*/
SKYRESULT SkyCloud::Display(const Camera &camera, SkyRenderableInstance *pInstance)
{
// copy the current camera
Camera cam(camera);
// This cosine computation, along with the if() below, are an optimization. The goal
// is to avoid sorting when it will make no visual difference. This will be true when the
// cloud particles are almost sorted for the current viewpoint. This is the case most of the
// time, since the viewpoint does not move very far in a single frame. Each time we sort,
// we cache the current view direction. Then, each time the cloud is displayed, if the
// current view direction is very close to the current view direction (dot product is nearly 1)
// then we do not resort the particles.
float rCosAngleSinceLastSort =
_vecLastSortViewDir * cam.ViewDir(); // dot product
float rSquareDistanceSinceLastSort =
(cam.Orig - _vecLastSortCamPos).LengthSqr();
if (rCosAngleSinceLastSort < s_rSortAngleErrorTolerance ||
rSquareDistanceSinceLastSort > s_rSortSquareDistanceTolerance)
{
// compute the sort position for particles.
// don't just use the camera position -- if it is too far away from the cloud, then
// precision limitations may cause the STL sort to hang. Instead, put the sort position
// just outside the bounding sphere of the cloud in the direction of the camera.
_vecSortPos = -cam.ViewDir();
_vecSortPos *= (1.1 * _boundingBox.GetRadius());
_vecSortPos += _boundingBox.GetCenter();
// sort the particles from back to front wrt the camera position.
_SortParticles(cam.ViewDir(), _vecSortPos, SKY_CLOUD_SORT_TOWARD);
//_vecLastSortViewDir = GLVU::GetCurrent()->GetCurrentCam()->ViewDir();
//_vecLastSortCamPos = GLVU::GetCurrent()->GetCurrentCam()->Orig;
_vecLastSortViewDir = cam.ViewDir();
_vecLastSortCamPos = cam.Orig;
}
// set the material state / properties that clouds use for rendering:
// Enables blending, with blend func (ONE, ONE_MINUS_SRC_ALPHA).
// Enables alpha test to discard completely transparent fragments.
// Disables depth test.
// Enables texturing, with modulation, and the texture set to the shared splat texture.
s_pMaterial->Activate();
Vec4f color;
Vec3f eyeDir;
// Draw the particles using immediate mode.
glBegin(GL_QUADS);
int i = 0;
for (ParticleIterator iter = _particles.begin(); iter != _particles.end(); iter++)
{
i++;
SkyCloudParticle *p = *iter;
// Start with ambient light
color = p->GetBaseColor();
if (_bUsePhaseFunction) // use the phase function for anisotropic scattering.
{
eyeDir = cam.Orig;
eyeDir -= p->GetPosition();
eyeDir.Normalize();
float pf;
// add the color contribution to this particle from each light source, modulated by
// the phase function. See _PhaseFunction() documentation for details.
for (int i = 0; i < p->GetNumLitColors(); i++)
{
pf = _PhaseFunction(_lightDirections[i], eyeDir);
// expand this to avoid temporary vector creation in the inner loop
color.x += p->GetLitColor(i).x * pf;
color.y += p->GetLitColor(i).y * pf;
color.z += p->GetLitColor(i).z * pf;
}
}
else // just use isotropic scattering instead.
{
for (int i = 0; i < (*iter)->GetNumLitColors(); ++i)
{
color += p->GetLitColor(i);
}
}
// Set the transparency independently of the colors
color.w = 1 - s_rTransparency;
// draw the particle as a textured billboard.
DrawQuad((*iter)->GetPosition(), cam.X * p->GetRadius(), cam.Y * p->GetRadius(), color);
}
glEnd();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyCloud::DisplaySplit
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::DisplaySplit(const Camera &camera, const Vec3f &vecSplitPoint, bool bBackHalf, SkyRenderableInstance *pInstance)
* @brief The same as Display(), except it displays only the particles in front of or behind the split point.
*
* This is used to render clouds into two impostor images for displaying clouds that contain objects.
*
* @see SkyRenderableInstanceCloud
*/
SKYRESULT SkyCloud::DisplaySplit(const Camera &camera,
const Vec3f &vecSplitPoint,
bool bBackHalf,
SkyRenderableInstance *pInstance /* = NULL */)
{
// copy the current camera
Camera cam(camera);
Vec3f vecCloudSpaceSplit = vecSplitPoint;
if (bBackHalf) // only sort when rendering the back half. Reuse sort for front half.
{
// compute the sort position for particles.
// don't just use the camera position -- if it is too far away from the cloud, then
// precision limitations may cause the STL sort to hang. Instead, put the sort position
// just outside the bounding sphere of the cloud in the direction of the camera.
_vecSortPos = -cam.ViewDir();
_vecSortPos *= (1.1 * _boundingBox.GetRadius());
_vecSortPos += _boundingBox.GetCenter();
// sort the particles from back to front wrt the camera position.
_SortParticles(cam.ViewDir(), _vecSortPos, SKY_CLOUD_SORT_TOWARD);
// we can't use the view direction optimization when the cloud is split, or we get a lot
// of popping of objects in and out of cloud cover. For consistency, though, we need to update
// the cached sort direction, since we just sorted the particles.
// _vecLastSortViewDir = GLVU::GetCurrent()->GetCurrentCam()->ViewDir();
// _vecLastSortCamPos = GLVU::GetCurrent()->GetCurrentCam()->Orig;
// compute the split distance.
vecCloudSpaceSplit -= _vecSortPos;
_rSplitDistance = vecCloudSpaceSplit * cam.ViewDir();
}
// set the material state / properties that clouds use for rendering:
// Enables blending, with blend func (ONE, ONE_MINUS_SRC_ALPHA).
// Enables alpha test to discard completely transparent fragments.
// Disables depth test.
// Enables texturing, with modulation, and the texture set to the shared splat texture.
s_pMaterial->Activate();
Vec4f color;
Vec3f eyeDir;
// Draw the particles using immediate mode.
glBegin(GL_QUADS);
// if bBackHalf is false, then we just continue where we left off. If it is true, we
// reset the iterator to the beginning of the sorted list.
static ParticleIterator iter;
if (bBackHalf)
iter = _particles.begin();
// iterate over the particles and render them.
for (; iter != _particles.end(); ++iter)
{
SkyCloudParticle *p = *iter;
if (bBackHalf && (p->GetSquareSortDistance() < _rSplitDistance))
break;
// Start with ambient light
color = p->GetBaseColor();
if (_bUsePhaseFunction) // use the phase function for anisotropic scattering.
{
eyeDir = cam.Orig;
eyeDir -= p->GetPosition();
eyeDir.Normalize();
float pf;
// add the color contribution to this particle from each light source, modulated by
// the phase function. See _PhaseFunction() documentation for details.
for (int i = 0; i < p->GetNumLitColors(); i++)
{
pf = _PhaseFunction(_lightDirections[i], eyeDir);
// expand this to avoid temporary vector creation in the inner loop
color.x += p->GetLitColor(i).x * pf;
color.y += p->GetLitColor(i).y * pf;
color.z += p->GetLitColor(i).z * pf;
}
}
else // just use isotropic scattering instead.
{
for (int i = 0; i < p->GetNumLitColors(); ++i)
{
color += p->GetLitColor(i);
}
}
// set the transparency independently of the colors.
color.w = 1 - s_rTransparency;
// draw the particle as a textured billboard.
DrawQuad((*iter)->GetPosition(), cam.X * p->GetRadius(), cam.Y * p->GetRadius(), color);
}
glEnd();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyCloud::Illuminate
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::Illuminate(SkyLight *pLight, SkyRenderableInstance* pInstance, bool bReset)
* @brief Compute the illumination of the cloud by the lightsource @a pLight
*
* This method uses graphics hardware to compute multiple forward scattering at each cloud
* in the cloud of light from the directional light source @a pLight. The algorithm works
* by successively subtracting "light" from an initially white (fully lit) frame buffer by
* using hardware blending and read back. The method stores the illumination from each light
* source passed to it separately at each particle, unless @a bReset is true, in which case
* the lists of illumination in the particles are reset before the lighting is computed.
*
*/
SKYRESULT SkyCloud::Illuminate(SkyLight *pLight, SkyRenderableInstance* pInstance, bool bReset)
{
int iOldVP[4];
glGetIntegerv(GL_VIEWPORT, iOldVP);
glViewport(0, 0, s_iShadeResolution, s_iShadeResolution);
Vec3f vecDir(pLight->GetDirection());
// if this is the first pass through the lights, reset will be true, and the cached light
// directions should be updated. Light directions are cached in cloud space to accelerate
// computation of the phase function, which depends on light direction and view direction.
if (bReset)
_lightDirections.clear();
_lightDirections.push_back(vecDir); // cache the (unit-length) light direction
// compute the light/sort position for particles from the light direction.
// don't just use the camera position -- if it is too far away from the cloud, then
// precision limitations may cause the STL sort to hang. Instead, put the sort position
// just outside the bounding sphere of the cloud in the direction of the camera.
Vec3f vecLightPos(vecDir);
vecLightPos *= (1.1*_boundingBox.GetRadius());
vecLightPos += _boundingBox.GetCenter();
// Set up a camera to look at the cloud from the light position. Since the sun is an infinite
// light source, this camera will use an orthographic projection tightly fit to the bounding
// sphere of the cloud.
Camera cam;
// Avoid degenerate camera bases.
Vec3f vecUp(0, 1, 0);
if (fabs(vecDir * vecUp) - 1 < 1e-6) // check that the view and up directions are not parallel.
vecUp.Set(1, 0, 0);
cam.LookAt(vecLightPos, _boundingBox.GetCenter(), vecUp);
// sort the particles away from the light source.
_SortParticles(cam.ViewDir(), vecLightPos, SKY_CLOUD_SORT_AWAY);
// projected dist to cntr along viewdir
float DistToCntr = (_boundingBox.GetCenter() - vecLightPos) * cam.ViewDir();
// calc tight-fitting near and far distances for the orthographic frustum
float rNearDist = DistToCntr - _boundingBox.GetRadius();
float rFarDist = DistToCntr + _boundingBox.GetRadius();
// set the modelview matrix from this camera.
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
float M[16];
cam.GetModelviewMatrix(M);
glLoadMatrixf(M);
// switch to parallel projection
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(-_boundingBox.GetRadius(), _boundingBox.GetRadius(),
-_boundingBox.GetRadius(), _boundingBox.GetRadius(),
rNearDist, rFarDist);
// set the material state / properties that clouds use for shading:
// Enables blending, with blend func (ONE, ONE_MINUS_SRC_ALPHA).
// Enables alpha test to discard completely transparent fragments.
// Disables depth test.
// Enables texturing, with modulation, and the texture set to the shared splat texture.
s_pShadeMaterial->Activate();
// these are used for projecting the particle position to determine where to read pixels.
double MM[16], PM[16];
int VP[4] = { 0, 0, s_iShadeResolution, s_iShadeResolution };
glGetDoublev(GL_MODELVIEW_MATRIX, MM);
glGetDoublev(GL_PROJECTION_MATRIX, PM);
// initialize back buffer to all white -- modulation darkens areas where cloud particles
// absorb light, and lightens it where they scatter light in the forward direction.
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float rPixelsPerLength = s_iShadeResolution / (2 * _boundingBox.GetRadius());
// the solid angle over which we will sample forward-scattered light.
float rSolidAngle = 0.09;
int i = 0;
int iNumFailed = 0;
for (ParticleIterator iter = _particles.begin(); iter != _particles.end(); ++iter, ++i)
{
Vec3f vecParticlePos = (*iter)->GetPosition();
Vec3f vecOffset(vecLightPos);
vecOffset -= vecParticlePos;
// compute the pixel area to read back in order to integrate the illumination of the particle
// over a constant solid angle.
float rDistance = fabs(cam.ViewDir() * vecOffset) - rNearDist;
float rArea = rSolidAngle * rDistance * rDistance;
int iPixelDim = sqrt(rArea) * rPixelsPerLength;
int iNumPixels = iPixelDim * iPixelDim;
if (iNumPixels < 1)
{
iNumPixels = 1;
iPixelDim = 1;
}
// the scale factor to convert the read back pixel colors to an average illumination of the area.
float rColorScaleFactor = rSolidAngle / (iNumPixels * 255.0f);
unsigned char *c = new unsigned char[4 * iNumPixels];
Vec3d vecWinPos;
// find the position in the buffer to which the particle position projects.
if (!gluProject(vecParticlePos.x, vecParticlePos.y, vecParticlePos.z,
MM, PM, VP,
&(vecWinPos.x), &(vecWinPos.y), &(vecWinPos.z)))
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"Error: SkyCloud::Illuminate(): failed to project particle position.");
}
// offset the projected window position by half the size of the readback region.
vecWinPos.x -= 0.5 * iPixelDim;
if (vecWinPos.x < 0) vecWinPos.x = 0;
vecWinPos.y -= 0.5 * iPixelDim;
if (vecWinPos.y < 0) vecWinPos.y = 0;
// read back illumination of this particle from the buffer.
glReadBuffer(GL_BACK);
glReadPixels(vecWinPos.x, vecWinPos.y, iPixelDim, iPixelDim, GL_RGBA, GL_UNSIGNED_BYTE, c);
// scattering coefficient vector.
Vec4f vecScatter(s_rScatterFactor, s_rScatterFactor, s_rScatterFactor, 1);
// add up the read back pixels (only need one component -- its grayscale)
int iSum = 0;
for (int k = 0; k < 4 * iNumPixels; k+=4)
iSum += c[k];
delete [] c;
// compute the amount of light scattered to this particle by particles closer to the light.
// this is the illumination over the solid angle that we measured (using glReadPixels) times
// the scattering coefficient (vecScatter);
Vec4f vecScatteredAmount(iSum * rColorScaleFactor,
iSum * rColorScaleFactor,
iSum * rColorScaleFactor,
1 - s_rTransparency);
vecScatteredAmount &= vecScatter;
// the color of th particle (iter) contributed by this light source (pLight) is the
// scattered light from the part of the cloud closer to the light, times the diffuse color
// of the light source. The alpha is 1 - the uniform transparency of all particles (modulated
// by the splat texture).
Vec4f vecColor = vecScatteredAmount;
vecColor &= pLight->GetDiffuse();
vecColor.w = 1 - s_rTransparency;
// add this color to the list of lit colors for the particle. The contribution from each light
// is kept separate because the phase function we apply at runtime depends on the light vector
// for each light source separately. This view-dependent effect is impossible without knowing
// the amount of light contributed for each light. This, of course, assumes the clouds will
// be lit by a reasonably small number of lights (The sun plus some simulation of light reflected
// from the sky and / or ground.) This technique works very well for simulating anisotropic
// illumination by skylight.
if (bReset)
{
(*iter)->SetBaseColor(s_pMaterial->GetAmbient());
(*iter)->ClearLitColors();
(*iter)->AddLitColor(vecColor);
}
else
{
(*iter)->AddLitColor(vecColor);
}
// the following computation (scaling of the scattered amount by the phase function) is done
// after the lit color is stored so we don't add the scattering to this particle twice.
vecScatteredAmount *= 1.5; // rayleigh scattering phase function for angle of zero or 180 = 1.5!
// clamp the color
if (vecScatteredAmount.x > 1) vecScatteredAmount.x = 1;
if (vecScatteredAmount.y > 1) vecScatteredAmount.y = 1;
if (vecScatteredAmount.z > 1) vecScatteredAmount.z = 1;
vecScatteredAmount.w = 1 - s_rTransparency;
vecScatteredAmount.x = 0.50; vecScatteredAmount.y = 0.60; vecScatteredAmount.z = 0.70;
// Draw the particle as a texture billboard. Use the scattered light amount as the color to
// simulate forward scattering of light by this particle.
glBegin(GL_QUADS);
DrawQuad(vecParticlePos, cam.X * (*iter)->GetRadius(), cam.Y * (*iter)->GetRadius(), vecScatteredAmount);
glEnd();
//glutSwapBuffers(); // Uncomment this swap buffers to visualize cloud illumination computation.
}
// Note: here we could optionally store the current back buffer as a shadow image
// to be projected from the light position onto the scene. This way we can have clouds shadow
// the environment.
// restore matrix stack and viewport.
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glViewport(iOldVP[0], iOldVP[1], iOldVP[2], iOldVP[3]);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyCloud::CopyBoundingVolume
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::CopyBoundingVolume() const
* @brief Returns a new copy of the SkyMinMaxBox for this cloud.
*/
SkyMinMaxBox* SkyCloud::CopyBoundingVolume() const
{
SkyMinMaxBox *pBox = new SkyMinMaxBox();
pBox->SetMax(_boundingBox.GetMax());
pBox->SetMin(_boundingBox.GetMin());
return pBox;
}
SKYRESULT SkyCloud::Load(const SkyArchive &archive,
float rScale, /* = 1.0f */
double latitude, double longitude )
{
unsigned int iNumParticles;
Vec3f vecCenter = Vec3f::ZERO;
//Vec3f vecCenter;
//float rRadius;
//archive.FindVec3f("CldCenter", &vecCenter);
//archive.FindFloat32("CldRadius", &rRadius);
//_boundingBox.SetMin(vecCenter - Vec3f(rRadius, rRadius, rRadius));
//_boundingBox.SetMax(vecCenter + Vec3f(rRadius, rRadius, rRadius));
archive.FindUInt32("CldNumParticles", &iNumParticles);
//if (!bLocal)
archive.FindVec3f("CldCenter", &vecCenter);
Vec3f *pParticlePositions = new Vec3f[iNumParticles];
float *pParticleRadii = new float[iNumParticles];
Vec4f *pParticleColors = new Vec4f[iNumParticles];
unsigned int iNumBytes;
archive.FindData("CldParticlePositions", ANY_TYPE, (void**const)&pParticlePositions, &iNumBytes);
archive.FindData("CldParticleRadii", ANY_TYPE, (void**const)&pParticleRadii, &iNumBytes);
archive.FindData("CldParticleColors", ANY_TYPE, (void**const)&pParticleColors, &iNumBytes);
for (unsigned int i = 0; i < iNumParticles; ++i)
{
SkyCloudParticle *pParticle = new SkyCloudParticle((pParticlePositions[i] + vecCenter) * rScale,
pParticleRadii[i] * rScale,
pParticleColors[i]);
_boundingBox.AddPoint(pParticle->GetPosition());
_particles.push_back(pParticle);
}
// this is just a bad hack to align cloud field from skyworks with local horizon at KSFO
// this "almost" works not quite the right solution okay to get some up and running
// we need to develop our own scheme for loading and positioning clouds
Mat33f R;
Vec3f moveit;
R.Set( 0, 1, 0,
1, 0, 0,
0, 0, 1);
// clouds sit in the y-z plane and x-axis is the vertical cloud height
Rotate( R );
// rotate the cloud field about the fgfs z-axis based on initial longitude
float ex = 0.0;
float ey = 0.0;
float ez = 1.0;
float phi = longitude / 57.29578;
float one_min_cos = 1 - cos(phi);
R.Set(
cos(phi) + one_min_cos*ex*ex, one_min_cos*ex*ey - ez*sin(phi), one_min_cos*ex*ez + ey*sin(phi),
one_min_cos*ex*ey + ez*sin(phi), cos(phi) + one_min_cos*ey*ey, one_min_cos*ey*ez - ex*sin(phi),
one_min_cos*ex*ez - ey*sin(phi), one_min_cos*ey*ez + ex*sin(phi), cos(phi) + one_min_cos*ez*ez );
Rotate( R );
// okay now that let's rotate about a vector for latitude where longitude forms the
// components of a unit vector in the x-y plane
ex = sin( longitude / 57.29578 );
ey = -cos( longitude / 57.29578 );
ez = 0.0;
phi = latitude / 57.29578;
one_min_cos = 1 - cos(phi);
R.Set(
cos(phi) + one_min_cos*ex*ex, one_min_cos*ex*ey - ez*sin(phi), one_min_cos*ex*ez + ey*sin(phi),
one_min_cos*ex*ey + ez*sin(phi), cos(phi) + one_min_cos*ey*ey, one_min_cos*ey*ez - ex*sin(phi),
one_min_cos*ex*ez - ey*sin(phi), one_min_cos*ey*ez + ex*sin(phi), cos(phi) + one_min_cos*ez*ez );
Rotate( R );
// need to calculate an offset to place the clouds at ~3000 feet MSL ATM this is an approximation
// to move the clouds to some altitude above sea level. At some locations this could be underground
// will need a better scheme to position clouds per user preferences
float cloud_level_msl = 3000.0f;
float x_offset = ex * cloud_level_msl;
float y_offset = ey * cloud_level_msl;
float z_offset = cloud_level_msl * 0.5;
moveit.Set( x_offset, y_offset, z_offset );
Translate( moveit );
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyCloud::Save
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::Save(SkyArchive &archive) const
* @brief Saves the cloud data to @a archive.
*
* @todo <WRITE EXTENDED SkyCloud::Save FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyCloud::Save(SkyArchive &archive) const
{
SkyArchive myArchive("Cloud");
//myArchive.AddVec3f("CldCenter", _center);
//myArchive.AddFloat32("CldRadius", _boundingBox.GetRadius());
myArchive.AddUInt32("CldNumParticles", _particles.size());
// make temp arrays
Vec3f *pParticlePositions = new Vec3f[_particles.size()];
float *pParticleRadii = new float[_particles.size()];
Vec4f *pParticleColors = new Vec4f[_particles.size()];
unsigned int i = 0;
for (ParticleConstIterator iter = _particles.begin(); iter != _particles.end(); ++iter, ++i)
{
pParticlePositions[i] = (*iter)->GetPosition(); // position around origin
pParticleRadii[i] = (*iter)->GetRadius();
pParticleColors[i] = (*iter)->GetBaseColor();
}
myArchive.AddData("CldParticlePositions",
ANY_TYPE,
pParticlePositions,
sizeof(Vec3f),
_particles.size());
myArchive.AddData("CldParticleRadii",
ANY_TYPE,
pParticleRadii,
sizeof(float),
_particles.size());
myArchive.AddData("CldParticleColors",
ANY_TYPE,
pParticleColors,
sizeof(Vec3f),
_particles.size());
archive.AddArchive(myArchive);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyCloud::Rotate
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::Rotate(const Mat33f& rot)
* @brief @todo <WRITE BRIEF SkyCloud::Rotate DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyCloud::Rotate FUNCTION DOCUMENTATION>
*/
void SkyCloud::Rotate(const Mat33f& rot)
{
_boundingBox.Clear();
for (int i = 0; i < _particles.size(); ++i)
{
_particles[i]->SetPosition(rot * _particles[i]->GetPosition());
_boundingBox.AddPoint(_particles[i]->GetPosition());
}
}
//------------------------------------------------------------------------------
// Function : SkyCloud::Translate
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::Translate(const Vec3f& trans)
* @brief @todo <WRITE BRIEF SkyCloud::Translate DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyCloud::Translate FUNCTION DOCUMENTATION>
*/
void SkyCloud::Translate(const Vec3f& trans)
{
for (int i = 0; i < _particles.size(); ++i)
{
_particles[i]->SetPosition(_particles[i]->GetPosition() + trans);
}
_boundingBox.SetMax(_boundingBox.GetMax() + trans);
_boundingBox.SetMin(_boundingBox.GetMin() + trans);
}
//------------------------------------------------------------------------------
// Function : SkyCloud::Scale
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::Scale(const float scale)
* @brief @todo <WRITE BRIEF SkyCloud::Scale DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyCloud::Scale FUNCTION DOCUMENTATION>
*/
void SkyCloud::Scale(const float scale)
{
_boundingBox.Clear();
for (int i = 0; i < _particles.size(); ++i)
{
_particles[i]->SetPosition(_particles[i]->GetPosition() * scale);
_boundingBox.AddPoint(_particles[i]->GetPosition());
}
}
//------------------------------------------------------------------------------
// Function : SkyCloud::_SortParticles
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::_SortParticles(const Vec3f& vecViewDir, const Vec3f& sortPoint, SortDirection dir)
* @brief Sorts the cloud particles in the direction specified by @a dir.
*
* @vecSortPoint is assumed to already be transformed into the basis space of the cloud.
*/
void SkyCloud::_SortParticles(const Vec3f& vecViewDir,
const Vec3f& vecSortPoint,
SortDirection dir)
{
Vec3f partPos;
for (int i = 0; i < _particles.size(); ++i)
{
partPos = _particles[i]->GetPosition();
partPos -= vecSortPoint;
_particles[i]->SetSquareSortDistance(partPos * vecViewDir);//partPos.LengthSqr());
}
switch (dir)
{
case SKY_CLOUD_SORT_TOWARD:
std::sort(_particles.begin(), _particles.end(), _towardComparator);
break;
case SKY_CLOUD_SORT_AWAY:
std::sort(_particles.begin(), _particles.end(), _awayComparator);
break;
default:
break;
}
}
//------------------------------------------------------------------------------
// Function : EvalHermite
// Description :
//------------------------------------------------------------------------------
/**
* EvalHermite(float pA, float pB, float vA, float vB, float u)
* @brief Evaluates Hermite basis functions for the specified coefficients.
*/
inline float EvalHermite(float pA, float pB, float vA, float vB, float u)
{
float u2=(u*u), u3=u2*u;
float B0 = 2*u3 - 3*u2 + 1;
float B1 = -2*u3 + 3*u2;
float B2 = u3 - 2*u2 + u;
float B3 = u3 - u;
return( B0*pA + B1*pB + B2*vA + B3*vB );
}
// NORMALIZED GAUSSIAN INTENSITY MAP (N must be a power of 2)
//------------------------------------------------------------------------------
// Function : CreateGaussianMap
// Description :
//------------------------------------------------------------------------------
/**
* CreateGaussianMap(int N)
*
* Creates a 2D gaussian image using a hermite surface.
*/
unsigned char* CreateGaussianMap(int N)
{
float *M = new float[2*N*N];
unsigned char *B = new unsigned char[4*N*N];
float X,Y,Y2,Dist;
float Incr = 2.0f/N;
int i=0;
int j = 0;
Y = -1.0f;
for (int y=0; y<N; y++, Y+=Incr)
{
Y2=Y*Y;
X = -1.0f;
for (int x=0; x<N; x++, X+=Incr, i+=2, j+=4)
{
Dist = (float)sqrt(X*X+Y2);
if (Dist>1) Dist=1;
M[i+1] = M[i] = EvalHermite(0.4f,0,0,0,Dist);// * (1 - noise);
B[j+3] = B[j+2] = B[j+1] = B[j] = (unsigned char)(M[i] * 255);
}
}
SAFE_DELETE_ARRAY(M);
return(B);
}
//------------------------------------------------------------------------------
// Function : SkyCloud::_CreateSplatTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::_CreateSplatTexture(unsigned int iResolution)
* @brief Creates the texture map used for cloud particles.
*/
void SkyCloud::_CreateSplatTexture(unsigned int iResolution)
{
unsigned char *splatTexture = CreateGaussianMap(iResolution);
SkyTexture texture;
TextureManager::InstancePtr()->Create2DTextureObject(texture, iResolution, iResolution,
GL_RGBA, splatTexture);
s_pMaterial->SetTexture(0, GL_TEXTURE_2D, texture);
s_pShadeMaterial->SetTexture(0, GL_TEXTURE_2D, texture);
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
s_pShadeMaterial->SetTextureParameter(0, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
s_pShadeMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
s_pShadeMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
s_pMaterial->EnableTexture(0, true);
s_pShadeMaterial->EnableTexture(0, true);
SAFE_DELETE_ARRAY(splatTexture);
}
//------------------------------------------------------------------------------
// Function : SkyCloud::_PhaseFunction
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloud::_PhaseFunction(const Vec3f& vecLightDir, const Vec3f& vecViewDir)
* @brief Computes the phase (scattering) function of the given light and view directions.
*
* A phase function is a transfer function that determines, for any angle between incident
* and outgoing directions, how much of the incident light intensity will be
* scattered in the outgoing direction. For example, scattering by very small
* particles such as those found in clear air, can be approximated using <i>Rayleigh
* scattering</i>. The phase function for Rayleigh scattering is
* p(q) = 0.75*(1 + cos<sup>2</sup>(q)), where q is the angle between incident
* and scattered directions. Scattering by larger particles is more complicated.
* It is described by Mie scattering theory. Cloud particles are more in the regime
* of Mie scattering than Rayleigh scattering. However, we obtain good visual
* results by using the simpler Rayleigh scattering phase function as an approximation.
*/
float SkyCloud::_PhaseFunction(const Vec3f& vecLightDir, const Vec3f& vecViewDir)
{
float rCosAlpha = vecLightDir * vecViewDir;
return .75f * (1 + rCosAlpha * rCosAlpha); // rayleigh scattering = (3/4) * (1+cos^2(alpha))
}

View File

@@ -0,0 +1,177 @@
//------------------------------------------------------------------------------
// File : SkyCloud.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyCloud.hpp
*
* Interface definition for class SkyCloud.
*/
#ifndef __SKYCLOUD_HPP__
#define __SKYCLOUD_HPP__
// warning for truncation of template name for browse info
#pragma warning( disable : 4786)
#include "SkyCloudParticle.hpp"
#include "SkyRenderable.hpp"
#include "SkyMinMaxBox.hpp"
#include "camera.hpp"
#include "SkyArchive.hpp"
#include "mat33.hpp"
#include <plib/sg.h>
class SkyMaterial;
class SkyLight;
class SkyRenderableInstance;
//------------------------------------------------------------------------------
/**
* @class SkyCloud
* @brief A renderable that represents a volumetric cloud.
*
* A SkyCloud is made up of particles, and is rendered using particle splatting.
* SkyCloud is intended to represent realisticly illuminated volumetric clouds
* through which the viewer and / or other objects can realistically pass.
*
* Realistic illumination is performed by the Illuminate() method, which uses a
* graphics hardware algorithm to precompute and store multiple forward scattering
* of light by each particle in the cloud. Clouds may be illuminated by multiple
* light sources. The light from each source is precomputed and stored at each
* particle. Each light's contribution is stored separately so that we can
* compute view-dependent (anisotropic) scattering at run-time. This gives realistic
* effects such as the "silver lining" that you see on a thick cloud when it crosses
* in front of the sun.
*
* At run-time, the cloud is rendered by drawing each particle as a view-oriented
* textured billboard (splat), with lighting computed from the precomputed illumination
* as follows: for each light source <i>l</i>, compute the scattering function (See _PhaseFunction())
* based on the view direction and the direction from the particle to the viewer. This
* scattering function modulates the lighting contribution of <i>l</i>. The modulated
* contributions are then added and used to modulate the color of the particle. The result
* is view-dependent scattering.
*
* If the phase (scattering) function is not enabled (see IsPhaseFunctionEnabled()), then the
* contributions of the light sources are simply added.
*
* @see SkyRenderableInstanceCloud, SkyCloudParticle, SkySceneManager
*/
class SkyCloud : public SkyRenderable
{
public:
SkyCloud();
virtual ~SkyCloud();
virtual SKYRESULT Update(const Camera &cam, SkyRenderableInstance* pInstance = NULL);
virtual SKYRESULT Display(const Camera &camera, SkyRenderableInstance *pInstance = NULL);
SKYRESULT DisplaySplit(const Camera &camera,
const Vec3f &vecSplitPoint,
bool bBackHalf,
SkyRenderableInstance *pInstance = NULL);
SKYRESULT Illuminate( SkyLight *pLight,
SkyRenderableInstance* pInstance,
bool bReset = false);
virtual SkyMinMaxBox* CopyBoundingVolume() const;
//! Enables the use of a scattering function for anisotropic light scattering.
void EnablePhaseFunction(bool bEnable) { _bUsePhaseFunction = bEnable; }
//! Returns true if the use of a scattering function is enabled.
bool IsPhaseFunctionEnabled() const { return _bUsePhaseFunction; }
SKYRESULT Save(SkyArchive &archive) const;
SKYRESULT Load(const SkyArchive &archive, float rScale = 1.0f,double latitude=0.0, double longitude=0.0);
void Rotate(const Mat33f& rot);
void Translate(const Vec3f& trans);
void Scale(const float scale);
protected: // methods
enum SortDirection
{
SKY_CLOUD_SORT_TOWARD,
SKY_CLOUD_SORT_AWAY
};
void _SortParticles( const Vec3f& vecViewDir,
const Vec3f& vecSortPoint,
SortDirection dir);
void _CreateSplatTexture( unsigned int iResolution);
float _PhaseFunction(const Vec3f& vecLightDir, const Vec3f& vecViewDir);
protected: // datatypes
typedef std::vector<SkyCloudParticle*> ParticleArray;
typedef ParticleArray::iterator ParticleIterator;
typedef ParticleArray::const_iterator ParticleConstIterator;
typedef std::vector<Vec3f> DirectionArray;
typedef DirectionArray::iterator DirectionIterator;
class ParticleAwayComparator
{
public:
bool operator()(SkyCloudParticle* pA, SkyCloudParticle *pB)
{
return ((*pA) < (*pB));
}
};
class ParticleTowardComparator
{
public:
bool operator()(SkyCloudParticle* pA, SkyCloudParticle *pB)
{
return ((*pA) > (*pB));
}
};
protected: // data
ParticleArray _particles; // cloud particles
// particle sorting functors for STL sort.
ParticleTowardComparator _towardComparator;
ParticleAwayComparator _awayComparator;
DirectionArray _lightDirections; // light directions in cloud space (cached)
SkyMinMaxBox _boundingBox; // bounds
bool _bUsePhaseFunction;
Vec3f _vecLastSortViewDir;
Vec3f _vecLastSortCamPos;
Vec3f _vecSortPos;
float _rSplitDistance;
static SkyMaterial *s_pMaterial; // shared material for clouds.
static SkyMaterial *s_pShadeMaterial;// shared material for illumination pass.
static unsigned int s_iShadeResolution; // the resolution of the viewport used for shading
static float s_rAlbedo; // the cloud albedo
static float s_rExtinction; // the extinction of the clouds
static float s_rTransparency; // the transparency of the clouds
static float s_rScatterFactor; // How much the clouds scatter
static float s_rSortAngleErrorTolerance; // how far the view must turn to cause a resort.
static float s_rSortSquareDistanceTolerance; // how far the view must move to cause a resort.
};
#endif //__SKYCLOUD_HPP__

View File

@@ -0,0 +1,175 @@
//------------------------------------------------------------------------------
// File : SkyCloudParticle.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyCloudParticle.hpp
*
* Definition of a simple cloud particle class.
*/
#ifndef __SKYCLOUDPARTICLE_HPP__
#define __SKYCLOUDPARTICLE_HPP__
#include "vec3f.hpp"
#include "vec4f.hpp"
#include <vector>
//------------------------------------------------------------------------------
/**
* @class SkyCloudParticle
* @brief A class for particles that make up a cloud.
*
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
*/
class SkyCloudParticle
{
public:
inline SkyCloudParticle();
inline SkyCloudParticle(const Vec3f& pos,
float rRadius,
const Vec4f& baseColor,
float rTransparency = 0);
inline ~SkyCloudParticle();
//! Returns the radius of the particle.
float GetRadius() const { return _rRadius; }
//! Returns the transparency of the particle.
float GetTransparency() const { return _rTransparency; }
//! Returns the position of the particle.
const Vec3f& GetPosition() const { return _vecPosition; }
//! Returns the base color of the particle. This is often used for ambient color.
const Vec4f& GetBaseColor() const { return _vecBaseColor; }
//! Returns the number of light contributions to this particle's color.
unsigned int GetNumLitColors() const { return _vecLitColors.size(); }
//! Returns the light contribution to the color of this particle from light @a index.
inline const Vec4f& GetLitColor(unsigned int index) const;
//! Returns the square distance from the sort position used for the operator< in sorts / splits.
float GetSquareSortDistance() const { return _rSquareSortDistance; }
//! Sets the radius of the particle.
void SetRadius(float rad) { _rRadius = rad; }
//! Returns the transparency of the particle.
void SetTransparency(float trans) { _rTransparency = trans; }
//! Sets the position of the particle.
void SetPosition(const Vec3f& pos) { _vecPosition = pos; }
//! Sets the base color of the particle. This is often used for ambient color.
void SetBaseColor(const Vec4f& col) { _vecBaseColor = col; }
//! Sets the light contribution to the color of this particle from light @a index.
void AddLitColor(const Vec4f& col) { _vecLitColors.push_back(col); }
//! Clears the list of light contributions.
void ClearLitColors() { _vecLitColors.clear(); }
//! Sets the square distance from the sort position used for the operator< in sorts.
void SetSquareSortDistance(float rSquareDistance) { _rSquareSortDistance = rSquareDistance; }
//! This operator is used to sort particle arrays from nearest to farthes.
bool operator<(const SkyCloudParticle& p) const
{
return (_rSquareSortDistance < p._rSquareSortDistance);
}
//! This operator is used to sort particle arrays from farthest to nearest.
bool operator>(const SkyCloudParticle& p) const
{
return (_rSquareSortDistance > p._rSquareSortDistance);
}
protected:
float _rRadius;
float _rTransparency;
Vec3f _vecPosition;
Vec4f _vecBaseColor;
std::vector<Vec4f> _vecLitColors;
Vec3f _vecEye;
// for sorting particles during shading
float _rSquareSortDistance;
};
//------------------------------------------------------------------------------
// Function : SkyCloudParticle::SkyCloudParticle
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloudParticle::SkyCloudParticle()
* @brief Default constructor.
*/
inline SkyCloudParticle::SkyCloudParticle()
: _rRadius(0),
_rTransparency(0),
_vecPosition(0, 0, 0),
_vecBaseColor(0, 0, 0, 1),
_vecEye(0, 0, 0),
_rSquareSortDistance(0)
{
_vecLitColors.clear();
}
//------------------------------------------------------------------------------
// Function : SkyCloudParticle::SkyCloudParticle
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloudParticle::SkyCloudParticle(const Vec3f& pos, float rRadius, const Vec4f& baseColor, float rTransparency)
* @brief Constructor.
*/
inline SkyCloudParticle::SkyCloudParticle(const Vec3f& pos,
float rRadius,
const Vec4f& baseColor,
float rTransparency /* = 0 */)
: _rRadius(rRadius),
_rTransparency(rTransparency),
_vecPosition(pos),
_vecBaseColor(baseColor),
_vecEye(0, 0, 0),
_rSquareSortDistance(0)
{
_vecLitColors.clear();
}
//------------------------------------------------------------------------------
// Function : SkyCloudParticle::~SkyCloudParticle
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyCloudParticle::~SkyCloudParticle()
* @brief Destructor.
*/
inline SkyCloudParticle::~SkyCloudParticle()
{
_vecLitColors.clear();
}
//------------------------------------------------------------------------------
// Function : Vec4f& SkyCloudParticle::GetLitColor
// Description :
//------------------------------------------------------------------------------
/**
* @fn Vec4f& SkyCloudParticle::GetLitColor(unsigned int index) const
* @brief Returns the lit color specified by index.
*
* If the index is out of range, returns a zero vector.
*/
inline const Vec4f& SkyCloudParticle::GetLitColor(unsigned int index) const
{
if (index <= _vecLitColors.size())
return _vecLitColors[index];
else
return Vec4f::ZERO;
}
#endif //__SKYCLOUDPARTICLE_HPP__

View File

@@ -0,0 +1,305 @@
//------------------------------------------------------------------------------
// File : SkyContext.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyContext.cpp
*
* Graphics Context Interface. Initializes GL extensions, etc.
*/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <GL/glut.h>
#ifndef WIN32
#include <GL/glx.h>
#endif
//#include "extgl.h"
#include "SkyContext.hpp"
#include "SkyUtil.hpp"
#include "SkyMaterial.hpp"
#include "SkyTextureState.hpp"
//------------------------------------------------------------------------------
// Function : SkyContext::SkyContext
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::SkyContext()
* @brief Constructor.
*
*/
SkyContext::SkyContext()
{
_iWidth = glutGet(GLUT_WINDOW_WIDTH);
_iHeight = glutGet(GLUT_WINDOW_HEIGHT);
// materials and structure classes
AddCurrentGLContext();
// Initialize all the extensions and load the functions - JW (file is extgl.c)
#ifdef WIN32
glInitialize();
InitializeExtension("GL_ARB_multitexture");
#endif
}
//------------------------------------------------------------------------------
// Function : SkyContext::~SkyContext
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::~SkyContext()
* @brief Destructor.
*/
SkyContext::~SkyContext()
{
// delete map of materials
for (ContextMaterialIterator cmi = _currentMaterials.begin(); cmi != _currentMaterials.end(); ++cmi)
{
SAFE_DELETE(cmi->second);
}
_currentMaterials.clear();
}
//------------------------------------------------------------------------------
// Function : SkyContext::ProcessReshapeEvent
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::ProcessReshapeEvent(int iWidth, int iHeight)
* @brief Handles window resize events, and notifies all context listeners of the event.
*/
SKYRESULT SkyContext::ProcessReshapeEvent(int iWidth, int iHeight)
{
_iWidth = iWidth;
_iHeight = iHeight;
return _SendMessage(SKYCONTEXT_MESSAGE_RESHAPE);
}
//------------------------------------------------------------------------------
// Function : SkyContext::InitializeExtensions
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::InitializeExtensions(const char *pExtensionNames)
* @brief Initializes GL extension specified by @a pExtensionNames.
*/
SKYRESULT SkyContext::InitializeExtension(const char *pExtensionName)
{ /***
if (!QueryExtension(pExtensionName)) // see query search function defined in extgl.c
{
SkyTrace(
"ERROR: SkyContext::InitializeExtenstions: The following extensions are unsupported: %s\n",
pExtensionName);
return SKYRESULT_FAIL;
} **/
//set this false to catch all the extensions until we come up with a linux version
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyContext::GetCurrentMaterial
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::GetCurrentMaterial()
* @brief Returns the current cached material state that is active in this OpenGL context.
*
* @todo <WRITE EXTENDED SkyContext::GetCurrentMaterial FUNCTION DOCUMENTATION>
*/
SkyMaterial* SkyContext::GetCurrentMaterial()
{
#ifdef WIN32
ContextMaterialIterator cmi = _currentMaterials.find(wglGetCurrentContext());
#else
ContextMaterialIterator cmi = _currentMaterials.find(glXGetCurrentContext());
#endif
if (_currentMaterials.end() != cmi)
return cmi->second;
else
{
SkyTrace("SkyContext::GetCurrentMaterial(): Invalid context.");
return NULL;
}
}
//------------------------------------------------------------------------------
// Function : SkyContext::GetCurrentTextureState
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::GetCurrentTextureState()
* @brief Returns the current cached texture state that is active in this OpenGL context.
*
* @todo <WRITE EXTENDED SkyContext::GetCurrentTextureState FUNCTION DOCUMENTATION>
*/
SkyTextureState* SkyContext::GetCurrentTextureState()
{
#ifdef WIN32
ContextTextureStateIterator ctsi = _currentTextureState.find(wglGetCurrentContext());
#else
ContextTextureStateIterator ctsi = _currentTextureState.find(glXGetCurrentContext());
#endif
if (_currentTextureState.end() != ctsi)
return ctsi->second;
else
{
SkyTrace("SkyContext::GetCurrentTextureState(): Invalid context.");
return NULL;
}
}
//------------------------------------------------------------------------------
// Function : SkyContext::AddCurrentGLContext
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::AddCurrentGLContext()
* @brief @todo <WRITE BRIEF SkyContext::AddCurrentGLContext DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyContext::AddCurrentGLContext FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyContext::AddCurrentGLContext()
{
SkyMaterial *pCurrentMaterial = new SkyMaterial;
#ifdef WIN32
_currentMaterials.insert(std::make_pair(wglGetCurrentContext(), pCurrentMaterial));
#else
_currentMaterials.insert(std::make_pair(glXGetCurrentContext(), pCurrentMaterial));
#endif
SkyTextureState *pCurrentTS = new SkyTextureState;
#ifdef WIN32
_currentTextureState.insert(std::make_pair(wglGetCurrentContext() , pCurrentTS));
#else
_currentTextureState.insert(std::make_pair(glXGetCurrentContext() , pCurrentTS));
#endif
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyContext::Register
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::Register(Listener* pListener, int priority)
* @brief Register with the messaging system to handle notification of mode changes
*/
SKYRESULT SkyContext::Register(Listener* pListener, int priority)
{
std::list<ListenerPair>::iterator iter =
std::find_if(_listeners.begin(), _listeners.end(), _ListenerPred(pListener));
if (iter == _listeners.end())
{
// insert the listener, sorted by priority
for (iter=_listeners.begin(); iter != _listeners.end(); ++iter)
{
if (priority <= iter->first)
{
_listeners.insert(iter, ListenerPair(priority, pListener));
break;
}
}
if (iter == _listeners.end())
{
_listeners.push_back(ListenerPair(priority, pListener));
}
// Send a message to the pListener if we are already active so it
// can intialize itself
//FAIL_RETURN(pListener->GraphicsReshapeEvent());
}
else
{
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyContext: Listener is already registered");
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyContext::UnRegister
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyContext::UnRegister(Listener *pListener)
* @brief UnRegister with the messaging system.
*/
SKYRESULT SkyContext::UnRegister(Listener *pListener)
{
std::list<ListenerPair>::iterator iter =
std::find_if(_listeners.begin(), _listeners.end(), _ListenerPred(pListener));
if (iter == _listeners.end())
{
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyContext: Listener is not registered");
}
else
{
_listeners.erase(iter);
}
return SKYRESULT_OK;
}
/**
* @fn SkyContext::_SendMessage(SkyMessageType msg)
* @brief Messaging system to handle notification of mode changes
*/
SKYRESULT SkyContext::_SendMessage(SkyMessageType msg)
{
if (_listeners.size() == 0) return SKYRESULT_OK;
bool failure = false;
SKYRESULT res, failureCode = SKYRESULT_OK;
std::list<ListenerPair>::iterator iter;
SKYRESULT (Listener::*fnPtr)() = NULL;
// Make a pointer to the appropriate method
switch (msg)
{
case SKYCONTEXT_MESSAGE_RESHAPE: fnPtr = &Listener::GraphicsReshapeEvent; break;
}
// Notify all listeners of the messag. catch failures, but still call everyone else.
// !!! WRH HORRIBLE HACK must cache the current "end" because these functions could register new listeners
std::list<ListenerPair>::iterator endIter = _listeners.end();
endIter--;
iter = _listeners.begin();
do
{
if ( SKYFAILED( res = (iter->second->*fnPtr)() ) )
{
failureCode = res;
SkyTrace("SkyContext: SendMessage failed");
}
if (iter == endIter) break;
iter++;
} while (true);
FAIL_RETURN(failureCode);
return SKYRESULT_OK;
}

View File

@@ -0,0 +1,139 @@
//------------------------------------------------------------------------------
// File : SkyContext.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyContext.hpp
*
* Graphics Context Interface. Initializes GL extensions, etc.
*/
#ifndef __SKYCONTEXT_HPP__
#define __SKYCONTEXT_HPP__
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
// warning for truncation of template name for browse info
// #pragma warning( disable : 4786)
#include "SkySingleton.hpp"
#include <simgear/compiler.h>
#include <list>
#include <map>
#include <algorithm>
#ifdef WIN32
# include "extgl.h"
#else
typedef void *HANDLE;
typedef HANDLE *PHANDLE;
#define DECLARE_HANDLE(n) typedef HANDLE n
DECLARE_HANDLE(HGLRC);
#endif
class SkyContext;
class SkyMaterial;
class SkyTextureState;
//! Graphics Context Singleton declaration.
/*! The Context must be created by calling GraphicsContext::Instantiate(). */
typedef SkySingleton<SkyContext> GraphicsContext;
//------------------------------------------------------------------------------
/**
* @class SkyContext
* @brief A manager / proxy for the state of OpenGL contexts.
*
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
*/
class SkyContext
{
public: // datatypes
//------------------------------------------------------------------------------
/**
* @class Listener
* @brief Inherit this class and overide its methods to be notified of context events.
*/
class Listener
{
public:
//! Handle a change in the dimensions of the graphics window.
virtual SKYRESULT GraphicsReshapeEvent() { return SKYRESULT_OK; }
};
/**
* @enum SkyMessageType messages that the context can generate for it's listeners.
*/
enum SkyMessageType
{
SKYCONTEXT_MESSAGE_RESHAPE,
SKYCONTEXT_MESSAGE_COUNT
};
public: // methods
SKYRESULT ProcessReshapeEvent(int iWidth, int iHeight);
SKYRESULT InitializeExtension(const char *pExtensionName);
//! Returns the current dimensions of the window.
void GetWindowSize(int &iWidth, int &iHeight) { iWidth = _iWidth; iHeight = _iHeight; }
SkyMaterial* GetCurrentMaterial();
SkyTextureState* GetCurrentTextureState();
SKYRESULT AddCurrentGLContext();
//------------------------------------------------------------------------------
// Register with the messaging system to handle notification of mode changes
//------------------------------------------------------------------------------
SKYRESULT Register(Listener *pListener, int priority = 0);
SKYRESULT UnRegister(Listener *pLlistener);
protected: // methods
SkyContext();
~SkyContext();
protected: // data
int _iWidth;
int _iHeight;
typedef std::map<HGLRC, SkyMaterial*> ContextMaterialMap;
typedef ContextMaterialMap::iterator ContextMaterialIterator;
typedef std::map<HGLRC, SkyTextureState*> ContextTextureStateMap;
typedef ContextTextureStateMap::iterator ContextTextureStateIterator;
ContextMaterialMap _currentMaterials;
ContextTextureStateMap _currentTextureState;
//------------------------------------------------------------------------------
// Messaging system to handle notification of mode changes
//------------------------------------------------------------------------------
typedef std::pair<int, Listener*> ListenerPair;
class _ListenerPred
{
public:
_ListenerPred(const Listener* l) { _l = l; }
bool operator()(const ListenerPair& pair) { return pair.second == _l; }
protected:
const Listener *_l;
};
SKYRESULT _SendMessage(SkyMessageType msg);
std::list<ListenerPair> _listeners;
};
#endif //__SKYCONTEXT_HPP__

View File

@@ -0,0 +1,65 @@
//------------------------------------------------------------------------------
// File : SkyControlled.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyControlled.hpp
*
* Interface definition for controlled objects.
*/
#ifndef __SKYCONTROLLED_HPP__
#define __SKYCONTROLLED_HPP__
//#include "BHXController.hpp"
template<typename ControlStateType> class SkyController;
//------------------------------------------------------------------------------
/**
* @class SkyControlled
* @brief A base class defining an interface for controlled objects.
*
* This class abstracts the control of objects into a simple interface that a
* class may inherit that allows it to be controlled by SkyController objects.
* A class simply inherits from SkyControlled, which forces the class to implement
* the method UpdateStateFromControls(). This method usually uses the SkyController
* object passed to SetController() to query the input state via
* SkyController::GetControlState().
*
* @see SkyController
*/
template<typename ControlStateType>
class SkyControlled
{
public:
//! Constructor.
SkyControlled() { _pController = NULL; }
//! Destructor
virtual ~SkyControlled() { _pController = NULL; }
//! Sets the controller which will control this controlled object.
void SetController(SkyController<ControlStateType> *pController) { _pController = pController; }
//! Updates the state of the controlled object based on the controls (received from the controller).
virtual SKYRESULT UpdateStateFromControls(SKYTIME timeStep) = 0;
protected:
SkyController<ControlStateType> *_pController;
ControlStateType _controlState;
};
#endif //__SKYCONTROLLED_HPP__

View File

@@ -0,0 +1,56 @@
//------------------------------------------------------------------------------
// File : SkyController.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyController.hpp
*
* Abstract base class for game object controllers.
*/
#ifndef __SKYCONTROLLER_HPP__
#define __SKYCONTROLLER_HPP__
#include "SkyUtil.hpp"
//------------------------------------------------------------------------------
/**
* @class SkyController
* @brief A class that defines an interface for translating general control input into game object control.
*
* This class abstracts game object control from specific control input, such
* as via user interface devices or via artificial intelligence. Subclasses of
* this class implement the method GetControlState() so that objects controlled
* by an instance of a SkyController can query the control state that determines
* their actions. The object need not know whether it is controlled by a human
* or the computer since either controller provides it the same interface.
*
* @see SkyControlled
*/
template <typename ControlStateType>
class SkyController
{
public:
//! Constructor.
SkyController() {}
//! Destructor.
virtual ~SkyController() {}
//! Fills out the control state structure passed in with the current state of controls.
virtual SKYRESULT GetControlState(ControlStateType &controlState) = 0;
};
#endif //__SKYCONTROLLER_HPP__

View File

@@ -0,0 +1,278 @@
//------------------------------------------------------------------------------
// File : SkyDynamicTextureManager.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyDynamicTextureManager.cpp
*
* Implementation of a repository for check out and check in of dynamic textures.
*/
#pragma warning( disable : 4786 )
#include "SkyDynamicTextureManager.hpp"
#include "SkyTexture.hpp"
#include "SkyContext.hpp"
#pragma warning( disable : 4786 )
//! Set this to 1 to print lots of dynamic texture usage messages.
#define SKYDYNTEXTURE_VERBOSE 0
//! The maximum number of textures of each resolution to allow in the checked in pool.
#define SKYDYNTEXTURE_TEXCACHE_LIMIT 32
//------------------------------------------------------------------------------
// Function : SkyDynamicTextureManager::SkyDynamicTextureManager
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyDynamicTextureManager::SkyDynamicTextureManager()
* @brief Constructor.
*/
SkyDynamicTextureManager::SkyDynamicTextureManager()
#ifdef SKYDYNTEXTURE_VERBOSE
: _iNumTextureBytesUsed(0),
_iNumTextureBytesCheckedIn(0),
_iNumTextureBytesCheckedOut(0)
#endif
{
for (int i = 0; i < 11; ++i)
for (int j = 0; j < 11; ++j)
_iAvailableSizeCounts[i][j] = 0;
}
//------------------------------------------------------------------------------
// Function : SkyDynamicTextureManager::~SkyDynamicTextureManager
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyDynamicTextureManager::~SkyDynamicTextureManager()
* @brief Destructor.
*/
SkyDynamicTextureManager::~SkyDynamicTextureManager()
{
for ( TextureSet::iterator subset = _availableTexturePool.begin();
subset != _availableTexturePool.end();
++subset )
{ // iterate over texture subsets.
for ( TextureSubset::iterator texture = (*subset).second->begin();
texture != (*subset).second->end();
++texture )
{
texture->second->Destroy();
delete texture->second;
}
subset->second->clear();
}
_availableTexturePool.clear();
for ( TextureSubset::iterator texture = _checkedOutTexturePool.begin();
texture != _checkedOutTexturePool.end();
++texture )
{
texture->second->Destroy();
delete texture->second;
}
_checkedOutTexturePool.clear();
}
//------------------------------------------------------------------------------
// Function : SkyDynamicTextureManager::CheckOutTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyDynamicTextureManager::CheckOutTexture(unsigned int iWidth, unsigned int iHeight)
* @brief Returns a texture from the available pool, creating a new one if necessary.
*
* Thi texture returned by this method is checked out: it will be maintained in a
* checked out pool until it is checked in with CheckInTexture(). The texture is owned
* by the SkyDynamicTextureManager -- it should not be deleted by another object. Checked out
* textures can be modified (copied, or rendered to, etc.), but should not be reallocated
* or resized. All checked out textures will be deleted when the SkyDynamicTextureManager
* is destroyed, so this manager should be destroyed only after rendering ceases.
*/
SkyTexture* SkyDynamicTextureManager::CheckOutTexture(unsigned int iWidth,
unsigned int iHeight)
{
int iWidthLog, iHeightLog;
iWidthLog = SkyGetLogBaseTwo(iWidth);
iHeightLog = SkyGetLogBaseTwo(iHeight);
// first see if a texture of this resolution is available:
// find the subset of textures with width = iWidth, if it exists.
TextureSet::iterator subset = _availableTexturePool.find(iWidth);
if (subset != _availableTexturePool.end())
{ // found the iWidth subset
// now find a texture with height = iHeight:
TextureSubset::iterator texture = (*subset).second->find(iHeight);
if (texture != (*subset).second->end())
{ // found one!
// extract the texture
SkyTexture *pTexture = (*texture).second;
(*texture).second = NULL;
// first remove it from this set.
(*subset).second->erase(texture);
// now add it to the checked out texture set.
_checkedOutTexturePool.insert(TextureSubset::value_type(pTexture->GetID(), pTexture));
// update checked out/in amount.
#if SKYDYNTEXTURE_VERBOSE
_iNumTextureBytesCheckedIn -= iWidth * iHeight * 4;
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
printf("CHECKOUT: %d x %d\n", iWidth, iHeight);
#endif
_iAvailableSizeCounts[iWidthLog][iHeightLog]--;
// we're now free to give this texture to the user
return pTexture;
}
else
{ // we didn't find an iWidth x iHeight texture, although the iWidth subset exists
// create a new texture of the appropriate dimensions and return it.
SkyTexture *pNewTexture = CreateDynamicTexture(iWidth, iHeight);
_checkedOutTexturePool.insert(TextureSubset::value_type(pNewTexture->GetID(),
pNewTexture));
#if SKYDYNTEXTURE_VERBOSE
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
#endif
return pNewTexture;
}
}
else
{ // we don't yet have a subset for iWidth textures. Create one.
TextureSubset *pSubset = new TextureSubset;
_availableTexturePool.insert(TextureSet::value_type(iWidth, pSubset));
// now create a new texture of the appropriate dimensions and return it.
SkyTexture *pNewTexture = CreateDynamicTexture(iWidth, iHeight);
_checkedOutTexturePool.insert(TextureSubset::value_type(pNewTexture->GetID(), pNewTexture));
#if SKYDYNTEXTURE_VERBOSE
_iNumTextureBytesCheckedOut += iWidth * iHeight * 4;
#endif
return pNewTexture;
}
}
//------------------------------------------------------------------------------
// Function : SkyDynamicTextureManager::CheckInTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyDynamicTextureManager::CheckInTexture(SkyTexture *pTexture)
* @brief Returns a checked-out texture to the available pool.
*
* This method removes the checked out texture from the checked out pool if it is
* checked out, and then checks it in to the available pool.
*/
void SkyDynamicTextureManager::CheckInTexture(SkyTexture *pTexture)
{
// first see if the texture is in the checked out pool.
TextureSubset::iterator coTexture = _checkedOutTexturePool.find(pTexture->GetID());
if (coTexture != _checkedOutTexturePool.end())
{ // if it is there, remove it.
_checkedOutTexturePool.erase(coTexture);
_iNumTextureBytesCheckedOut -= pTexture->GetWidth() * pTexture->GetHeight() * 4;
}
// Don't cache too many unused textures.
int iWidthLog, iHeightLog;
iWidthLog = SkyGetLogBaseTwo(pTexture->GetWidth());
iHeightLog = SkyGetLogBaseTwo(pTexture->GetHeight());
if (_iAvailableSizeCounts[iWidthLog][iHeightLog] >= SKYDYNTEXTURE_TEXCACHE_LIMIT)
{
#if SKYDYNTEXTURE_VERBOSE
_iNumTextureBytesUsed -= pTexture->GetWidth() * pTexture->GetHeight() * 4;
printf("%dx%d texture DESTROYED.\n\t Total memory used: %d bytes.\n",
pTexture->GetWidth(), pTexture->GetHeight(), _iNumTextureBytesUsed);
#endif
pTexture->Destroy();
SAFE_DELETE(pTexture);
return;
}
// now check the texture into the available pool.
// find the width subset:
TextureSet::iterator subset = _availableTexturePool.find(pTexture->GetWidth());
if (subset != _availableTexturePool.end())
{ // the subset exists. Add the texture to it
(*subset).second->insert(TextureSubset::value_type(pTexture->GetHeight(), pTexture));
_iNumTextureBytesCheckedIn += pTexture->GetWidth() * pTexture->GetHeight() * 4;
_iAvailableSizeCounts[iWidthLog][iHeightLog]++;
}
else
{ // subset not found. Create it.
TextureSubset *pSubset = new TextureSubset;
// insert the texture.
pSubset->insert(TextureSubset::value_type(pTexture->GetHeight(), pTexture));
// insert the subset into the available pool
_availableTexturePool.insert(TextureSet::value_type(pTexture->GetWidth(), pSubset));
#if SKYDYNTEXTURE_VERBOSE
_iNumTextureBytesCheckedIn += pTexture->GetWidth() * pTexture->GetHeight() * 4;
_iAvailableSizeCounts[iWidthLog][iHeightLog]++;
#endif
}
pTexture = NULL;
}
//------------------------------------------------------------------------------
// Function : SkyDynamicTextureManager::CreateDynamicTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyDynamicTextureManager::CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight)
* @brief Allocate a new dynamic texture object of the given resolution.
*
* This method is used by CheckOutTexture() when it can't find an available texture of
* the requested resolution. It can also be called externally, but will result in an
* unmanaged texture unless the new texture is subsequently checked in using CheckInTexture().
*/
SkyTexture* SkyDynamicTextureManager::CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight)
{
unsigned int iID;
glGenTextures(1, &iID);
SkyTexture *pNewTexture = new SkyTexture(iWidth, iHeight, iID);
glBindTexture(GL_TEXTURE_2D, pNewTexture->GetID());
// set default filtering.
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// create an empty buffer
unsigned char *pData = new unsigned char[iWidth * iHeight * 4];
// allocate the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, iWidth, iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData );
delete [] pData;
// update the used texture bytes...
_iNumTextureBytesUsed += iWidth * iHeight * 4;
#if SKYDYNTEXTURE_VERBOSE
printf("New %dx%d texture created.\n\t Total memory used: %d bytes\n", iWidth, iHeight, _iNumTextureBytesUsed);
printf("\tTotal memory checked in: %d\n", _iNumTextureBytesCheckedIn);
printf("\tTotal memory checked out: %d\n", _iNumTextureBytesCheckedOut);
#endif
return pNewTexture;
}

View File

@@ -0,0 +1,80 @@
//------------------------------------------------------------------------------
// File : SkyDynamicTextureManager.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyDynamicTextureManager.hpp
*
* Interface definition of a repository for check out and check in of dynamic textures.
*/
#ifndef __SKYDYNAMICTEXTUREMANAGER_HPP__
#define __SKYDYNAMICTEXTUREMANAGER_HPP__
// warning for truncation of template name for browse info
#pragma warning( disable : 4786)
#include <map>
#include <GL/glut.h>
#include "SkyUtil.hpp"
#include "SkySingleton.hpp"
using namespace std;
class SkyTexture;
class SkyDynamicTextureManager;
//! Dynamic Texture Manager Singleton declaration.
/*! The DynamicTextureManager must be created by calling DynamicTextureManager::Instantiate(). */
typedef SkySingleton<SkyDynamicTextureManager> DynamicTextureManager;
//------------------------------------------------------------------------------
/**
* @class SkyDynamicTextureManager
* @brief A repository that allows check-out and check-in from a pool of dynamic textures.
*
* When an object needs a dynamic texture, it checks it out using CheckOutTexture(), passing
* the resolution of the texture it needs. When the object is done with the texture, it
* calls CheckInTexture(). New dynamic textures can be allocated by calling CreateDynamicTexture,
* but these textures will be unmanaged.
*/
class SkyDynamicTextureManager
{
public:
SkyTexture* CheckOutTexture(unsigned int iWidth, unsigned int iHeight);
void CheckInTexture(SkyTexture* pTexture);
SkyTexture* CreateDynamicTexture(unsigned int iWidth, unsigned int iHeight);
protected: // methods
SkyDynamicTextureManager(); // these are protected because it is a singleton.
~SkyDynamicTextureManager();
protected: // datatypes
typedef multimap<unsigned int, SkyTexture*> TextureSubset;
typedef multimap<unsigned int, TextureSubset*> TextureSet;
protected: // data
TextureSet _availableTexturePool;
TextureSubset _checkedOutTexturePool;
unsigned int _iAvailableSizeCounts[11][11];
unsigned int _iNumTextureBytesUsed;
unsigned int _iNumTextureBytesCheckedOut;
unsigned int _iNumTextureBytesCheckedIn;
};
#endif //__SKYDYNAMICTEXTUREMANAGER_HPP__

View File

@@ -0,0 +1,231 @@
//------------------------------------------------------------------------------
// File : SkyLight.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyLight.cpp
*
* Implementation of a class that maintains the state and operation of a light.
*/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#ifdef WIN32
# ifdef _MSC_VER
# pragma warning( disable : 4786)
# endif
# include "extgl.h"
#endif
#include "SkyLight.hpp"
#include "SkyMaterial.hpp"
#include "mat44.hpp"
#include <GL/glut.h>
SkyMaterial* SkyLight::s_pMaterial = NULL;
//------------------------------------------------------------------------------
// Function : SkyLight::SkyLight
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyLight::SkyLight(SkyLightType eType)
* @brief @todo <WRITE BRIEF SkyLight::SkyLight DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyLight::SkyLight FUNCTION DOCUMENTATION>
*/
SkyLight::SkyLight(SkyLightType eType)
: _bEnabled(true),
_bDirty(true),
_iLastGLID(-1),
_eType(eType),
_vecPosition(0, 0, 1, 1),
_vecDirection(0, 0, -1, 0),
_vecDiffuse(1, 1, 1, 1),
_vecAmbient(0, 0, 0, 0),
_vecSpecular(1, 1, 1, 1),
_vecAttenuation(1, 0, 0),
_rSpotExponent(0),
_rSpotCutoff(180)
{
if (!s_pMaterial)
{
s_pMaterial = new SkyMaterial;
s_pMaterial->SetColorMaterialMode(GL_DIFFUSE);
s_pMaterial->EnableColorMaterial(true);
s_pMaterial->EnableLighting(false);
}
}
//------------------------------------------------------------------------------
// Function : SkyLight::~SkyLight
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyLight::~SkyLight()
* @brief @todo <WRITE BRIEF SkyLight::~SkyLight DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyLight::~SkyLight FUNCTION DOCUMENTATION>
*/
SkyLight::~SkyLight()
{
}
//------------------------------------------------------------------------------
// Function : SkyLight::Display
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyLight::Display() const
* @brief Displays a wireframe representation of the light.
*
* This is useful for debugging.
*/
void SkyLight::Display() const
{
s_pMaterial->Activate();
//if (_bEnabled)
//glColor3fv(&(_vecDiffuse.x));
//else
glColor3f(0, 0, 0);
switch(_eType)
{
case SKY_LIGHT_POINT:
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
{
glTranslatef(_vecPosition.x, _vecPosition.y, _vecPosition.z);
glutWireSphere(4, 8, 8);
}
glPopMatrix();
break;
case SKY_LIGHT_DIRECTIONAL:
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
{
Mat44f mat;
Vec3f vecPos(_vecPosition.x, _vecPosition.y, _vecPosition.z);
Vec3f vecDir(_vecDirection.x, _vecDirection.y, _vecDirection.z);
Vec3f vecUp(0, 1, 0);
if (fabs(vecDir * vecUp) - 1 < 1e-6) // check that the view and up directions are not parallel.
vecUp.Set(1, 0, 0);
mat.invLookAt(vecPos, vecPos + 10 * vecDir, vecUp);
glPushMatrix();
{
glTranslatef(-50 * vecDir.x, -50 * vecDir.y, -50 * vecDir.z);
glMultMatrixf(mat);
glutWireCone(10, 10, 4, 1);
}
glPopMatrix();
glMultMatrixf(mat);
GLUquadric *pQuadric = gluNewQuadric();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
gluCylinder(pQuadric, 4, 4, 50, 4, 4);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glPopMatrix();
}
break;
case SKY_LIGHT_SPOT:
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
{
Mat44f mat;
Vec3f vecUp = Vec3f(0, 1, 0);
Vec3f vecPos(_vecPosition.x, _vecPosition.y, _vecPosition.z);
Vec3f vecDir(_vecDirection.x, _vecDirection.y, _vecDirection.z);
if (_vecDirection == vecUp)
vecUp.Set(1, 0, 0);
mat.invLookAt(vecPos + 50 * vecDir, vecPos + 51 * vecDir, vecUp);
glMultMatrixf(mat);
float rAlpha= acos(pow(10, (-12 / _rSpotExponent)));
//glutWireCone(50 * tan(SKYDEGREESTORADS * rAlpha), 50, 16, 8);
glutWireCone(50 * tan(SKYDEGREESTORADS * _rSpotCutoff), 50, 16, 8);
}
glPopMatrix();
}
break;
default:
break;
}
}
//------------------------------------------------------------------------------
// Function : SkyLight::Activate
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyLight::Activate(int iLightID)
* @brief @todo <WRITE BRIEF SkyLight::Activate DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyLight::Activate FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyLight::Activate(int iLightID)
{
glPushMatrix();
// set the position every frame
if (SKY_LIGHT_DIRECTIONAL != _eType)
glLightfv(GL_LIGHT0 + iLightID, GL_POSITION, &(_vecPosition.x));
else
glLightfv(GL_LIGHT0 + iLightID, GL_POSITION, &(_vecDirection.x));
if (SKY_LIGHT_SPOT == _eType)
glLightfv(GL_LIGHT0 + iLightID, GL_SPOT_DIRECTION, &(_vecDirection.x));
// set other light properties only when they change.
if (_bDirty || iLightID != _iLastGLID)
{
glLightfv(GL_LIGHT0 + iLightID, GL_DIFFUSE, &(_vecDiffuse.x));
glLightfv(GL_LIGHT0 + iLightID, GL_AMBIENT, &(_vecAmbient.x));
glLightfv(GL_LIGHT0 + iLightID, GL_SPECULAR, &(_vecSpecular.x));
glLightf(GL_LIGHT0 + iLightID, GL_CONSTANT_ATTENUATION, _vecAttenuation.x);
glLightf(GL_LIGHT0 + iLightID, GL_LINEAR_ATTENUATION, _vecAttenuation.y);
glLightf(GL_LIGHT0 + iLightID, GL_QUADRATIC_ATTENUATION, _vecAttenuation.z);
if (SKY_LIGHT_SPOT == _eType)
{
glLightf(GL_LIGHT0 + iLightID, GL_SPOT_CUTOFF, _rSpotCutoff);
glLightf(GL_LIGHT0 + iLightID, GL_SPOT_EXPONENT, _rSpotExponent);
}
else
{
glLightf(GL_LIGHT0 + iLightID, GL_SPOT_CUTOFF, 180);
glLightf(GL_LIGHT0 + iLightID, GL_SPOT_EXPONENT, 0);
}
if (_bEnabled)
glEnable(GL_LIGHT0 + iLightID);
else
{
glDisable(GL_LIGHT0 + iLightID);
}
_iLastGLID = iLightID;
_bDirty = false;
}
glPopMatrix();
return SKYRESULT_OK;
}

View File

@@ -0,0 +1,97 @@
//------------------------------------------------------------------------------
// File : SkyLight.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyLight.hpp
*
* Definition of a class that maintains the state and operation of a light.
*/
#ifndef __SKYLIGHT_HPP__
#define __SKYLIGHT_HPP__
#include "vec3f.hpp"
#include "vec4f.hpp"
#include "SkyUtil.hpp"
class SkyMaterial;
class SkyLight
{
public: // types
enum SkyLightType
{
SKY_LIGHT_POINT,
SKY_LIGHT_DIRECTIONAL,
SKY_LIGHT_SPOT,
SKY_LIGHT_NUM_TYPES
};
public: // methods
SkyLight(SkyLightType eType);
virtual ~SkyLight();
// for visualization of light positions / directions.
void Display() const;
bool GetEnabled() const { return _bEnabled; }
SkyLightType GetType() const { return _eType; }
const float* GetPosition() const { return _vecPosition; }
const float* GetDirection() const { return _vecDirection; }
const float* GetDiffuse() const { return _vecDiffuse; }
const float* GetAmbient() const { return _vecAmbient; }
const float* GetSpecular() const { return _vecSpecular; }
const float* GetAttenuation() const { return _vecAttenuation; }
float GetSpotExponent() const { return _rSpotExponent; }
float GetSpotCutoff() const { return _rSpotCutoff; }
void Enable(bool bEnable) { _bEnabled = bEnable; _bDirty = true; }
void SetType(const SkyLightType& t) { _eType = t; _bDirty = true; }
void SetPosition(const float pos[3])
{ _vecPosition.Set(pos[0], pos[1], pos[2], (_eType != SKY_LIGHT_DIRECTIONAL)); _bDirty = true; }
void SetDirection(const float dir[3]) { _vecDirection.Set(dir[0], dir[1], dir[2], 0); _bDirty = true; }
void SetDiffuse(const float color[4]) { _vecDiffuse.Set(color); _bDirty = true; }
void SetAmbient(const float color[4]) { _vecAmbient.Set(color); _bDirty = true; }
void SetSpecular(const float color[4]){ _vecSpecular.Set(color); _bDirty = true; }
void SetAttenuation(float rConstant, float rLinear, float rQuadratic)
{ _vecAttenuation.Set(rConstant, rLinear, rQuadratic); _bDirty = true; }
void SetSpotExponent(float rExp) { _rSpotExponent = rExp; _bDirty = true; }
void SetSpotCutoff(float rCutoff) { _rSpotCutoff = rCutoff; _bDirty = true; }
SKYRESULT Activate(int iLightID);
protected: // data
bool _bEnabled;
bool _bDirty;
int _iLastGLID;
SkyLightType _eType;
Vec4f _vecPosition;
Vec4f _vecDirection;
Vec4f _vecDiffuse;
Vec4f _vecAmbient;
Vec4f _vecSpecular;
Vec3f _vecAttenuation; // constant, linear, and quadratic attenuation factors.
float _rSpotExponent;
float _rSpotCutoff;
static SkyMaterial *s_pMaterial; // used for rendering the lights during debugging
};
#endif //__SKYLIGHT_HPP__

View File

@@ -0,0 +1,445 @@
//------------------------------------------------------------------------------
// File : SkyMaterial.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyMaterial.cpp
*
* Implementation of class SkyMaterial, a meterial property object.
*/
#include "SkyMaterial.hpp"
#include "SkyContext.hpp"
//------------------------------------------------------------------------------
// Function : SkyMaterial::SkyMaterial
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMaterial::SkyMaterial()
* @brief Constructor.
*/
SkyMaterial::SkyMaterial()
: _iMaterialID(-1),
_vecDiffuse(Vec4f::ZERO),
_vecSpecular(Vec4f::ZERO),
_vecAmbient(Vec4f::ZERO),
_vecEmissive(Vec4f::ZERO),
_rSpecularPower(0),
_bLighting(true),
_eColorMaterialFace(GL_FRONT_AND_BACK),
_eColorMaterialMode(GL_AMBIENT_AND_DIFFUSE),
_bColorMaterial(false),
_vecFogColor(Vec4f::ZERO),
_eFogMode(GL_EXP),
_bFog(false),
_eDepthFunc(GL_LESS),
_bDepthMask(true),
_bDepthTest(true),
_eAlphaFunc(GL_ALWAYS),
_rAlphaRef(0),
_bAlphaTest(false),
_eBlendSrcFactor(GL_ONE),
_eBlendDstFactor(GL_ZERO),
_bBlending(false),
_bFaceCulling(false),
_eFaceCullingMode(GL_BACK),
_eTextureEnvMode(GL_MODULATE)
{
_rFogParams[SKY_FOG_DENSITY] = 1;
_rFogParams[SKY_FOG_START] = 0;
_rFogParams[SKY_FOG_END] = 1;
}
//------------------------------------------------------------------------------
// Function : SkyMaterial::~SkyMaterial
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMaterial::~SkyMaterial()
* @brief Destructor.
*/
SkyMaterial::~SkyMaterial()
{
}
//------------------------------------------------------------------------------
// Function : SkyMaterial::SetFogParameter
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMaterial::SetFogParameter(GLenum eParameter, float rValue)
*/
SKYRESULT SkyMaterial::SetFogParameter(GLenum eParameter, float rValue)
{
switch (eParameter)
{
case GL_FOG_DENSITY:
_rFogParams[SKY_FOG_DENSITY] = rValue;
break;
case GL_FOG_START:
_rFogParams[SKY_FOG_START] = rValue;
break;
case GL_FOG_END:
_rFogParams[SKY_FOG_END] = rValue;
break;
default:
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyMaterial::SetFogParameter(): Invalid parameter.");
break;
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyMaterial::GetFogParameter
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMaterial::GetFogParameter(GLenum eParameter) const
*/
float SkyMaterial::GetFogParameter(GLenum eParameter) const
{
switch (eParameter)
{
case GL_FOG_DENSITY:
return _rFogParams[SKY_FOG_DENSITY];
break;
case GL_FOG_START:
return _rFogParams[SKY_FOG_START];
break;
case GL_FOG_END:
return _rFogParams[SKY_FOG_END];
break;
default:
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyMaterial::GetFogParameter(): Invalid parameter.");
break;
}
return -1;
}
//------------------------------------------------------------------------------
// Function : SkyMaterial::Activate
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMaterial::Activate()
* @brief @todo <WRITE BRIEF SkyMaterial::SetMaterialPropertiesForDisplay DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyMaterial::SetMaterialPropertiesForDisplay FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyMaterial::Activate()
{
// Update the cached current material, and only pass values that have changed to the GL.
SkyMaterial *pCurrentMaterial = GraphicsContext::InstancePtr()->GetCurrentMaterial();
assert(NULL != pCurrentMaterial);
// basic material properties
if (pCurrentMaterial->GetDiffuse() != GetDiffuse())
{
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &(GetDiffuse().x));
pCurrentMaterial->SetDiffuse(GetDiffuse());
}
if (pCurrentMaterial->GetSpecular() != GetSpecular())
{
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &(GetSpecular().x));
pCurrentMaterial->SetSpecular(GetSpecular());
}
if (pCurrentMaterial->GetAmbient() != GetAmbient())
{
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &(GetAmbient().x));
pCurrentMaterial->SetAmbient(GetAmbient());
}
if (pCurrentMaterial->GetEmissive() != GetEmissive())
{
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &(GetEmissive().x));
pCurrentMaterial->SetEmissive(GetEmissive());
}
if (pCurrentMaterial->GetSpecularPower() != GetSpecularPower())
{
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GetSpecularPower());
pCurrentMaterial->SetSpecularPower(GetSpecularPower());
}
// lighting
if (pCurrentMaterial->IsLightingEnabled() != IsLightingEnabled())
{
if (IsLightingEnabled())
glEnable(GL_LIGHTING);
else
glDisable(GL_LIGHTING);
pCurrentMaterial->EnableLighting(IsLightingEnabled());
}
// color material (which material property tracks color calls)
if (pCurrentMaterial->GetColorMaterialFace() != GetColorMaterialFace() ||
pCurrentMaterial->GetColorMaterialMode() != GetColorMaterialMode())
{
glColorMaterial(GetColorMaterialFace(), GetColorMaterialMode());
pCurrentMaterial->SetColorMaterialFace(GetColorMaterialFace());
pCurrentMaterial->SetColorMaterialMode(GetColorMaterialMode());
}
if (pCurrentMaterial->IsColorMaterialEnabled() != IsColorMaterialEnabled())
{
if (IsColorMaterialEnabled())
glEnable(GL_COLOR_MATERIAL);
else
glDisable(GL_COLOR_MATERIAL);
pCurrentMaterial->EnableColorMaterial(IsColorMaterialEnabled());
}
// fog
if (pCurrentMaterial->GetFogMode() != GetFogMode())
{
glFogf(GL_FOG_MODE, GetFogMode());
pCurrentMaterial->SetFogMode(GetFogMode());
}
if (pCurrentMaterial->GetFogColor() != GetFogColor())
{
glFogfv(GL_FOG_COLOR, GetFogColor());
pCurrentMaterial->SetFogColor(GetFogColor());
}
if (pCurrentMaterial->GetFogParameter(GL_FOG_DENSITY) != GetFogParameter(GL_FOG_DENSITY))
{
glFogf(GL_FOG_DENSITY, GetFogParameter(GL_FOG_DENSITY));
pCurrentMaterial->SetFogParameter(GL_FOG_DENSITY, GetFogParameter(GL_FOG_DENSITY));
}
if (pCurrentMaterial->GetFogParameter(GL_FOG_START) != GetFogParameter(GL_FOG_START))
{
glFogf(GL_FOG_START, GetFogParameter(GL_FOG_START));
pCurrentMaterial->SetFogParameter(GL_FOG_START, GetFogParameter(GL_FOG_START));
}
if (pCurrentMaterial->GetFogParameter(GL_FOG_END) != GetFogParameter(GL_FOG_END))
{
glFogf(GL_FOG_END, GetFogParameter(GL_FOG_END));
pCurrentMaterial->SetFogParameter(GL_FOG_END, GetFogParameter(GL_FOG_END));
}
if (pCurrentMaterial->IsFogEnabled() != IsFogEnabled())
{
if (IsFogEnabled())
glEnable(GL_FOG);
else
glDisable(GL_FOG);
pCurrentMaterial->EnableFog(IsFogEnabled());
}
// depth test
if (pCurrentMaterial->GetDepthFunc() != GetDepthFunc())
{
glDepthFunc(GetDepthFunc());
pCurrentMaterial->SetDepthFunc(GetDepthFunc());
}
if (pCurrentMaterial->GetDepthMask() != GetDepthMask())
{
glDepthMask(GetDepthMask());
pCurrentMaterial->SetDepthMask(GetDepthMask());
}
if (pCurrentMaterial->IsDepthTestEnabled() != IsDepthTestEnabled())
{
if (IsDepthTestEnabled())
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
pCurrentMaterial->EnableDepthTest(IsDepthTestEnabled());
}
// alpha test
if (pCurrentMaterial->GetAlphaFunc() != GetAlphaFunc() ||
pCurrentMaterial->GetAlphaRef() != GetAlphaRef())
{
glAlphaFunc(GetAlphaFunc(), GetAlphaRef());
pCurrentMaterial->SetAlphaFunc(GetAlphaFunc());
pCurrentMaterial->SetAlphaRef(GetAlphaRef());
}
if (pCurrentMaterial->IsAlphaTestEnabled() != IsAlphaTestEnabled())
{
if (IsAlphaTestEnabled())
glEnable(GL_ALPHA_TEST);
else
glDisable(GL_ALPHA_TEST);
pCurrentMaterial->EnableAlphaTest(IsAlphaTestEnabled());
}
// blending
if (pCurrentMaterial->GetBlendingSourceFactor() != GetBlendingSourceFactor() ||
pCurrentMaterial->GetBlendingDestFactor() != GetBlendingDestFactor())
{
glBlendFunc(GetBlendingSourceFactor(), GetBlendingDestFactor());
pCurrentMaterial->SetBlendFunc(GetBlendingSourceFactor(), GetBlendingDestFactor());
}
if (pCurrentMaterial->IsBlendingEnabled() != IsBlendingEnabled())
{
if (IsBlendingEnabled())
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
pCurrentMaterial->EnableBlending(IsBlendingEnabled());
}
if (pCurrentMaterial->GetFaceCullingMode() != GetFaceCullingMode())
{
glCullFace(GetFaceCullingMode());
pCurrentMaterial->SetFaceCullingMode(GetFaceCullingMode());
}
if (pCurrentMaterial->IsFaceCullingEnabled() != IsFaceCullingEnabled())
{
if (IsFaceCullingEnabled())
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
pCurrentMaterial->EnableFaceCulling(IsFaceCullingEnabled());
}
// texturing
FAIL_RETURN(_textureState.Activate());
if (pCurrentMaterial->GetTextureApplicationMode() != GetTextureApplicationMode())
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GetTextureApplicationMode());
pCurrentMaterial->SetTextureApplicationMode(GetTextureApplicationMode());
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyMaterial::Force
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMaterial::Force()
* @brief @todo <WRITE BRIEF SkyMaterial::SetMaterialPropertiesForDisplay DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyMaterial::SetMaterialPropertiesForDisplay FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyMaterial::Force()
{
// Update the cached current material, and only pass values that have changed to the GL.
SkyMaterial *pCurrentMaterial = GraphicsContext::InstancePtr()->GetCurrentMaterial();
assert(NULL != pCurrentMaterial);
// basic material properties
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &(GetDiffuse().x));
pCurrentMaterial->SetDiffuse(GetDiffuse());
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &(GetSpecular().x));
pCurrentMaterial->SetSpecular(GetSpecular());
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &(GetAmbient().x));
pCurrentMaterial->SetAmbient(GetAmbient());
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &(GetEmissive().x));
pCurrentMaterial->SetEmissive(GetEmissive());
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GetSpecularPower());
pCurrentMaterial->SetSpecularPower(GetSpecularPower());
// lighting
if (IsLightingEnabled())
glEnable(GL_LIGHTING);
else
glDisable(GL_LIGHTING);
pCurrentMaterial->EnableLighting(IsLightingEnabled());
// color material (which material property tracks color calls)
glColorMaterial(GetColorMaterialFace(), GetColorMaterialMode());
pCurrentMaterial->SetColorMaterialFace(GetColorMaterialFace());
pCurrentMaterial->SetColorMaterialMode(GetColorMaterialMode());
if (IsColorMaterialEnabled())
glEnable(GL_COLOR_MATERIAL);
else
glDisable(GL_COLOR_MATERIAL);
pCurrentMaterial->EnableColorMaterial(IsColorMaterialEnabled());
// fog
glFogf(GL_FOG_MODE, GetFogMode());
pCurrentMaterial->SetFogMode(GetFogMode());
glFogfv(GL_FOG_COLOR, GetFogColor());
pCurrentMaterial->SetFogColor(GetFogColor());
glFogf(GL_FOG_DENSITY, GetFogParameter(GL_FOG_DENSITY));
pCurrentMaterial->SetFogParameter(GL_FOG_DENSITY, GetFogParameter(GL_FOG_DENSITY));
glFogf(GL_FOG_START, GetFogParameter(GL_FOG_START));
pCurrentMaterial->SetFogParameter(GL_FOG_START, GetFogParameter(GL_FOG_START));
glFogf(GL_FOG_END, GetFogParameter(GL_FOG_END));
pCurrentMaterial->SetFogParameter(GL_FOG_END, GetFogParameter(GL_FOG_END));
if (IsFogEnabled())
glEnable(GL_FOG);
else
glDisable(GL_FOG);
pCurrentMaterial->EnableFog(IsFogEnabled());
// depth test
glDepthFunc(GetDepthFunc());
pCurrentMaterial->SetDepthFunc(GetDepthFunc());
glDepthMask(GetDepthMask());
pCurrentMaterial->SetDepthMask(GetDepthMask());
if (IsDepthTestEnabled())
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
pCurrentMaterial->EnableDepthTest(IsDepthTestEnabled());
// alpha test
glAlphaFunc(GetAlphaFunc(), GetAlphaRef());
pCurrentMaterial->SetAlphaFunc(GetAlphaFunc());
pCurrentMaterial->SetAlphaRef(GetAlphaRef());
if (IsAlphaTestEnabled())
glEnable(GL_ALPHA_TEST);
else
glDisable(GL_ALPHA_TEST);
// blending
glBlendFunc(GetBlendingSourceFactor(), GetBlendingDestFactor());
pCurrentMaterial->SetBlendFunc(GetBlendingSourceFactor(), GetBlendingDestFactor());
if (IsBlendingEnabled())
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
pCurrentMaterial->EnableBlending(IsBlendingEnabled());
glCullFace(GetFaceCullingMode());
pCurrentMaterial->SetFaceCullingMode(GetFaceCullingMode());
if (IsFaceCullingEnabled())
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
pCurrentMaterial->EnableFaceCulling(IsFaceCullingEnabled());
// texturing
FAIL_RETURN(_textureState.Force());
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GetTextureApplicationMode());
pCurrentMaterial->SetTextureApplicationMode(GetTextureApplicationMode());
return SKYRESULT_OK;
}

View File

@@ -0,0 +1,269 @@
//------------------------------------------------------------------------------
// File : SkyMaterial.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyMaterial.hpp
*
* Interface definition for class SkyMaterial, a meterial property object.
*/
#ifndef __SKYMATERIAL_HPP__
#define __SKYMATERIAL_HPP__
// #pragma warning( disable : 4786)
#include "vec4f.hpp"
#include "SkyUtil.hpp"
#include "SkyTextureManager.hpp"
#include "SkyTextureState.hpp"
#include <GL/glut.h>
// forward
class SkyRenderable;
//------------------------------------------------------------------------------
/**
* @class SkyMaterial
* @brief A class for organizing and caching material state.
*
* This class handles setting and querying material state. By calling the Activate()
* method, the material's state can be made current in OpenGL. The material will not
* set states that are currently active in the current OpenGL context.
*/
class SkyMaterial
{
public:
SkyMaterial();
~SkyMaterial();
SKYRESULT Activate();
SKYRESULT Force();
// Getters for basic material properties
//! Returns the material identifier.
int GetMaterialID() const { return _iMaterialID; }
//! Returns the material diffuse color.
const Vec4f& GetDiffuse() const { return _vecDiffuse; }
//! Returns the material specular color.
const Vec4f& GetSpecular() const { return _vecSpecular; }
//! Returns the material ambient color.
const Vec4f& GetAmbient() const { return _vecAmbient; }
//! Returns the material emissive color.
const Vec4f& GetEmissive() const { return _vecEmissive; }
//! Returns the material specular power (shininess).
const float GetSpecularPower() const { return _rSpecularPower; }
// lighting
//! Returns true if lighting is enabled for this material.
bool IsLightingEnabled() const { return _bLighting; }
// color material (which material property tracks color calls)
//! Returns the face for which color material tracking is enabled.
GLenum GetColorMaterialFace() const { return _eColorMaterialFace; }
//! Returns the color material tracking mode.
GLenum GetColorMaterialMode() const { return _eColorMaterialMode; }
//! Returns true if color material tracking is enabled.
bool IsColorMaterialEnabled() const { return _bColorMaterial; }
//! Returns the fog density or start / end distance.
float GetFogParameter(GLenum eParameter) const;
//! Returns the fog mode (exponential, linear, etc.)
GLenum GetFogMode() const { return _eFogMode; }
//! Returns the fog color.
const Vec4f& GetFogColor() const { return _vecFogColor; }
//! Returns true if fog is enabled for this material.
bool IsFogEnabled() const { return _bFog; }
// texturing
//! Returns the active texture target for texture unit @a iTextureUnit.
GLenum GetActiveTarget(unsigned int iTextureUnit) const
{ return _textureState.GetActiveTarget(iTextureUnit); }
//! Returns the bound texture ID for texture unit @a iTextureUnit.
unsigned int GetTextureID(unsigned int iTextureUnit) const
{ return _textureState.GetTextureID(iTextureUnit); }
//! Returns true if texturing is enabled for texture unit @a iTextureUnit.
bool IsTextureEnabled(unsigned int iTextureUnit) const
{ return _textureState.IsTextureEnabled(iTextureUnit); }
//! Returns the value of the texture parameter @a eParameter for texture unit @a iTextureUnit.
GLenum GetTextureParameter(unsigned int iTextureUnit, GLenum eParameter) const
{ return _textureState.GetTextureParameter(iTextureUnit, eParameter); }
//! Returns the texture application mode of the texture environment.
GLenum GetTextureApplicationMode() const { return _eTextureEnvMode; }
//! Returns a reference to the texture state object owned by this materal.
SkyTextureState& GetTextureState() { return _textureState; }
// depth test
//! Returns true if depth testing is enabled for this material.
bool IsDepthTestEnabled() const { return _bDepthTest; }
//! Returns the depth test function for this material.
GLenum GetDepthFunc() const { return _eDepthFunc; }
//! Returns true if depth writes are enabled for this material, false if not.
bool GetDepthMask() const { return _bDepthMask; }
// alpha test
//! Returns true if alpha testing is enabled for this material.
bool IsAlphaTestEnabled() const { return _bAlphaTest; }
//! Returns the alpha test function for this material.
GLenum GetAlphaFunc() const { return _eAlphaFunc; }
//! Returns the reference value for alpha comparison.
float GetAlphaRef() const { return _rAlphaRef; }
// blending
//! Returns true if blending is enabled for this material.
bool IsBlendingEnabled() const { return _bBlending; }
//! Returns the source blending factor for this material.
GLenum GetBlendingSourceFactor() const { return _eBlendSrcFactor; }
//! Returns the destination blending factor for this material.
GLenum GetBlendingDestFactor() const { return _eBlendDstFactor; }
//! Returns true if face culling enabled for this material.
bool IsFaceCullingEnabled() const { return _bFaceCulling; }
//! Returns which faces are culled -- front-facing or back-facing.
GLenum GetFaceCullingMode() const { return _eFaceCullingMode; }
// Setters for basic material properties
//! Sets the material identifier.
void SetMaterialID(int ID) { _iMaterialID = ID; }
//! Sets the diffuse material color.
void SetDiffuse( const Vec4f& d) { _vecDiffuse = d; }
//! Sets the specular material color.
void SetSpecular(const Vec4f& d) { _vecSpecular = d; }
//! Sets the ambient material color.
void SetAmbient( const Vec4f& d) { _vecAmbient = d; }
//! Sets the emissive material color.
void SetEmissive(const Vec4f& d) { _vecEmissive = d; }
//! Sets the material specular power (shininess).
void SetSpecularPower(float power) { _rSpecularPower = power; }
// lighting
//! Enables / Disables lighting for this material.
void EnableLighting(bool bEnable) { _bLighting = bEnable; }
// color material (which material property tracks color calls)
//! Sets which faces (front or back) track color calls.
void SetColorMaterialFace(GLenum eFace) { _eColorMaterialFace = eFace; }
//! Sets which material property tracks color calls.
void SetColorMaterialMode(GLenum eMode) { _eColorMaterialMode = eMode; }
//! Enables / Disables material color tracking for this material.
void EnableColorMaterial(bool bEnable) { _bColorMaterial = bEnable; }
//! Sets the fog density or start / end distance.
SKYRESULT SetFogParameter(GLenum eParameter, float rValue);
//! Sets the fog mode (exponential, linear, etc.)
void SetFogMode(GLenum eMode) { _eFogMode = eMode; }
//! Sets the fog color.
void SetFogColor(const Vec4f& color) { _vecFogColor = color; }
//! Enables / Disables fog for this material.
void EnableFog(bool bEnable) { _bFog = bEnable; }
// texturing
//! Sets the bound texture and texture target for texture unit @a iTextureUnit.
SKYRESULT SetTexture(unsigned int iTextureUnit, GLenum eTarget, SkyTexture& texture)
{ return _textureState.SetTexture(iTextureUnit, eTarget, texture); }
//! Sets the bound texture and texture target for texture unit @a iTextureUnit.
SKYRESULT SetTexture(unsigned int iTextureUnit, GLenum eTarget, unsigned int iTextureID)
{ return _textureState.SetTexture(iTextureUnit, eTarget, iTextureID); }
//! Enables / Disables texture unit @a iTextureUnit for this material.
SKYRESULT EnableTexture(unsigned int iTextureUnit, bool bEnable)
{ return _textureState.EnableTexture(iTextureUnit, bEnable); }
//! Sets the value of the texture parameter @a eParameter for texture unit @a iTextureUnit.
SKYRESULT SetTextureParameter(unsigned int iTextureUnit, GLenum eParameter, GLenum eMode)
{ return _textureState.SetTextureParameter(iTextureUnit, eParameter, eMode); }
//! Sets the texture application mode of the texture environment.
void SetTextureApplicationMode(GLenum eMode){ _eTextureEnvMode = eMode;}
// depth test
//! Enables / Disables depth test for this material.
void EnableDepthTest(bool bEnable) { _bDepthTest = bEnable; }
//! Sets the depth test function (greater, less than, equal, etc.).
void SetDepthFunc(GLenum eDepthFunc) { _eDepthFunc = eDepthFunc;}
//! If @a bDepthMask is true, then depth writes are enabled, otherwise they are not.
void SetDepthMask(bool bDepthMask) { _bDepthMask = bDepthMask;}
// alpha test
//! Enables / Disables alpha test for this material.
void EnableAlphaTest(bool bEnable) { _bAlphaTest = bEnable; }
//! Sets the alpha test function (greater, less than, equal, etc.).
void SetAlphaFunc(GLenum eAlphaFunc) { _eAlphaFunc = eAlphaFunc;}
//! Sets the reference value against which fragment alpha values are compared.
void SetAlphaRef(float rAlphaRef) { _rAlphaRef = rAlphaRef; }
// blending
//! Enables / Disables blending for this material.
void EnableBlending(bool bEnable) { _bBlending = bEnable; }
//! Sets the source and destination blending factors for this material.
void SetBlendFunc(GLenum eSrcFactor, GLenum eDstFactor)
{ _eBlendSrcFactor = eSrcFactor; _eBlendDstFactor = eDstFactor; }
//! Enables / Disables face culling for this material.
void EnableFaceCulling(bool bEnable) { _bFaceCulling = bEnable; }
//! Sets which faces will be culled -- front facing or back facing.
void SetFaceCullingMode(GLenum eMode) { _eFaceCullingMode = eMode; }
protected:
int _iMaterialID;
Vec4f _vecDiffuse;
Vec4f _vecSpecular;
Vec4f _vecAmbient;
Vec4f _vecEmissive;
float _rSpecularPower;
bool _bLighting;
GLenum _eColorMaterialFace;
GLenum _eColorMaterialMode;
bool _bColorMaterial;
enum SkyFogParams
{
SKY_FOG_DENSITY,
SKY_FOG_START,
SKY_FOG_END,
SKY_FOG_NUM_PARAMS
};
Vec4f _vecFogColor;
GLenum _eFogMode;
float _rFogParams[SKY_FOG_NUM_PARAMS];
bool _bFog;
GLenum _eDepthFunc;
bool _bDepthMask;
bool _bDepthTest;
GLenum _eAlphaFunc;
float _rAlphaRef;
bool _bAlphaTest;
GLenum _eBlendSrcFactor;
GLenum _eBlendDstFactor;
bool _bBlending;
bool _bFaceCulling;
GLenum _eFaceCullingMode;
SkyTextureState _textureState;
GLenum _eTextureEnvMode;
};
#endif //__SKYMATERIAL_HPP__

View File

@@ -0,0 +1,322 @@
//------------------------------------------------------------------------------
// File : SkyMinMaxBox.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyMinMaxBox.cpp
*
* Implementation of a bounding box class. Modified from Wes Hunt's BoundingBox.
*/
#include "SkyMinMaxBox.hpp"
#include "camutils.hpp"
#include <GL/glut.h>
#include <float.h>
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::SkyMinMaxBox
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::SkyMinMaxBox()
* @brief Constructor
*/
SkyMinMaxBox::SkyMinMaxBox()
{
Clear();
}
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::Clear
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::Clear()
* @brief Reset the min and max to floating point extremes.
*
*/
void SkyMinMaxBox::Clear()
{
_min.x = FLT_MAX;
_min.y = FLT_MAX;
_min.z = FLT_MAX;
_max.x = -FLT_MAX;
_max.y = -FLT_MAX;
_max.z = -FLT_MAX;
}
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::PointInBBox
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::PointInBBox( const Vec3f &pt ) const
* @brief Queries pt to see if it is inside the SkyMinMaxBox.
*
*/
bool SkyMinMaxBox::PointInBBox( const Vec3f &pt ) const
{
if( (pt.x >= _min.x) && ( pt.x <= _max.x ) )
{
if( (pt.y >= _min.y) && ( pt.y <= _max.y ) )
{
if( (pt.z >= _min.z) && ( pt.z <= _max.z ) )
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::AddPoint
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::AddPoint( float x , float y , float z )
* @brief Adds a point and adjusts bounds if necessary.
*/
void SkyMinMaxBox::AddPoint( float x , float y , float z )
{
if( x > _max.x )
_max.x = x;
if( x < _min.x )
_min.x = x;
if( y > _max.y )
_max.y = y;
if( y < _min.y )
_min.y = y;
if( z > _max.z )
_max.z = z;
if( z < _min.z )
_min.z = z;
// update the center and radius
_UpdateSphere();
}
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::AddPoint
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::AddPoint( const Vec3f &pt )
* @brief Adds a point and adjusts bounds if necessary.
*/
void SkyMinMaxBox::AddPoint( const Vec3f &pt )
{
if( pt.x > _max.x )
_max.x = pt.x;
if( pt.x < _min.x )
_min.x = pt.x;
if( pt.y > _max.y )
_max.y = pt.y;
if( pt.y < _min.y )
_min.y = pt.y;
if( pt.z > _max.z )
_max.z = pt.z;
if( pt.z < _min.z )
_min.z = pt.z;
// update the center and radius
_UpdateSphere();
}
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::ViewFrustumCull
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::ViewFrustumCull( const Camera &cam, const Mat44f &mat )
* @brief Returns true if bounding volume culled against cam.
*
* This function must transform the object space min and max then adjust the new
* min and max box by expanding it. Each of the 8 points must be tested. This
* is faster then doing an xform of all the geometry points and finding a tight
* fitting min max box, however this will be enlarged.
*/
bool SkyMinMaxBox::ViewFrustumCull( const Camera &cam, const Mat44f &mat )
{
SkyMinMaxBox xBV; // Xformed Bounding Volume
Vec3f xMin = mat * _min; // Xformed _min
Vec3f xMax = mat * _max; // Xformed _max
Vec3f offset = _max - _min; // Offset for sides of MinMaxBox
Vec3f tmp;
xBV.Clear(); // Clear the values first
// First find the new minimum x,y,z
// Find min + x
tmp.Set(mat.M[0], mat.M[4], mat.M[8]);
tmp *= offset.x;
tmp += xMin;
xBV.AddPoint(tmp);
// Find min + y
tmp.Set(mat.M[1], mat.M[5], mat.M[9]);
tmp *= offset.y;
tmp += xMin;
xBV.AddPoint(tmp);
// Find min + z
tmp.Set(mat.M[3], mat.M[6], mat.M[10]);
tmp *= offset.z;
tmp += xMin;
xBV.AddPoint(tmp);
// Second find the new maximum x,y,z
// Find max - x
tmp.Set(mat.M[0], mat.M[4], mat.M[8]);
tmp *= -offset.x;
tmp += xMax;
xBV.AddPoint(tmp);
// Find max - y
tmp.Set(mat.M[1], mat.M[5], mat.M[9]);
tmp *= -offset.y;
tmp += xMax;
xBV.AddPoint(tmp);
// Find max - z
tmp.Set(mat.M[3], mat.M[6], mat.M[10]);
tmp *= -offset.z;
tmp += xMax;
xBV.AddPoint(tmp);
// Use the camera utility function that already exists for minmax boxes
return VFC(&cam, xBV.GetMin(), xBV.GetMax());
}
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::Transform
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::Transform(const Mat44f& mat)
* @brief @todo <WRITE BRIEF SkyMinMaxBox::Transform DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyMinMaxBox::Transform FUNCTION DOCUMENTATION>
*/
void SkyMinMaxBox::Transform(const Mat44f& mat)
{
Vec3f verts[8];
_CalcVerts(verts);
Clear();
for (int i = 0; i < 8; ++i)
{
AddPoint(mat * verts[i]);
}
}
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::_UpdateSphere
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::_UpdateSphere()
* @brief Updates the bounding sphere based on min and max.
*/
void SkyMinMaxBox::_UpdateSphere()
{
_vecCenter = _min;
_vecCenter += _max;
_vecCenter *= 0.5f;
Vec3f rad = _max;
rad -= _vecCenter;
_rRadius = rad.Length();
}
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::Display
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::Display() const
* @brief @todo <WRITE BRIEF SkyMinMaxBox::Display DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyMinMaxBox::Display FUNCTION DOCUMENTATION>
*/
void SkyMinMaxBox::Display() const
{
Vec3f V[8];
_CalcVerts(V);
glPushAttrib(GL_LINE_BIT);
glLineWidth(1.0);
glBegin(GL_LINE_LOOP); // TOP FACE
glVertex3fv(V[4]); glVertex3fv(V[5]); glVertex3fv(V[1]); glVertex3fv(V[0]);
glEnd();
glBegin(GL_LINE_LOOP); // BOTTOM FACE
glVertex3fv(V[3]); glVertex3fv(V[2]); glVertex3fv(V[6]); glVertex3fv(V[7]);
glEnd();
glBegin(GL_LINE_LOOP); // LEFT FACE
glVertex3fv(V[1]); glVertex3fv(V[5]); glVertex3fv(V[6]); glVertex3fv(V[2]);
glEnd();
glBegin(GL_LINE_LOOP); // RIGHT FACE
glVertex3fv(V[0]); glVertex3fv(V[3]); glVertex3fv(V[7]); glVertex3fv(V[4]);
glEnd();
glBegin(GL_LINE_LOOP); // NEAR FACE
glVertex3fv(V[1]); glVertex3fv(V[2]); glVertex3fv(V[3]); glVertex3fv(V[0]);
glEnd();
glBegin(GL_LINE_LOOP); // FAR FACE
glVertex3fv(V[4]); glVertex3fv(V[7]); glVertex3fv(V[6]); glVertex3fv(V[5]);
glEnd();
glPopAttrib();
}
//-----------------------------------------------------------------------------
// Calculates the eight corner vertices of the MinMaxBox.
// V must be prealloced.
// 5---4
// / /|
// 1---0 | VERTS : 0=RTN,1=LTN,2=LBN,3=RBN,4=RTF,5=LTF,6=LBF,7=RBF
// | | 7 (L,R, B,T, N,F) = (Left,Right, Bottom,Top, Near,Far)
// | |/
// 2---3
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Function : SkyMinMaxBox::_CalcVerts
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyMinMaxBox::_CalcVerts(Vec3f pVerts[8]) const
* @brief @todo <WRITE BRIEF SkyMinMaxBox::_CalcVerts DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyMinMaxBox::_CalcVerts FUNCTION DOCUMENTATION>
*/
void SkyMinMaxBox::_CalcVerts(Vec3f pVerts[8]) const
{
pVerts[0].Set(_max); pVerts[4].Set(_max.x, _max.y, _min.z);
pVerts[1].Set(_min.x, _max.y, _max.z); pVerts[5].Set(_min.x, _max.y, _min.z);
pVerts[2].Set(_min.x, _min.y, _max.z); pVerts[6].Set(_min);
pVerts[3].Set(_max.x, _min.y, _max.z); pVerts[7].Set(_max.x, _min.y, _min.z);
}

View File

@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
// File : SkyMinMaxBox.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyMinMaxBox.hpp
*
* Interface definition for a min-max bounding box class for bounding volume hierarchies.
*/
#ifndef __SKYMINMAXBOX_HPP__
#define __SKYMINMAXBOX_HPP__
#include "SkyBoundingVolume.hpp"
//------------------------------------------------------------------------------
/**
* @class SkyMinMaxBox
* @brief An AABB class that can be used in bounding volume hierarchies.
*
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
*/
class SkyMinMaxBox : public SkyBoundingVolume
{
public:
SkyMinMaxBox();
//! Destructor
virtual ~SkyMinMaxBox() {}
void AddPoint( const Vec3f &pt );
void AddPoint( float x , float y , float z );
//! Expand this box to contain @a box.
void Union(const SkyMinMaxBox& box) { AddPoint(box.GetMin()); AddPoint(box.GetMax()); }
//! Returns the minimum corner of the bounding box.
const Vec3f &GetMin() const { return _min; }
//! Returns the maximum corner of the bounding box.
const Vec3f &GetMax() const { return _max; }
//! Sets the minimum corner of the bounding box.
void SetMin(const Vec3f &min) { _min = min; _UpdateSphere(); }
//! Sets the maximum corner of the bounding box.
void SetMax(const Vec3f &max) { _max = max; _UpdateSphere(); }
//! Returns the X width of the bounding box.
float GetWidthInX() const { return _max.x - _min.x;}
//! Returns the Y width of the bounding box.
float GetWidthInY() const { return _max.y - _min.y;}
//! Returns the Z width of the bounding box.
float GetWidthInZ() const { return _max.z - _min.z;}
bool PointInBBox( const Vec3f &pt ) const;
bool ViewFrustumCull( const Camera &cam, const Mat44f &mat );
void Transform(const Mat44f& mat);
// Reset the bounding box
void Clear();
void Display() const;
protected:
void _UpdateSphere();
void _CalcVerts(Vec3f pVerts[8]) const;
private:
Vec3f _min; // Original object space BV
Vec3f _max;
};
#endif //__SKYMINMAXBOX_HPP__

View File

@@ -0,0 +1,116 @@
//------------------------------------------------------------------------------
// File : SkyRenderable.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
//------------------------------------------------------------------------------
// File : SkyRenderable.hpp
//------------------------------------------------------------------------------
// Sky : Copyright 2002 Mark J. Harris and Andrew Zaferakis
//------------------------------------------------------------------------------
/**
* @file SkyRenderable.hpp
*
* Abstract base class definition for SkyRenderable, a renderable object class.
*/
#ifndef __SKYRENDERABLE_HPP__
#define __SKYRENDERABLE_HPP__
#pragma warning( disable : 4786)
#include <string>
#include "SkyUtil.hpp"
// forward to reduce unnecessary dependencies
class SkyMinMaxBox;
class SkyRenderableInstance;
class Camera;
//------------------------------------------------------------------------------
/**
* @class SkyRenderable
* @brief An base class for renderable objects.
*
* Each SkyRenderable object should know how to Display itself, however some
* objects may not have a bounding volume that is useful (skybox, etc.)
*/
class SkyRenderable
{
public:
//! Constructor
SkyRenderable() {}
//! Destructor
virtual ~SkyRenderable() { }
//------------------------------------------------------------------------------
// Function : SetName
// Description :
//------------------------------------------------------------------------------
/**
* @fn SetName(const std::string &name)
* @brief Set a name for this renderable.
*/
void SetName(const std::string &name) { _name = name; }
//------------------------------------------------------------------------------
// Function : GetName
// Description :
//------------------------------------------------------------------------------
/**
* @fn GetName() const
* @brief Get the name of this renderable.
*/
const std::string& GetName() const { return _name; }
//------------------------------------------------------------------------------
// Function : Update
// Description :
//------------------------------------------------------------------------------
/**
* @fn Update(const Camera &cam, SkyRenderableInstance *pInstance)
* @brief Update the state of the renderable.
*
* This method is optional, as some renderables will need periodic updates
* (i.e. for animation) and others will not.
*/
virtual SKYRESULT Update(const Camera &cam, SkyRenderableInstance *pInstance = NULL)
{ return SKYRESULT_OK; }
//------------------------------------------------------------------------------
// Function : Display
// Description :
//------------------------------------------------------------------------------
/**
* @fn Display(const Camera &cam, SkyRenderableInstance *pInstance)
* @brief Display the object.
*/
virtual SKYRESULT Display(const Camera &cam, SkyRenderableInstance *pInstance = NULL) = 0;
//------------------------------------------------------------------------------
// Function : CopyBoundingVolume
// Description :
//------------------------------------------------------------------------------
/**
* @fn CopyBoundingVolume() const
* @brief Create a copy of the object's bounding volume, useful for collision, VFC, etc.
*/
virtual SkyMinMaxBox* CopyBoundingVolume() const = 0;// { return 0; }
protected:
std::string _name; // the name of this renderable.
};
#endif //__SKYRENDERABLE_HPP__

View File

@@ -0,0 +1,202 @@
//------------------------------------------------------------------------------
// File : SkyRenderableInstance.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyRenderableInstance.hpp
*
* Interface definition for SkyRenderableInstance, an instance of a renderable object.
*/
#ifndef __SKYRENDERABLEINSTANCE_HPP__
#define __SKYRENDERABLEINSTANCE_HPP__
#include <vector>
#include "mat33.hpp"
#include "mat44.hpp"
#include "SkyUtil.hpp"
// forward to reduce unnecessary dependencies
class Camera;
class SkyMinMaxBox;
// forward so we can make the following typedefs easily visible in the header.
// rather than buried under the class definition.
class SkyRenderableInstance;
//! A dynamic array of SkyRenderableInstance pointers.
typedef std::vector<SkyRenderableInstance*> InstanceArray;
//! An instance array iterator.
typedef InstanceArray::iterator InstanceIterator;
//------------------------------------------------------------------------------
/**
* @class SkyRenderableInstance
* @brief An instance of a SkyRenderable object.
*
* An instance contains a pointer to a SkyRenderable object. The
* instance contains attributes such as position, orientation,
* scale, etc. that vary between instances.
*/
class SkyRenderableInstance
{
public:
//! Constructor.
SkyRenderableInstance()
: _bCulled(false), _bAlive(true), _vecPosition(0, 0, 0), _rScale(1), _rSquareSortDistance(0)
{
_matRotation.Identity(); _matInvRotation.Identity();
}
//! Constructor.
SkyRenderableInstance(const Vec3f &position,
const Mat33f &rotation,
const float scale)
: _bCulled(false), _bAlive(true), _vecPosition(position),
_matRotation(rotation), _rScale(scale), _rSquareSortDistance(0)
{
_matInvRotation = _matRotation;
_matInvRotation.Transpose();
}
//! Destructor
virtual ~SkyRenderableInstance() {}
// Setters / Getters
//! Set the world space position of the instance.
virtual void SetPosition(const Vec3f &position) { _vecPosition = position; }
//! Set the world space rotation of the instance.
virtual void SetRotation(const Mat33f &rotation) { _matRotation = rotation;
_matInvRotation = rotation;
_matInvRotation.Transpose(); }
//! Set the world space scale of the instance.
virtual void SetScale( const float &scale) { _rScale = scale; }
//! Returns the world space position of the instance.
virtual const Vec3f& GetPosition() const { return _vecPosition; }
//! Returns the world space rotation matrix of the instance.
virtual const Mat33f& GetRotation() const { return _matRotation; }
//! Returns the inverse of the world space rotation matrix of the instance.
virtual const Mat33f& GetInverseRotation() const { return _matInvRotation; }
//! Returns the world space scale of the instance.
virtual float GetScale() const { return _rScale; }
//! Update the instance based on the given camera, @a cam.
virtual SKYRESULT Update(const Camera &cam) { return SKYRESULT_OK; }
//! Render the instance.
virtual SKYRESULT Display() { return SKYRESULT_OK; }
//! Returns the transform matrix from model space to world space.
inline virtual void GetModelToWorldTransform(Mat44f &mat) const;
//! Returns the transform matrix from world space to model space.
inline virtual void GetWorldToModelTransform(Mat44f &mat) const;
//! Returns the object-space bounding volume for this instance, or NULL if none is available.
virtual SkyMinMaxBox* GetBoundingVolume() const { return NULL; }
//! Returns true if and only if the bounding volume of this instance lies entirely outside @a cam.
virtual bool ViewFrustumCull(const Camera &cam) { return false; }
//! Returns true if the instance was culled.
virtual bool IsCulled() { return _bCulled; }
//! Sets the culled state of the instance.
virtual void SetCulled(bool bCulled) { _bCulled = bCulled; }
//! Returns true if the instance is currently active.
virtual bool IsAlive() { return _bAlive; }
//! Activates or deactivates the instance.
virtual void SetIsAlive(bool bAlive) { _bAlive = bAlive; }
//! Sets the distance of this object from the sort position. Used to sort instances.
virtual void SetSquareSortDistance(float rSqrDist) { _rSquareSortDistance = rSqrDist; }
//! Returns the distance of this object from the sort position. (Set with SetSquareSortDistance())
virtual float GetSquareSortDistace() const { return _rSquareSortDistance; }
//! This operator is used to sort instance arrays.
bool operator<(const SkyRenderableInstance& instance) const
{
return (_rSquareSortDistance > instance._rSquareSortDistance);
}
protected:
bool _bCulled; // Culled flag
bool _bAlive; // Alive object flag
Vec3f _vecPosition; // Position
Mat33f _matRotation; // Rotation
Mat33f _matInvRotation; // inverse rotation
float _rScale; // Scale
// for sorting particles during shading
float _rSquareSortDistance;
};
//------------------------------------------------------------------------------
// Function : SkyRenderableInstance::GetModelToWorldTransform
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstance::GetModelToWorldTransform(Mat44f &mat) const
* @brief Returns the 4x4 transformation matrix from world to model space.
*/
inline void SkyRenderableInstance::GetModelToWorldTransform(Mat44f &mat) const
{
mat[0] = _matRotation.M[0]; mat[4] = _matRotation.M[3];
mat[8] = _matRotation.M[6]; mat[12] = 0;
mat[1] = _matRotation.M[1]; mat[5] = _matRotation.M[4];
mat[9] = _matRotation.M[7]; mat[13] = 0;
mat[2] = _matRotation.M[2]; mat[6] = _matRotation.M[5];
mat[10] = _matRotation.M[8]; mat[14] = 0;
mat[3] = 0; mat[7] = 0; mat[11] = 0; mat[15] = 0;
// Scale the matrix (we don't want to scale translation or mat[15] which is 1)
if (_rScale != 1)
mat *= _rScale;
// Set the translation and w coordinate after the potential scaling
mat[12] = _vecPosition.x; mat[13] = _vecPosition.y; mat[14] = _vecPosition.z;
mat[15] = 1;
}
//------------------------------------------------------------------------------
// Function : Mat44f& SkyRenderableInstance::GetWorldToModelTransform
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstance::GetWorldToModelTransform(Mat44f &mat) const
* @brief Returns the 4x4 transformation matrix from world to model space.
*/
inline void SkyRenderableInstance::GetWorldToModelTransform(Mat44f &mat) const
{
mat[0] = _matRotation.M[0]; mat[4] = _matRotation.M[1];
mat[8] = _matRotation.M[2]; mat[12] = 0;
mat[1] = _matRotation.M[3]; mat[5] = _matRotation.M[4];
mat[9] = _matRotation.M[5]; mat[13] = 0;
mat[2] = _matRotation.M[6]; mat[6] = _matRotation.M[7];
mat[10] = _matRotation.M[8]; mat[14] = 0;
mat[3] = 0; mat[7] = 0; mat[11] = 0; mat[15] = 0;
// Scale the matrix (we don't want to scale translation or mat[15] which is 1)
if (_rScale != 1)
mat *= (1 / _rScale);
// Set the translation and w coordinate after the potential scaling
mat[12] = -_vecPosition.x; mat[13] = -_vecPosition.y; mat[14] = -_vecPosition.z;
mat[15] = 1;
}
#endif //__SKYRENDERABLEINSTANCE_HPP__

View File

@@ -0,0 +1,708 @@
//------------------------------------------------------------------------------
// File : SkyRenderableInstanceCloud.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyRenderableInstanceCloud.cpp
*
* Implementation of class SkyRenderableInstanceCloud.
*/
#include "SkyUtil.hpp"
#include "SkyCloud.hpp"
#include "SkyMaterial.hpp"
#include "SkyBoundingVolume.hpp"
#include "SkyRenderableInstanceCloud.hpp"
#include "SkyDynamicTextureManager.hpp"
//! Set this to 1 to see verbose messages about impostor updates.
#define SKYCLOUD_VERBOSE 0
//! Set this to control the number of frames a cloud has to be culled before its textures are released.
#define SKYCLOUD_CULL_RELEASE_COUNT 100
//------------------------------------------------------------------------------
// Static declarations.
//------------------------------------------------------------------------------
unsigned int SkyRenderableInstanceCloud::s_iCount = 0;
float SkyRenderableInstanceCloud::s_rErrorToleranceAngle = SKYDEGREESTORADS * 0.125f;
SkyMaterial* SkyRenderableInstanceCloud::s_pMaterial = NULL;
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::SkyRenderableInstanceCloud
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::SkyRenderableInstanceCloud(SkyCloud *pCloud, bool bUseOffScreenBuffer)
* @brief Constructor.
*/
SkyRenderableInstanceCloud::SkyRenderableInstanceCloud(SkyCloud *pCloud,
bool bUseOffScreenBuffer /* = true */)
: SkyRenderableInstance(),
_iCloudID(-1),
_pCloud(pCloud),
_pWorldSpaceBV(NULL),
_rRadius(0),
_bScreenImpostor(false),
_bImageExists(false),
_bEnabled(true),
_bUseOffScreenBuffer(bUseOffScreenBuffer),
_bSplit(false),
_vecSplit(0, 0, 0),
_vecNearPoint(0, 0, 0),
_vecFarPoint(0, 0, 0),
_iLogResolution(0),
_pBackTexture(NULL),
_pFrontTexture(NULL),
_iCulledCount(0)
{
_Initialize();
// cout << "Cloud Instance created" << endl;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::SkyRenderableInstanceCloud
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::SkyRenderableInstanceCloud(SkyCloud *pCloud, const Vec3f &position, const Mat33f &rotation, const float scale, bool bUseOffScreenBuffer)
* @brief Constructor.
*/
SkyRenderableInstanceCloud::SkyRenderableInstanceCloud(SkyCloud *pCloud,
const Vec3f &position,
const Mat33f &rotation,
const float scale,
bool bUseOffScreenBuffer /* = true */)
: SkyRenderableInstance(position, rotation, scale),
_iCloudID(-1),
_pCloud(pCloud),
_pWorldSpaceBV(NULL),
_rRadius(0),
_bScreenImpostor(false),
_bImageExists(false),
_bEnabled(true),
_bUseOffScreenBuffer(false),
_bSplit(false),
_vecSplit(0, 0, 0),
_vecNearPoint(0, 0, 0),
_vecFarPoint(0, 0, 0),
_iLogResolution(0),
_pBackTexture(NULL),
_pFrontTexture(NULL)
{
_Initialize();
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::~SkyRenderableInstanceCloud
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::~SkyRenderableInstanceCloud()
* @brief Destructor
*/
SkyRenderableInstanceCloud::~SkyRenderableInstanceCloud()
{
_pCloud = NULL;
SAFE_DELETE(_pWorldSpaceBV);
s_iCount--;
// delete the offscreen buffer when no one else is using it.
if (0 == s_iCount)
{
//JW?? SAFE_DELETE(s_pRenderBuffer);
SAFE_DELETE(s_pMaterial);
}
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::SetPosition
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::SetPosition(const Vec3f &position)
* @brief Set the world space position of the instance.
*
* @todo <WRITE EXTENDED SkyRenderableInstanceCloud::SetPosition FUNCTION DOCUMENTATION>
*/
void SkyRenderableInstanceCloud::SetPosition(const Vec3f &position)
{
if (_pCloud)
{
_pCloud->Translate(position - _vecPosition);
}
_vecPosition = position;
_UpdateWorldSpaceBounds();
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::SetRotation
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::SetRotation(const Mat33f &rotation)
* @brief Set the world space rotation of the instance.
*
* @todo <WRITE EXTENDED SkyRenderableInstanceCloud::SetRotation FUNCTION DOCUMENTATION>
*/
void SkyRenderableInstanceCloud::SetRotation(const Mat33f &rotation)
{
if (_pCloud)
{
_pCloud->Translate(-_vecPosition);
_pCloud->Rotate(_matInvRotation * rotation);
_pCloud->Translate(_vecPosition);
}
_matRotation = rotation;
_matInvRotation = rotation;
_matInvRotation.Transpose();
_UpdateWorldSpaceBounds();
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::SetScale
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::SetScale(const float &scale)
* @brief Set the world space scale of the instance.
*/
void SkyRenderableInstanceCloud::SetScale(const float &scale)
{
if (_pCloud)
{
_pCloud->Translate(-_vecPosition);
_pCloud->Scale(scale);
_pCloud->Translate(_vecPosition);
}
_rScale = scale;
_UpdateWorldSpaceBounds();
}
//------------------------------------------------------------------------------
// Function : DrawQuad
// Description :
//------------------------------------------------------------------------------
/**
* DrawQuad(Vec3f pos, Vec3f x, Vec3f y, Vec4f color)
* @brief Simply draws an OpenGL quad at @a pos.
*
* The quad's size and orientation are determined by the (non-unit) vectors @a x
* and @a y. Its color is given by @a color.
*/
inline void DrawQuad(Vec3f pos, Vec3f x, Vec3f y, Vec4f color)
{
glColor4fv(&(color.x));
Vec3f left = pos; left -= y;
Vec3f right = left; right += x;
left -= x;
glTexCoord2f(0, 0); glVertex3fv(&(left.x));
glTexCoord2f(1, 0); glVertex3fv(&(right.x));
left += y; left += y;
right += y; right += y;
glTexCoord2f(1, 1); glVertex3fv(&(right.x));
glTexCoord2f(0, 1); glVertex3fv(&(left.x));
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::Display
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::Display(bool bDisplayFrontOfSplit)
* @brief Display the instance of the cloud using the impostor image.
*/
SKYRESULT SkyRenderableInstanceCloud::Display(bool bDisplayFrontOfSplit /* = false */)
{
if (!_bImageExists || !_bEnabled)
{
//FAIL_RETURN(DisplayWithoutImpostor(*(GLVU::GetCurrent()->GetCurrentCam())));
FAIL_RETURN(DisplayWithoutImpostor(Camera()));
}
else
{//cout << "Using impostor image\n";
if (!_pBackTexture || (bDisplayFrontOfSplit && !_pFrontTexture)) {
// cout << "texture id failure" << endl;
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyRenderableInstanceCloud::Display(): missing texture!");
}
s_pMaterial->SetTexture(0, GL_TEXTURE_2D, bDisplayFrontOfSplit ? *_pFrontTexture : *_pBackTexture);
if (_bScreenImpostor)
{
s_pMaterial->EnableDepthTest(false);
}
else if (_bSplit)
{
if (!bDisplayFrontOfSplit)
{
s_pMaterial->EnableDepthTest(true);
s_pMaterial->SetDepthMask(false);
}
else
s_pMaterial->EnableDepthTest(false);
}
else
{
s_pMaterial->EnableDepthTest(true);
s_pMaterial->SetDepthMask(true);
}
s_pMaterial->Activate();
// s_pMaterial->Force();
Vec3f x, y, z;
if (!_bScreenImpostor)
{//cout << "Outside the cloud\n";
z = _vecPosition;
z -= _impostorCam.Orig;
z.Normalize();
x = (z ^ _impostorCam.Y);
x.Normalize();
x *= _rRadius;
y = (x ^ z);
y.Normalize();
y *= _rRadius;
glBegin(GL_QUADS);
DrawQuad(_vecPosition, x, y, Vec4f(1, 1, 1, 1));
glEnd();
}
else
{ //cout << "Drawing a polygon - must be inside a cloud\n";
x = _impostorCam.X;
x *= 0.5f * (_impostorCam.wR - _impostorCam.wL);
y = _impostorCam.Y;
y *= 0.5f * (_impostorCam.wT - _impostorCam.wB);
z = -_impostorCam.Z;
z *= _impostorCam.Near;
// draw a polygon with this texture...
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(-1, 1, -1, 1);
glColor4f(1, 1, 1, 1);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(-1, -1);
glTexCoord2f(1, 0); glVertex2f(1, -1);
glTexCoord2f(1, 1); glVertex2f(1, 1);
glTexCoord2f(0, 1); glVertex2f(-1, 1);
glEnd();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::DisplayWithoutImpostor
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::DisplayWithoutImpostor(const Camera &cam)
* @brief Displays the cloud directly -- without an impotor.
*
* This is used both when the impostor is disabled and to create the impostor image
* when it needs to be updated.
*/
SKYRESULT SkyRenderableInstanceCloud::DisplayWithoutImpostor(const Camera &cam)
{
// Get and set the world space transformation
/*Mat44f mat;
GetModelToWorldTransform(mat);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixf(mat.M);*/
FAIL_RETURN_MSG(_pCloud->Display(cam, this), "SkyRenderableInstanceCloud:Display(): Cloud's display failed.");
//glMatrixMode(GL_MODELVIEW);
//glPopMatrix();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::ViewFrustumCull
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::ViewFrustumCull(const Camera &cam)
* @brief View frustum cull the object given its world position
*/
bool SkyRenderableInstanceCloud::ViewFrustumCull(const Camera &cam)
{
Mat44f xform;
//GetModelToWorldTransform(xform);
xform.Identity();
_bCulled = (_pWorldSpaceBV == NULL) ? false : _pWorldSpaceBV->ViewFrustumCull(cam, xform);
return _bCulled;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::ReleaseImpostorTextures
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::ReleaseImpostorTextures()
* @brief Causes the instance to release its impostor textures for use by other impostors.
*
* This method is called when the cloud is view frustum culled.
*/
void SkyRenderableInstanceCloud::ReleaseImpostorTextures()
{
_iCulledCount++;
if (_iCulledCount > SKYCLOUD_CULL_RELEASE_COUNT)
{
_iCulledCount = 0;
if (_pBackTexture)
{
DynamicTextureManager::InstancePtr()->CheckInTexture(_pBackTexture);
_pBackTexture = NULL;
}
if (_pFrontTexture)
{
DynamicTextureManager::InstancePtr()->CheckInTexture(_pFrontTexture);
_pFrontTexture = NULL;
}
_bImageExists = false;
}
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::Update
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::Update(const Camera &cam)
* @brief Updates the impostor image to be valid for the current viewpoint.
*
* If the image is already valid, exits early.
*
* @see SetErrorToleranceAngle, IsValid
*/
SKYRESULT SkyRenderableInstanceCloud::Update(const Camera &cam)
{
if (!_bEnabled || IsImpostorValid(cam))
return SKYRESULT_OK;
// since we are going to update it anyway, let's make sure we don't try to use it if something
// goes wrong. This will be set to true on the successful completion of this Update() method.
_bImageExists = false;
//cout << "updating impostor\n";
Mat44f M;
_impostorCam = cam;
float rDistance = (_vecPosition - cam.Orig).Length();
float rRadius = _pWorldSpaceBV->GetRadius();
float rCamRadius = sqrt(cam.wR*cam.wR + cam.Near*cam.Near);
float rWidth = cam.wR - cam.wL;
float rHeight = cam.wT - cam.wB;
float rMaxdim = (rWidth > rHeight) ? rWidth : rHeight;
if (rRadius * cam.Near / rDistance < 0.5 * rMaxdim && (rDistance - rRadius > rCamRadius))
{ // outside cloud
_impostorCam.TightlyFitToSphere(cam.Orig, cam.Y, _vecPosition, rRadius);
_rRadius = 0.5f * (_impostorCam.wR - _impostorCam.wL) * rDistance / _impostorCam.Near;
_rRadius *= GetScale();
_bScreenImpostor = false;
// store points used in later error estimation
_vecNearPoint = -_impostorCam.Z;
_vecNearPoint *= _impostorCam.Near;
_vecNearPoint += _impostorCam.Orig;
_vecFarPoint = -_impostorCam.Z;
_vecFarPoint *= _impostorCam.Far;
_vecFarPoint += _impostorCam.Orig;
}
else // inside cloud
{
_impostorCam.Far = _impostorCam.Near + 3 * rRadius;
_bScreenImpostor = true;
}
// resolution based on screensize, distance, and object size.
// Cam radius is used to heuristically reduce resolution for clouds very close to the camera.
_iLogResolution = _GetRequiredLogResolution(rDistance, rRadius, rCamRadius);
int iRes = 1 << _iLogResolution;
int iOldVP[4];
glGetIntegerv(GL_VIEWPORT, iOldVP);
_impostorCam.GetProjectionMatrix(M);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(M);
_impostorCam.GetModelviewMatrix(M);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(M);
glViewport(0, 0, iRes, iRes);
s_pMaterial->SetDepthMask(true); // so that the depth buffer gets cleared!
s_pMaterial->Activate();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (!_bSplit)
{
FAIL_RETURN(DisplayWithoutImpostor(_impostorCam));
if (_pBackTexture && _pBackTexture->GetWidth() != iRes)
{
DynamicTextureManager::InstancePtr()->CheckInTexture(_pBackTexture);
_pBackTexture = NULL;
}
if (!_pBackTexture)
{
_pBackTexture = DynamicTextureManager::InstancePtr()->CheckOutTexture(iRes, iRes);
}
s_pMaterial->SetTexture(0, GL_TEXTURE_2D, *_pBackTexture); // shared material for clouds.
s_pMaterial->Activate();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, iRes, iRes);
}
else
{
FAIL_RETURN_MSG(_pCloud->DisplaySplit(cam, _vecSplit, true, this),
"SkyRenderableInstanceCloud:Display(): Cloud's display failed.");
if (_pBackTexture && _pBackTexture->GetWidth() != iRes)
{
DynamicTextureManager::InstancePtr()->CheckInTexture(_pBackTexture);
_pBackTexture = NULL;
}
if (_pFrontTexture && _pFrontTexture->GetWidth() != iRes)
{
DynamicTextureManager::InstancePtr()->CheckInTexture(_pFrontTexture);
_pFrontTexture = NULL;
}
if (!_pBackTexture)
{
_pBackTexture = DynamicTextureManager::InstancePtr()->CheckOutTexture(iRes, iRes);
}
s_pMaterial->SetTexture(0, GL_TEXTURE_2D, *_pBackTexture); // shared material for clouds.
FAIL_RETURN(s_pMaterial->Activate());
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, iRes, iRes);
// now clear and draw the front.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
FAIL_RETURN_MSG(_pCloud->DisplaySplit(cam, _vecSplit, false, this),
"SkyRenderableInstanceCloud:Display(): Cloud's display failed.");
if (!_pFrontTexture)
{
_pFrontTexture = DynamicTextureManager::InstancePtr()->CheckOutTexture(iRes, iRes);
}
s_pMaterial->GetTextureState().SetTexture(0, GL_TEXTURE_2D, *_pFrontTexture);
FAIL_RETURN(s_pMaterial->GetTextureState().Activate());
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, iRes, iRes);
}
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
//GLVU::CheckForGLError("Cloud Impostor Update");
glViewport(iOldVP[0], iOldVP[1], iOldVP[2], iOldVP[3]);
_bImageExists = true;
// the textures should now exist.
assert(_pBackTexture);
assert(!_bSplit || (_bSplit && _pFrontTexture));
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::IsImpostorValid
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::IsImpostorValid(const Camera& cam)
* @brief Returns true if the impostor image is valid for the given camera.
*
* Will return false if this is a screen impostor, or if there is error in either
* the translation of the camera from the capture point or the impostor image resolution.
*
* @see SetErrorToleranceAngle
*/
bool SkyRenderableInstanceCloud::IsImpostorValid(const Camera& cam)
{
// first make sure there is a current image.
if (!_bImageExists)
return false;
// screen impostors should always be updated
if (_bScreenImpostor)
{
_vecFarPoint = Vec3f::ZERO;
_vecNearPoint = Vec3f::ZERO;
#if SKYCLOUD_VERBOSE
SkyTrace("Screen Impostor Update");
#endif
return false;
}
// impostors are valid from the viewpoint from which they were captured
if (cam.Orig == _impostorCam.Orig)
return true;
if (_bSplit)
{
#if SKYCLOUD_VERBOSE
SkyTrace("Split Impostor Update");
#endif
return false;
}
Vec3f vecX = _vecNearPoint - cam.Orig;
Vec3f vecY = _vecFarPoint - cam.Orig;
float rXLength = vecX.Length();
float rYLength = vecY.Length();
if (rXLength > rYLength)
{
#if SKYCLOUD_VERBOSE
SkyTrace("Backwards Impostor Update");
#endif
return false;
}
vecX /= rXLength;
vecY /= rYLength;
float rCosAlpha = vecX * vecY; // dot product of normalized vectors = cosine
if (fabs(rCosAlpha) < 1.0)
{
float rAlpha = acos(rCosAlpha);
if (rAlpha >= s_rErrorToleranceAngle)
{
#if SKYCLOUD_VERBOSE
SkyTrace("Angle Error Update %f", SKYRADSTODEGREES * rAlpha);
#endif
return false;
}
}
float rDistance = (_vecPosition - cam.Orig).Length();
float rCamRadius = sqrt(cam.wR*cam.wR + cam.Near*cam.Near);
int iRes = _GetRequiredLogResolution(rDistance, _pWorldSpaceBV->GetRadius(), rCamRadius);
if (iRes > _iLogResolution)
{
#if SKYCLOUD_VERBOSE
SkyTrace("Resolution Error Update: Required: %d Actual: %d", iRes, _iLogResolution);
#endif
return false;
}
return true;
}
//------------------------------------------------------------------------------
// Function : SetErrorToleranceAngle
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::SetErrorToleranceAngle(float rDegrees)
* @brief Set the global error tolerance angle for all impostors.
*/
void SkyRenderableInstanceCloud::SetErrorToleranceAngle(float rDegrees)
{
s_rErrorToleranceAngle = SKYDEGREESTORADS * rDegrees;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceCloud::_Initialize
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceCloud::_Initialize()
* @brief Initializer used by the constructors.
*/
void SkyRenderableInstanceCloud::_Initialize()
{
_UpdateWorldSpaceBounds();
// if (!s_pRenderBuffer && _bUseOffScreenBuffer)
// {
//JW?? s_pRenderBuffer = new SkyOffScreenBuffer(GLUT_SINGLE | GLUT_DEPTH | GLUT_STENCIL);
//JW?? s_pRenderBuffer->Initialize(true);
//JW?? s_pRenderBuffer->MakeCurrent();
// set some GL state:
// glClearColor(0, 0, 0, 0);
//JW?? GLVU::GetCurrent()->MakeCurrent();
// }
if (!s_pMaterial)
{
s_pMaterial = new SkyMaterial;
s_pMaterial->EnableBlending(true);
s_pMaterial->SetBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
s_pMaterial->SetAlphaFunc(GL_GREATER);
s_pMaterial->EnableDepthTest(false);
s_pMaterial->SetDepthMask(true);
s_pMaterial->EnableAlphaTest(true);
s_pMaterial->EnableLighting(false);
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
s_pMaterial->SetTextureParameter(0, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
s_pMaterial->EnableTexture(0, true);
}
s_iCount++;
}

View File

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

View File

@@ -0,0 +1,76 @@
//------------------------------------------------------------------------------
// File : SkyRenderableInstanceGeneric.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyRenderableInstanceGeneric.hpp
*
* Interface for a basic implementation of SkyRenderableInstance
*/
#ifndef __SKYRENDERABLEINSTANCEGENERIC_HPP__
#define __SKYRENDERABLEINSTANCEGENERIC_HPP__
#include "SkyRenderableInstance.hpp"
// forward to reduce unnecessary dependencies
class SkyRenderable;
class SkyMinMaxBox;
//------------------------------------------------------------------------------
/**
* @class SkyRenderableInstanceGeneric
* @brief A generic renderable instance
*
* The SkyRenderableInstanceGeneric is a basic implementation of the base class.
* For view frustum culling, the function ViewFrustumCull should be called once
* per frame, at which point a flag is set if the object is culled or not. It
* is possible that the object is then queried multiple times if it is culled or
* not by various other objects before being displayed, that is why the flag is
* stored.
*/
class SkyRenderableInstanceGeneric : public SkyRenderableInstance
{
public:
SkyRenderableInstanceGeneric(SkyRenderable *pObject);
SkyRenderableInstanceGeneric(SkyRenderable *pObject,
const Vec3f &position,
const Mat33f &rotation,
const float scale);
virtual ~SkyRenderableInstanceGeneric();
// Setters / Getters
virtual void SetRenderable(SkyRenderable *pRenderable );
//! Returns a pointer to the renderable that this instance represents.
virtual SkyRenderable* GetRenderable() const { return _pObj; }
virtual SKYRESULT Display();
// Test / Set / Get
virtual bool ViewFrustumCull( const Camera &cam );
virtual SkyMinMaxBox* GetBoundingVolume() const { return _pBV; }
protected:
protected:
SkyRenderable *_pObj; // Pointer to the renderable object
SkyMinMaxBox *_pBV; // Pointer to bounding volume
};
#endif //__SKYRENDERABLEINSTANCEGENERIC_HPP__

View File

@@ -0,0 +1,178 @@
//------------------------------------------------------------------------------
// File : SkyRenderableInstanceGroup.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyRenderableInstanceGroup.cpp
*
* Implementation of class SkyRenderableInstanceGroup, an instance that groups
* other instances.
*/
#include <GL/glut.h>
#include "SkyRenderableInstanceGroup.hpp"
#include "SkySceneManager.hpp"
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceGroup::SkyRenderableInstanceGroup
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceGroup::SkyRenderableInstanceGroup()
* @brief Constructor.
*/
SkyRenderableInstanceGroup::SkyRenderableInstanceGroup()
: SkyRenderableInstance(),
_pObjectSpaceBV(NULL)
{
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup()
* @brief Destructor.
*/
SkyRenderableInstanceGroup::~SkyRenderableInstanceGroup()
{
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceGroup::Update
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceGroup::Update(const Camera &cam)
* @brief Processes any per frame updates the instance requires.
*
* This method simply calls the SkyRenderableInstance::Update() method of each of
* its sub-instances.
*/
SKYRESULT SkyRenderableInstanceGroup::Update(const Camera &cam)
{
InstanceIterator ii;
for (ii = _opaqueSubInstances.begin(); ii != _opaqueSubInstances.end(); ++ii)
{
FAIL_RETURN((*ii)->Update(cam));
}
for (ii = _transparentSubInstances.begin(); ii != _transparentSubInstances.end(); ++ii)
{
FAIL_RETURN((*ii)->Update(cam));
}
SkySceneManager::SortInstances(_transparentSubInstances, cam.Orig);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceGroup::Display
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceGroup::Display()
* @brief Displays all sub-instances of this instance.
*
* The object-to-world transform of this instance group will be applied to all sub-instances before
* their own object-to-world transforms are applied.
*/
SKYRESULT SkyRenderableInstanceGroup::Display()
{
// Get and set the world space transformation
Mat44f mat;
GetModelToWorldTransform(mat);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixf(mat.M);
InstanceIterator ii;
/***
for (ii = _opaqueSubInstances.begin(); ii != _opaqueSubInstances.end(); ++ii)
{
FAIL_RETURN((*ii)->Display());
}
for (ii = _transparentSubInstances.begin(); ii != _transparentSubInstances.end(); ++ii)
{
FAIL_RETURN((*ii)->Display());
}
***/
_pObjectSpaceBV->Display();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceGroup::ViewFrustumCull
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceGroup::ViewFrustumCull(const Camera& cam)
* @brief @todo <WRITE BRIEF SkyRenderableInstanceGroup::ViewFrustumCull DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyRenderableInstanceGroup::ViewFrustumCull FUNCTION DOCUMENTATION>
*/
bool SkyRenderableInstanceGroup::ViewFrustumCull(const Camera& cam)
{
Mat44f xform;
GetModelToWorldTransform(xform);
_bCulled = (_pObjectSpaceBV == NULL) ? false : _pObjectSpaceBV->ViewFrustumCull(cam, xform);
return _bCulled;
}
//------------------------------------------------------------------------------
// Function : SkyRenderableInstanceGroup::AddSubInstance
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyRenderableInstanceGroup::AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent)
* @brief Adds a sub-instance to the group.
*/
void SkyRenderableInstanceGroup::AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent)
{
if (!bTransparent)
_opaqueSubInstances.push_back(pInstance);
else
_transparentSubInstances.push_back(pInstance);
// update the bounds...
Mat44f xform;
pInstance->GetModelToWorldTransform(xform);
SkyMinMaxBox *pBV = pInstance->GetBoundingVolume();
if (pBV)
{
Vec3f min = pInstance->GetBoundingVolume()->GetMin();
Vec3f max = pInstance->GetBoundingVolume()->GetMax();
if (!_pObjectSpaceBV)
_pObjectSpaceBV = new SkyMinMaxBox;
_pObjectSpaceBV->AddPoint(xform * min);
_pObjectSpaceBV->AddPoint(xform * max);
}
}

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// File : SkyRenderableInstanceGroup.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyRenderableInstanceGroup.hpp
*
* Interface definition for class SkyRenderableInstanceGroup, an instance that groups
* other instances.
*/
#ifndef __SKYRENDERABLEINSTANCEGROUP_HPP__
#define __SKYRENDERABLEINSTANCEGROUP_HPP__
#include "SkyRenderableInstance.hpp"
#include "SkyMinMaxBox.hpp"
//------------------------------------------------------------------------------
/**
* @class SkyRenderableInstanceGroup
* @brief A renderable instance that groups other instances.
*
* This class provides a very basic way to implement static hierarchies of objects.
* It is not meant to be a full scene graph --
*/
class SkyRenderableInstanceGroup : public SkyRenderableInstance
{
public:
SkyRenderableInstanceGroup();
virtual ~SkyRenderableInstanceGroup();
//! Update all sub-instances.
virtual SKYRESULT Update(const Camera &cam);
//! Render all sub-instances.
virtual SKYRESULT Display();
//! Returns true if and only if the bounding volume of this instance lies entirely outside @a cam.
virtual bool ViewFrustumCull(const Camera &cam);
//! Adds an instance to the group that this instance represents.
void AddSubInstance(SkyRenderableInstance *pInstance, bool bTransparent);
protected:
InstanceArray _opaqueSubInstances;
InstanceArray _transparentSubInstances;
SkyMinMaxBox *_pObjectSpaceBV; // Pointer to bounding volume in object space
};
#endif //__SKYRENDERABLEINSTANCEGROUP_HPP__

View File

@@ -0,0 +1,250 @@
//------------------------------------------------------------------------------
// File : SkySceneLoader.cpp
//------------------------------------------------------------------------------
// Adapted from SkyWorks for FlightGear by J. Wojnaroski -- castle@mminternet.com
// Copywrite July 2002
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/**
* @file SkySceneLoader.cpp
*
* Implementation of class SkySceneLoader.
*/
#include <plib/ssg.h>
#include <plib/sg.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/math/point3d.hxx>
#include <simgear/math/polar3d.hxx>
#include <simgear/math/vector.hxx>
#include "SkySceneLoader.hpp"
#include "SkySceneManager.hpp"
#include "SkyTextureManager.hpp"
#include "SkySceneManager.hpp"
#include "SkyDynamicTextureManager.hpp"
#include "SkyContext.hpp"
#include "SkyLight.hpp"
#include "camera.hpp"
ssgLight _sky_ssgLights [ 8 ] ;
sgdVec3 cam_pos;
static sgdVec3 delta;
Point3D origin;
Camera *pCam = new Camera();
// Need to add a light here until we figure out how to use the sun position and color
SkyLight::SkyLightType eType = SkyLight::SKY_LIGHT_DIRECTIONAL;
SkyLight *pLight = new SkyLight(eType);
// hack
sgMat4 my_copy_of_ssgOpenGLAxisSwapMatrix =
{
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f }
};
//------------------------------------------------------------------------------
// Function : SkySceneLoader::SkySceneLoader
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneLoader::SkySceneLoader()
* @brief Constructor.
*/
SkySceneLoader::SkySceneLoader()
{
}
//------------------------------------------------------------------------------
// Function : SkySceneLoader::~SkySceneLoader
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneLoader::~SkySceneLoader()
* @brief Destructor.
*/
SkySceneLoader::~SkySceneLoader()
{
SceneManager::Destroy();
DynamicTextureManager::Destroy();
TextureManager::Destroy();
GraphicsContext::Destroy();
}
//------------------------------------------------------------------------------
// Function : SkySceneLoader::Load
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneLoader::Load(std::string filename)
* @brief Loads a SkyWorks scene.
*
* This is a temporary fix, as it loads only limited scenes
* It can however, load any number of Cloud
+
*/
//bool SkySceneLoader::Load(std::string filepath)
bool SkySceneLoader::Load( SGPath filename, double latitude, double longitude )
{
SkyArchive archive;
SGPath base = filename.dir();
if (SKYFAILED(archive.Load(filename.c_str()))) {
cout << "Archive file not found\n" << filename.c_str();
return false;
}
char *pFilename;
// Need to create the managers
cout << "GraphicsContext::Instantiate();" << endl;
GraphicsContext::Instantiate();
cout << " TextureManager::Instantiate();" << endl;
TextureManager::Instantiate();
cout << " DynamicTextureManager::Instantiate();" << endl;
DynamicTextureManager::Instantiate();
cout << " SceneManager::Instantiate();" << endl;
SceneManager::Instantiate();
unsigned int iNumFiles;
if (!SKYFAILED(archive.GetInfo("CloudFile", STRING_TYPE, &iNumFiles)))
{
for (unsigned int i = 0; i < iNumFiles; ++i)
{
FAIL_RETURN(archive.FindString("CloudFile", &pFilename, i));
// this is where we have to append the $fg_root string to the filename
base.append( pFilename );
const char *FilePath = base.c_str();
//float rScale = 1.0;
//FAIL_RETURN(archive.FindFloat32("CloudScale", &rScale, i));
float rScale = 40.0;
SkyArchive cloudArchive;
FAIL_RETURN(cloudArchive.Load(FilePath));
FAIL_RETURN(SceneManager::InstancePtr()->LoadClouds(cloudArchive, rScale, latitude, longitude));
}
}
Vec3f dir(0, 0, 1);
pLight->SetPosition(Vec3f(0, 0, 17000));
pLight->SetDirection(dir);
pLight->SetAmbient(Vec4f( 0.0f, 0.0f, 0.0f, 0.0f));
pLight->SetDiffuse(Vec4f(1.0f, 1.0f, 1.0f, 0.0f));
//pLight->SetDiffuse(Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
//pLight->SetSpecular(Vec4f(1.0f, 1.0f, 1.0f, 0.0f));
// No attenuation
pLight->SetAttenuation(1.0f, 0.0f, 0.0f);
SceneManager::InstancePtr()->AddLight(pLight);
SceneManager::InstancePtr()->ShadeClouds();
return true;
}
void SkySceneLoader::Set_Cloud_Orig( Point3D *posit )
{
// set origin for cloud coordinates to initial tile center
origin = *posit;
sgdSetVec3( delta, origin[0], origin[1], origin[2]);
//printf("Cloud marker %f %f %f\n", origin[0], origin[1], origin[2] );
}
void SkySceneLoader::Update( double *view_pos )
{
double wind_x, wind_y, wind_z;
wind_x = 0.0; wind_z = 0.0;
// just a dumb test to see what happens if we can move the clouds en masse via the camera
delta[0] += wind_x; delta[2] += wind_z;
sgdSubVec3( cam_pos, view_pos, delta );
//cout << "ORIGIN: " << delta[0] << " " << delta[1] << " " << delta[2] << endl;
//cout << "CAM : " << cam_pos[0] << " " << cam_pos[1] << " " << cam_pos[2] << endl;
SceneManager::InstancePtr()->Update(*pCam);
// need some scheme to reshade selected clouds a few at a time to save frame rate cycles
// SceneManager::InstancePtr()->ShadeClouds();
}
void SkySceneLoader::Resize( double w, double h )
{
pCam->Perspective( (float) h, (float) (w / h), 0.5, 120000.0 );
}
void SkySceneLoader::Draw( sgMat4 mat )
{/* need this if you want to look at FG matrix
if ( _ssgCurrentContext == NULL )
{
cout<< "ssg: No Current Context: Did you forgot to call ssgInit()?" ; char x; cin >> x;
}
ssgForceBasicState () ;
*/
sgMat4 test, m, *pm, viewmat, cameraMatrix;
pm = &m;
sgSetVec4(mat[3], cam_pos[0], cam_pos[1], cam_pos[2], SG_ONE);
// at this point the view matrix has the cloud camera position relative to cloud origin
// now transform to screen coordinates
sgTransposeNegateMat4 ( viewmat, mat ) ;
sgCopyMat4 ( cameraMatrix, my_copy_of_ssgOpenGLAxisSwapMatrix ) ;
sgPreMultMat4 ( cameraMatrix, viewmat ) ;
//sgCopyMat4 ( test, cameraMatrix );
//printf( "\nSkyworks ViewModel matrix\n" );
//cout << test[0][0] << " " << test[1][0] << " " << test[2][0] << " " << test[3][0] << endl;
//cout << test[0][1] << " " << test[1][1] << " " << test[2][1] << " " << test[3][1] << endl;
//cout << test[0][2] << " " << test[1][2] << " " << test[2][2] << " " << test[3][2] << endl;
//cout << test[0][3] << " " << test[1][3] << " " << test[2][3] << " " << test[3][3] << endl;
// this is the cameraview matrix used by flightgear to render scene
//_ssgCurrentContext->getModelviewMatrix( m );
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity () ;
glLoadMatrixf( (float *) cameraMatrix );
//sgCopyMat4( test, m );
pCam->SetModelviewMatrix( (float *) cameraMatrix );
//printf( "\nFG modelview matrix\n" );
//cout << test[0][0] << " " << test[1][0] << " " << test[2][0] << " " << test[3][0] << endl;
//cout << test[0][1] << " " << test[1][1] << " " << test[2][1] << " " << test[3][1] << endl;
//cout << test[0][2] << " " << test[1][2] << " " << test[2][2] << " " << test[3][2] << endl;
//cout << test[0][3] << " " << test[1][3] << " " << test[2][3] << " " << test[3][3] << endl;
SceneManager::InstancePtr()->Display(*pCam);
//pLight->Display(); // draw the light position to debug with sun position
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity () ;
}

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// File : SkySceneLoader.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkySceneLoader.hpp
*
* Definition of a simple class for loading scenes into SkyWorks.
*/
#ifndef __SKYSCENELOADER_HPP__
#define __SKYSCENELOADER_HPP__
#ifdef HAVE_CONFIG
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/math/point3d.hxx>
#include "SkyUtil.hpp"
//------------------------------------------------------------------------------
/**
* @class SkySceneLoader
* @brief A simple scene loader for SkyWorks scenes.
*
* Loads a scene using the Load() method, which is passed the filename of a
* file containing a SkyArchive describing the scene.
*/
class SkySceneLoader
{
public:
SkySceneLoader();
~SkySceneLoader();
bool Load( SGPath fileroot, double latitude, double longitude );
void Set_Cloud_Orig( Point3D *posit );
void Update( double *view_pos );
void Resize( double w, double h);
void Draw( sgMat4 mat );
};
#endif //__SKYSCENELOADER_HPP__

View File

@@ -0,0 +1,922 @@
//------------------------------------------------------------------------------
// File : SkySceneManager.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkySceneManager.cpp
*
* Implementation of the singleton class SkySceneManager, which manages objects,
* instances, scene update, visibility, culling, and rendering.
*/
// warning for truncation of template name for browse info
#pragma warning( disable : 4786)
#include "SkySceneManager.hpp"
#include "SkyMaterial.hpp"
#include "SkyLight.hpp"
#include "SkyCloud.hpp"
#include "SkyRenderable.hpp"
#include "SkyRenderableInstance.hpp"
#include "SkyRenderableInstanceCloud.hpp"
#include "camutils.hpp"
#include <algorithm>
//------------------------------------------------------------------------------
// Function : SkySceneManager::SkySceneManager
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::SkySceneManager()
* @brief Constructor
*/
SkySceneManager::SkySceneManager()
: /*_pSkyBox(NULL),
_pTerrain(NULL),*/
_bDrawLights(false),
_bDrawTree(false),
_bReshadeClouds(true)
{
_wireframeMaterial.SetColorMaterialMode(GL_DIFFUSE);
_wireframeMaterial.EnableColorMaterial(true);
_wireframeMaterial.EnableLighting(false);
// add the default material with ID -1
// this should avoid errors caused by models without materials exported from MAX
// (because flexporter gives them the ID -1).
SkyMaterial *pDefaultMaterial = new SkyMaterial;
pDefaultMaterial->SetMaterialID(-1);
AddMaterial(pDefaultMaterial);
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::~SkySceneManager
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::~SkySceneManager()
* @brief Destructor.
*
* This destructor deletes all renderables, instances (renderable instances, cloud instances,
* and otherwise), materials, and lights that were added to the scene using the Add*() functions.
* In other words, the scene manager owns all entities added to the scene. This eases cleanup
* and shutdown.
*/
SkySceneManager::~SkySceneManager()
{
ObjectIterator oi;
for (oi = _objects.begin(); oi != _objects.end(); ++oi)
SAFE_DELETE(*oi);
_objects.clear();
CloudIterator ci;
for (ci = _clouds.begin(); ci != _clouds.end(); ++ci)
SAFE_DELETE(*ci);
_clouds.clear();
InstanceIterator ii;
for (ii = _instances.begin(); ii != _instances.end(); ++ii)
SAFE_DELETE(*ii);
_instances.clear();
CloudInstanceIterator cii;
for (cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
SAFE_DELETE(*cii);
_cloudInstances.clear();
ContainerSetIterator cni;
for (cni = _containerClouds.begin(); cni != _containerClouds.end(); ++cni)
SAFE_DELETE(cni->second);
_containerClouds.clear();
MaterialIterator mi;
for (mi = _materials.begin(); mi != _materials.end(); ++mi)
SAFE_DELETE(mi->second);
_materials.clear();
LightIterator li;
for (li = _lights.begin(); li!= _lights.end(); ++li)
SAFE_DELETE(li->second);
_lights.clear();
//SAFE_DELETE(_pSkyBox);
//SAFE_DELETE(_pTerrain);
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::AddObject
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::AddObject(SkyRenderable *pObject)
* @brief Add a new SkyRenderable object to the manager.
*/
SKYRESULT SkySceneManager::AddObject(SkyRenderable *pObject)
{
// Check for null object
if (NULL == pObject)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"SkySceneManager::AddObject(): Attempting to add NULL Renderable Object.");
}
_objects.push_back(pObject);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::AddInstance
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::AddInstance(SkyRenderableInstance *pInstance, bool bTransparent)
* @brief Add a new SkyRenderableInstance to the manager.
*/
SKYRESULT SkySceneManager::AddInstance(SkyRenderableInstance *pInstance, bool bTransparent /* = false */)
{
// Check for null instance
if (NULL == pInstance)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"SkySceneManager::AddObject(): Attempting to add NULL Renderable Instance.");
}
if (!bTransparent)
_instances.push_back(pInstance);
else
_transparentInstances.push_back(pInstance);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::AddCloud
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::AddCloud(SkyCloud *pCloud)
* @brief Add a new cloud object to the manager.
*
* @todo <WRITE EXTENDED SkySceneManager::AddCloud FUNCTION DOCUMENTATION>
*/
SKYRESULT SkySceneManager::AddCloud(SkyCloud *pCloud)
{
if (NULL == pCloud)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"SkySceneManager::AddObject(): Attempting to add NULL SkyCloud Object.");
}
_clouds.push_back(pCloud);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::AddCloudInstance
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::AddCloudInstance(SkyRenderableInstanceCloud *pInstance)
* @brief Add a new instance of a cloud to the manager.
*
* @todo Note that since cloud instances share shading information, if two instances
* of a cloud have different orientations, one of the instances will have incorrect
* lighting for the scene. For this reason, I recommend that the number of clouds and
* cloud instances is equal.
*/
SKYRESULT SkySceneManager::AddCloudInstance(SkyRenderableInstanceCloud *pInstance)
{
// Check for null instance
if (NULL == pInstance)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"SkySceneManager::AddObject(): Attempting to add NULL SkyCloud Instance.");
}
pInstance->SetID(_cloudInstances.size());
_cloudInstances.push_back(pInstance);
SkyContainerCloud *pContainer = new SkyContainerCloud(pInstance);
_containerClouds.insert(std::make_pair(pInstance->GetID(), pContainer));
RebuildCloudBVTree();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::AddMaterial
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::AddMaterial(SkyMaterial *pMaterial)
* @brief Adds a material to the scene.
*
* Materials are kept in a map with their ID as key. A material can be retrieved
* from the scene manager by passing its ID to GetMaterial.
*
* @see GetMaterial, SkyMaterial
*/
SKYRESULT SkySceneManager::AddMaterial(SkyMaterial *pMaterial)
{
// Check for null instance
if (NULL == pMaterial)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"SkySceneMananger::AddMaterial(): Attempting to add NULL Material to Scene Manager");
}
_materials.insert(std::make_pair(pMaterial->GetMaterialID(), pMaterial));
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::GetMaterial
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::GetMaterial(int iMaterialID)
* @brief Returns the material with ID @a iMaterialID.
*
* If the material is not found, returns NULL.
*
* @see AddMaterial, SkyMaterial
*/
SkyMaterial* SkySceneManager::GetMaterial(int iMaterialID)
{
MaterialIterator mi = _materials.find(iMaterialID);
if (_materials.end() == mi)
{
SkyTrace("SkySceneManager::GetMaterial: Error: invalid material ID");
return NULL;
}
else
return mi->second;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::ActivateMaterial
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::ActivateMaterial(int iMaterialID)
* @brief Makes the specified material active, setting the appropriate rendering state.
*
* @todo <WRITE EXTENDED SkySceneManager::ActivateMaterial FUNCTION DOCUMENTATION>
*/
SKYRESULT SkySceneManager::ActivateMaterial(int iMaterialID)
{
// cout << "Activating material\n"; char mm; cin >> mm;
MaterialIterator mi = _materials.find(iMaterialID);
if (_materials.end() == mi)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"SkySceneManager::ActivateMaterial: Error: invalid material ID.");
}
else
{
FAIL_RETURN_MSG(mi->second->Activate(),
"SkySceneManager::ActivateMaterial: Error: failed to activate.");
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::AddLight
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::AddLight(SkyLight *pLight)
* @brief @todo <WRITE BRIEF SkySceneManager::AddLight DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::AddLight FUNCTION DOCUMENTATION>
*/
SKYRESULT SkySceneManager::AddLight(SkyLight *pLight)
{
// Check for null instance
if (NULL == pLight)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"SkySceneMananger::AddLight(): Attempting to add NULL Light to Scene Manager");
}
_lights.insert(std::make_pair(_lights.size(), pLight));
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::GetLight
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::GetLight(int iLightID)
* @brief @todo <WRITE BRIEF SkySceneManager::GetLight DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::GetLight FUNCTION DOCUMENTATION>
*/
SkyLight* SkySceneManager::GetLight(int iLightID)
{
LightIterator li = _lights.find(iLightID);
if (_lights.end() == li)
{
SkyTrace("SkySceneManager::GetLight: Error: Invalid light ID");
return NULL;
}
else
return li->second;
}
//------------------------------------------------------------------------------
// Function : Alive
// Description :
//------------------------------------------------------------------------------
/**
* @fn Alive(SkyRenderableInstance* pInstance)
* @brief A predicate to determine if an object is dead or not.
*/
bool Alive(SkyRenderableInstance* pInstance)
{
return (pInstance->IsAlive());
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::Update
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::Update(const Camera &cam)
* @brief Iterate through all SkyRenderableInstances and update them.
*/
SKYRESULT SkySceneManager::Update(const Camera &cam)
{
_ResolveVisibility(cam);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::Display
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::Display(const Camera &cam)
* @brief Iterate through all SkyRenderableInstances and display them.
*/
SKYRESULT SkySceneManager::Display( const Camera &cam )
{
// _clearMaterial.Force();
_clearMaterial.Activate();
//glClear(GL_DEPTH_BUFFER_BIT);
// set lights (only lights that have changed will be passed to GL).
for (LightIterator li = _lights.begin(); li != _lights.end(); ++li)
{
li->second->Activate(li->first);
//if (_bDrawLights)
//li->second->Display();
}
//if (_bDrawTree)// force the issue and draw
//_VisualizeCloudBVTree(cam, _cloudBVTree.GetRoot());
/*
glLineWidth(2.0);
glBegin(GL_LINES);
// red is Cartesian y-axis
glColor3ub( 255, 0, 0 );
glVertex3f( 0.0,0.0,0.0 );
glVertex3f( 0.0, -104000.0, 0.0);
// yellow is Cartesian z-axis
glColor3ub( 255, 255, 0 );
glVertex3f( 0.0, 0.0, 0.0);
glVertex3f( 0.0, 0.0, 104000.0);
// blue is Cartesian x-axis
glColor3ub( 0, 0, 255 );
glVertex3f( 0.0, 0.0, 0.0);
glVertex3f( -104000.0, 0.0, 0.0);
glEnd();
*/
// draw all container clouds and "free" objects not in clouds.
//int i = 0;
for (InstanceIterator iter = _visibleInstances.begin(); iter != _visibleInstances.end(); ++iter)
{
FAIL_RETURN_MSG((*iter)->Display(),
"SkySceneManager::Display(): instance display failed.");
//i++;
}
//cout << "There are " << i << " visible clouds\n";
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::RebuildCloudBVTree
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::RebuildCloudBVTree()
* @brief Builds an AABB tree of the cloud bounding volumes.
*/
SKYRESULT SkySceneManager::RebuildCloudBVTree()
{
CloudInstanceIterator cii;
SkyMinMaxBox bbox;
_cloudBVTree.BeginTree();
for (cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
{
bbox = (*cii)->GetWorldSpaceBounds();
_cloudBVTree.AddObject(*cii, bbox);
}
_cloudBVTree.EndTree();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::ShadeClouds
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::ShadeClouds()
* @brief @todo <WRITE BRIEF SkySceneManager::ShadeClouds DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::ShadeClouds FUNCTION DOCUMENTATION>
*/
SKYRESULT SkySceneManager::ShadeClouds()
{
// cout << "SkySceneManager::ShadeClouds()\n";
int i=0;
for (CloudInstanceIterator cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
{
for (LightIterator li = _lights.begin(); li != _lights.end(); ++li)
{
if (SkyLight::SKY_LIGHT_DIRECTIONAL == li->second->GetType())
{
(*cii)->GetCloud()->Illuminate(li->second, *cii, li == _lights.begin());
// printf("Shading Cloud %d of %d with light %d \n", i++, _cloudInstances.size(), *li );
}
}
}
_bReshadeClouds = false;
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::LoadClouds
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::LoadClouds(SkyArchive& cloudArchive, float rScale)
* @brief @todo <WRITE BRIEF SkySceneManager::LoadClouds DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::LoadClouds FUNCTION DOCUMENTATION>
*/
SKYRESULT SkySceneManager::LoadClouds(SkyArchive& cloudArchive, float rScale, double latitude, double longitude)
{
unsigned int iNumClouds = 0;
cloudArchive.FindUInt32("CldNumClouds", &iNumClouds);
SkyArchive subArchive;
//iNumClouds = 5; //set this value to reduce cloud field for debugging
for (int i = 0; i < iNumClouds; ++i)
{printf("Loading # %d of %d clouds\n", i+1, iNumClouds);
cloudArchive.FindArchive("Cloud", &subArchive, i);
SkyCloud *pCloud = new SkyCloud();
pCloud->Load(subArchive, rScale, latitude, longitude);
SkyRenderableInstanceCloud *pInstance = new SkyRenderableInstanceCloud(pCloud, false);
AddCloud(pCloud);
AddCloudInstance(pInstance);
}
RebuildCloudBVTree();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::_SortClouds
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::_SortClouds(CloudInstanceArray& clouds, const Vec3f& vecSortPoint)
* @brief @todo <WRITE BRIEF SkySceneManager::_SortClouds DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::_SortClouds FUNCTION DOCUMENTATION>
*/
void SkySceneManager::_SortClouds(CloudInstanceArray& clouds, const Vec3f& vecSortPoint)
{
static InstanceComparator comparator;
for (CloudInstanceIterator cii = clouds.begin(); cii != clouds.end(); ++cii)
{
Vec3f vecPos = (*cii)->GetPosition();
vecPos -= vecSortPoint;
(*cii)->SetSquareSortDistance(vecPos.LengthSqr());
}
std::sort(clouds.begin(), clouds.end(), comparator);
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::_SortInstances
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint)
* @brief @todo <WRITE BRIEF SkySceneManager::_SortInstances DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::_SortInstances FUNCTION DOCUMENTATION>
*/
void SkySceneManager::SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint)
{
static InstanceComparator comparator;
for (InstanceIterator ii = instances.begin(); ii != instances.end(); ++ii)
{
Vec3f vecPos = (*ii)->GetPosition();
vecPos -= vecSortPoint;
(*ii)->SetSquareSortDistance(vecPos.LengthSqr());
}
std::sort(instances.begin(), instances.end(), comparator);
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::_ViewFrustumCullClouds
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::_ViewFrustumCullClouds(const Camera& cam, const CloudBVTree::Node *pNode)
* @brief @todo <WRITE BRIEF SkySceneManager::_ViewFrustumCullClouds DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::_ViewFrustumCullClouds FUNCTION DOCUMENTATION>
*/
void SkySceneManager::_ViewFrustumCullClouds(const Camera& cam, const CloudBVTree::Node *pNode)
{
if (!pNode)
return;
int i;
int iResult = CamMinMaxBoxOverlap(&cam, pNode->GetNodeBV().GetMin(), pNode->GetNodeBV().GetMax());
//iResult = COMPLETEIN; // just a hack to force the issue
if (COMPLETEIN == iResult)
{
// trivially add all instances
for (i = 0; i < pNode->GetNumObjs(); ++i)
{
SkyRenderableInstanceCloud* pInstance =
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
_visibleCloudInstances.push_back(pInstance);
}
}
else if ((PARTIAL == iResult) && pNode->IsLeaf())
{
SkyMinMaxBox bbox;
// check each instance in this node against camera
for (i = 0; i < pNode->GetNumObjs(); ++i)
{
SkyRenderableInstanceCloud* pInstance =
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
bbox = pInstance->GetWorldSpaceBounds();
iResult = CamMinMaxBoxOverlap(&cam, bbox.GetMin(), bbox.GetMax());
if (COMPLETEOUT != iResult)
_visibleCloudInstances.push_back(pInstance);
else
pInstance->ReleaseImpostorTextures();
}
}
else if (PARTIAL == iResult)
{
_ViewFrustumCullClouds(cam, pNode->GetLeftChild());
_ViewFrustumCullClouds(cam, pNode->GetRightChild());
}
else // the node is completely out. All of its child clouds should release their textures.
{
for (i = 0; i < pNode->GetNumObjs(); ++i)
{
SkyRenderableInstanceCloud* pInstance =
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
pInstance->ReleaseImpostorTextures();
}
}
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::_VisualizeCloudBVTree
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::_VisualizeCloudBVTree(const Camera& cam, const CloudBVTree::Node *pNode)
* @brief @todo <WRITE BRIEF SkySceneManager::_VisualizeCloudBVTree DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::_VisualizeCloudBVTree FUNCTION DOCUMENTATION>
*/
void SkySceneManager::_VisualizeCloudBVTree(const Camera& cam, const CloudBVTree::Node *pNode)
{
// set display state.
_wireframeMaterial.Activate();
int iResult = CamMinMaxBoxOverlap(&cam, pNode->GetNodeBV().GetMin(), pNode->GetNodeBV().GetMax());
if (COMPLETEIN == iResult)
{
// draw this node's bounding box in green.
glColor3f(0, 1, 0);
pNode->GetNodeBV().Display();
}
else if (PARTIAL == iResult)
{
SkyMinMaxBox bbox;
if (pNode->IsLeaf())
{
// draw this node's bounding box and the boxes of all of its objects that are visible.
// draw this node's bbox in orange.
glColor3f(1, 0.5, 0);
pNode->GetNodeBV().Display();
int i;
for (i = 0; i < pNode->GetNumObjs(); ++i)
{
SkyRenderableInstanceCloud* pInstance =
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
bbox = pInstance->GetWorldSpaceBounds();
iResult = CamMinMaxBoxOverlap(&cam, bbox.GetMin(), bbox.GetMax());
if (COMPLETEIN == iResult)
{
// draw the box in green
glColor3f(0, 1, 0);
bbox.Display();
}
else if (PARTIAL == iResult)
{
// draw the box in yellow
glColor3f(1, 1, 0);
bbox.Display();
}
}
}
else
{
_VisualizeCloudBVTree(cam, pNode->GetLeftChild());
_VisualizeCloudBVTree(cam, pNode->GetRightChild());
}
}
else
{
// draw the node's bbox in red.
// This should NEVER be visible from the camera from which it was culled!
glColor3f(1, 0, 0);
pNode->GetNodeBV().Display();
}
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::_ResolveVisibility
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::_ResolveVisibility(const Camera &cam)
* @brief @todo <WRITE BRIEF SkySceneManager::_ResolveRenderingOrder DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::_ResolveRenderingOrder FUNCTION DOCUMENTATION>
*/
SKYRESULT SkySceneManager::_ResolveVisibility(const Camera &cam)
{
InstanceIterator ii;
// clear the free instance array
_visibleInstances.clear();
// clear the contained instance arrays
ContainerSetIterator csi;
for (csi = _containerClouds.begin(); csi != _containerClouds.end(); ++csi)
{
csi->second->containedOpaqueInstances.clear();
csi->second->containedTransparentInstances.clear();
}
// clear the visible cloud array.
_visibleCloudInstances.clear();
// Test each instance for containment inside a cloud's bounding volume.
// If the instance is inside a cloud, it is considered a "contained" instance, and will be
// rendered with the cloud in which it is contained for correct visibility. If the instance is
// not inside any cloud, then it is a "free" instance, and will be rendered after all contained
// instances. Transparent instances of each type are rendered after opaque instances of each
// type.
// opaque instances
for (ii = _instances.begin(); ii != _instances.end(); ++ii)
{
// cout << "Opague instance\n"; char zz; cin >> zz;
(*ii)->ViewFrustumCull(cam); // First VFC then check if culled, some instances may
// manually set the culled flag, instead of using VFC
if (!(*ii)->IsCulled())
{
// first update this instance.
FAIL_RETURN_MSG((*ii)->Update(cam), "SkySceneManager::_ResolveVisibility(): instance update failed.");
if (!_TestInsertInstanceIntoClouds(cam, _cloudBVTree.GetRoot(), *ii, false))
_visibleInstances.push_back(*ii);
}
}
// transparent instances
for (ii = _transparentInstances.begin(); ii != _transparentInstances.end(); ++ii)
{
// cout << "Transparent instance\n"; char tt; cin >> tt;
(*ii)->ViewFrustumCull(cam); // First VFC then check if culled, some instances may
// manually set the culled flag, instead of using VFC
if (!(*ii)->IsCulled())
{
// first update this instance.
FAIL_RETURN_MSG((*ii)->Update(cam), "SkySceneManager::Update(): instance update failed.");
if (!_TestInsertInstanceIntoClouds(cam, _cloudBVTree.GetRoot(), *ii, true))
_visibleInstances.push_back(*ii);
}
}
// view frustum cull the clouds
_ViewFrustumCullClouds(cam, _cloudBVTree.GetRoot());
// Clouds must be rendered in sorted order.
//_SortClouds(_visibleCloudInstances, cam.Orig);
// reshade the clouds if necessary.
if (_bReshadeClouds)
{
printf("ReShading clouds\n");
FAIL_RETURN(ShadeClouds());
}
// Now process the visible clouds. First, go through the container clouds corresponding to the
// clouds, calculate their split points, and update their impostors.
for (CloudInstanceIterator cii = _visibleCloudInstances.begin();
cii != _visibleCloudInstances.end();
++cii)
{
// get the container corresponding to this cloud
ContainerSetIterator csi = _containerClouds.find((*cii)->GetID());
if (csi == _containerClouds.end())
{
SkyTrace("Error: SkySceneManager::_ResolveVisibility(): Invalid cloud instance %d.",
(*cii)->GetID());
return SKYRESULT_FAIL;
}
if (csi->second->containedOpaqueInstances.size() > 0 ||
csi->second->containedTransparentInstances.size() > 0)
{
SortInstances(csi->second->containedOpaqueInstances, cam.Orig);
SortInstances(csi->second->containedTransparentInstances, cam.Orig);
SkyRenderableInstance *pOpaque = (csi->second->containedOpaqueInstances.size() > 0) ?
csi->second->containedOpaqueInstances.back() : NULL;
SkyRenderableInstance *pTransparent = (csi->second->containedTransparentInstances.size() > 0) ?
csi->second->containedTransparentInstances.back() : NULL;
// find the closest contained instance to the camera
if (pOpaque && pTransparent)
{
if (*pOpaque < *pTransparent)
(*cii)->SetSplitPoint(pOpaque->GetPosition());
else
(*cii)->SetSplitPoint(pTransparent->GetPosition());
}
else if (pOpaque)
(*cii)->SetSplitPoint(pOpaque->GetPosition());
else if (pTransparent)
(*cii)->SetSplitPoint(pTransparent->GetPosition());
else
(*cii)->SetSplit(false);
}
else
(*cii)->SetSplit(false);
// add the container to the list of visiblie clouds to be rendered this frame.
_visibleInstances.push_back(csi->second);
// now update the impostors
FAIL_RETURN_MSG((*cii)->Update(cam),
"SkySceneManager::_ResolveVisibility(): cloud instance update failed.");
}
SortInstances(_visibleInstances, cam.Orig);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkySceneManager::_TestInsertInstanceIntoClouds
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySceneManager::_TestInsertInstanceIntoClouds(const Camera &cam, const CloudBVTree::Node *pNode, SkyRenderableInstance *pInstanceToInsert, bool bTransparent)
* @brief @todo <WRITE BRIEF SkySceneManager::_TestInsertInstanceIntoClouds DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkySceneManager::_TestInsertInstanceIntoClouds FUNCTION DOCUMENTATION>
*/
bool SkySceneManager::_TestInsertInstanceIntoClouds(const Camera &cam,
const CloudBVTree::Node *pNode,
SkyRenderableInstance *pInstanceToInsert,
bool bTransparent)
{
if (_clouds.size() <= 0)
return false;
if (pNode->GetNodeBV().PointInBBox(pInstanceToInsert->GetPosition()))
{
if (pNode->IsLeaf())
{
SkyMinMaxBox bbox;
int i;
// check the instance against each cloud in this leaf node.
for (i = 0; i < pNode->GetNumObjs(); ++i)
{
SkyRenderableInstanceCloud* pCloud =
const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
bbox = pCloud->GetWorldSpaceBounds();
if (bbox.PointInBBox(pInstanceToInsert->GetPosition()))
{
// get the container cloud struct for this cloud instance, and add this instance.
ContainerSetIterator csi = _containerClouds.find(pCloud->GetID());
if (csi == _containerClouds.end())
{
SkyTrace(
"Error: SkySceneManager::_TestInsertInstanceIntoClouds(): Invalid cloud instance %d.",
pCloud->GetID());
return false;
}
else // this instance is inside a cloud. Set up for split cloud rendering.
{
if (!bTransparent)
csi->second->containedOpaqueInstances.push_back(pInstanceToInsert);
else
csi->second->containedTransparentInstances.push_back(pInstanceToInsert);
csi->second->pCloud->SetSplit(true);
return true;
}
}
}
return false;
}
else
{
if (!_TestInsertInstanceIntoClouds(cam, pNode->GetLeftChild(), pInstanceToInsert, bTransparent))
return _TestInsertInstanceIntoClouds(cam, pNode->GetRightChild(), pInstanceToInsert, bTransparent);
else
return true;
}
}
else
return false;
}

View File

@@ -0,0 +1,188 @@
//------------------------------------------------------------------------------
// File : SkySceneManager.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkySceneManager.hpp
*
* The SkySceneManager class manages all of the renderable objects and
* instances. This class maintains lists of each object and instance.
* The scene manager decides what to display, it can make use of various
* techniques such as view frustum culling, material grouping, etc.
*/
#ifndef __SKYSCENEMANAGER_HPP__
#define __SKYSCENEMANAGER_HPP__
// warning for truncation of template name for browse info
#pragma warning( disable : 4786)
#include "vec3f.hpp"
#include <vector>
#include <map>
#include "SkyUtil.hpp"
#include "SkySingleton.hpp"
#include "SkyRenderableInstance.hpp"
#include "SkyMaterial.hpp"
#include "SkyAABBTree.hpp"
#include "SkyRenderableInstanceCloud.hpp"
// forward to reduce unnecessary dependencies
class Camera;
class SkyRenderable;
class SkyRenderableInstance;
class SkyMaterial;
class SkyLight;
class SkyCloud;
//class SkyHeavens;
//class SkyHeightField;
//------------------------------------------------------------------------------
/**
* @class SkySceneManager
* @brief Manages all of the renderable objects and instances.
*/
class SkySceneManager; // Forward declaration
//! A singleton of the SkySceneManager. Can only create the SceneManager with SceneManager::Instantiate();
typedef SkySingleton<SkySceneManager> SceneManager;
class SkySceneManager
{
public:
SKYRESULT AddObject( SkyRenderable *pObject);
SKYRESULT AddInstance( SkyRenderableInstance *pInstance, bool bTransparent = false);
SKYRESULT AddCloud( SkyCloud *pCloud);
SKYRESULT AddCloudInstance(SkyRenderableInstanceCloud *pInstance);
SKYRESULT AddMaterial( SkyMaterial *pMaterial);
SkyMaterial* GetMaterial( int iMaterialID);
SKYRESULT ActivateMaterial(int iMaterialID);
SKYRESULT AddLight( SkyLight *pLight);
SkyLight* GetLight( int iLightID);
//! Set the sky box for this scene.
// void SetSkyBox( SkyHeavens *pSkyBox) { _pSkyBox = pSkyBox; }
//! Set the terrain for this scene.
//void SetTerrain( SkyHeightField *pTerrain) { _pTerrain = pTerrain; }
//! Enable wireframe display of lights (for debugging).
void EnableDrawLights(bool bEnable) { _bDrawLights = bEnable; }
//! Enable wireframe display of bounding volume tree of clouds.
void EnableDrawBVTree(bool bEnable) { _bDrawTree = bEnable; }
//! Returns true if wireframe display of lights is enabled.
bool IsDrawLightsEnabled() const { return _bDrawLights; }
//! Returns true if wireframe display of the cloud bounding volume tree is enabled.
bool IsDrawBVTreeEnabled() const { return _bDrawTree; }
SKYRESULT Update( const Camera &cam);
SKYRESULT Display( const Camera &cam);
SKYRESULT RebuildCloudBVTree();
SKYRESULT ShadeClouds();
//! Force the illumination of all clouds to be recomputed in the next update.
void ForceReshadeClouds() { _bReshadeClouds = true; }
// sort instances in @a instances from back to front.
static void SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint);
// load a set of clouds from an archive file.
SKYRESULT LoadClouds(SkyArchive& cloudArchive, float rScale = 1.0f, double latitude=0.0, double longitude=0.0);
protected: // datatypes
// Typedef the vectors into cleaner names
typedef std::vector<SkyRenderable*> ObjectArray;
typedef std::map<int, SkyMaterial*> MaterialSet;
typedef std::map<int, SkyLight*> LightSet;
typedef std::vector<SkyRenderableInstanceCloud*> CloudInstanceArray;
typedef std::vector<SkyCloud*> CloudArray;
typedef std::map<int, SkyContainerCloud*> ContainerCloudSet;
typedef SkyAABBTree<SkyRenderableInstanceCloud*> CloudBVTree;
typedef ObjectArray::iterator ObjectIterator;
typedef CloudArray::iterator CloudIterator;
typedef CloudInstanceArray::iterator CloudInstanceIterator;
typedef MaterialSet::iterator MaterialIterator;
typedef LightSet::iterator LightIterator;
typedef ContainerCloudSet::iterator ContainerSetIterator;
class InstanceComparator
{
public:
bool operator()(SkyRenderableInstance* pA, SkyRenderableInstance *pB)
{
return ((*pA) < (*pB));
}
};
class ContainerComparator
{
public:
bool operator()(SkyContainerCloud* pA, SkyContainerCloud *pB)
{
return ((*pA) < (*pB));
}
};
protected: // methods
SkySceneManager();
~SkySceneManager();
void _SortClouds(CloudInstanceArray& clouds, const Vec3f& vecSortPoint);
void _ViewFrustumCullClouds(const Camera& cam, const CloudBVTree::Node *pNode);
void _VisualizeCloudBVTree(const Camera& cam, const CloudBVTree::Node *pNode);
SKYRESULT _ResolveVisibility(const Camera &cam);
bool _TestInsertInstanceIntoClouds(const Camera &cam,
const CloudBVTree::Node *pNode,
SkyRenderableInstance *pInstanceToInsert,
bool bTransparent);
private: // data
ObjectArray _objects;
CloudArray _clouds;
InstanceArray _instances;
InstanceArray _transparentInstances;
InstanceArray _visibleInstances; //! @TODO: change this to "_freeInstances"
CloudInstanceArray _cloudInstances;
CloudInstanceArray _visibleCloudInstances;
ContainerCloudSet _containerClouds;
MaterialSet _materials;
LightSet _lights;
SkyMaterial _wireframeMaterial; // used for rendering the wireframes for debugging
SkyMaterial _clearMaterial; // used to maintain state consistency when clearing.
CloudBVTree _cloudBVTree;
//SkyHeavens *_pSkyBox;
//SkyHeightField *_pTerrain;
bool _bDrawLights;
bool _bDrawTree;
bool _bReshadeClouds;
};
#endif //__SKYSCENEMANAGER_HPP__

View File

@@ -0,0 +1,292 @@
//------------------------------------------------------------------------------
// File : SkySingleton.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkySingleton.hpp
*
* A generic singleton template wrapper to make classes into singletons
*/
#ifndef __SKYSINGLETON_HPP__
#define __SKYSINGLETON_HPP__
#include "SkyUtil.hpp"
#include <assert.h>
#include <stdlib.h>
//------------------------------------------------------------------------------
/**
* @class SkySingleton
* @brief A singleton template class.
*
* Usage : Use this template container class to make any class into a
* singleton. I usually do this:
*
* @code
* class MyClass
* {
* public:
* // normal class stuff, but don't put ctor/dtor here.
* int GetData() { return _someData; }
* protected:
* // Make the ctor(s)/dtor protected, so this can only be
* // instantiated as a singleton. Note: singleton will still
* // work on classes that do not follow this (public ctors)
* // but violation of the singleton is possible then, since non-
* // singleton versions of the class can be instantiated.
* MyClass() : _someData(5) {}
* MyClass(int arg) : _someData(arg) {} // etc...
* // don't implement the copy constructor, because singletons
* // shouldn't be copied!
* MyClass(const MyClass& mc) {}
* ~MyClass() {}
* private:
* int _someData;
* };
*
* // now create a singleton of MyClass
* typedef SkySingleton<MyClass> MyClassSingleton;
*
* @endcode
* Later, in your program code, you can instantiate the singleton and access
* its members like so:
*
* @code
* void somefunc()
* {
* // instantiate the MyClassSingleton
* MyClassSingleton::Instantiate();
* // could also call MyClassSingleton::Instantiate(10);
* // since we have a constructor of that form in MyClass.
*
* // access the methods in MyClass:
* int data1 = MyClassSingleton::InstancePtr()->GetData();
* // or...
* int data2 = MyClassSingleton::InstanceRef().GetData();
*
* // now destroy the singleton
* MyClassSingleton::Destroy();
* }
* @endcode
*/
template <class T>
class SkySingleton : protected T
{
public:
//------------------------------------------------------------------------------
// Function : Instantiate
// Description :
//------------------------------------------------------------------------------
/**
* @fn Instantiate()
* @brief Creates the singleton instance for class T.
*
* Assures (by assertion) that the instance will only be created once.
* This works for default constructors.
*/
static void Instantiate()
{
assert(!s_pInstance);
s_pInstance = new SkySingleton();
}
//------------------------------------------------------------------------------
// Function : Destroy
// Description :
//------------------------------------------------------------------------------
/**
* @fn Destroy() { SAFE_DELETE(s_pInstance); }
* @brief Destructor, deletes the instance
*/
static void Destroy() { SAFE_DELETE(s_pInstance); }
//------------------------------------------------------------------------------
// Function : InstancePtr
// Description :
//------------------------------------------------------------------------------
/**
* @fn InstancePtr() { assert(s_pInstance); return s_pInstance; }
* @brief Returns a pointer to the instance
*/
static T* InstancePtr() { assert(s_pInstance); return s_pInstance; }
//------------------------------------------------------------------------------
// Function : InstanceRef
// Description :
//------------------------------------------------------------------------------
/**
* @fn InstanceRef() { assert(s_pInstance); return *s_pInstance; }
* @brief Returns a reference to the instance
*/
static T& InstanceRef() { assert(s_pInstance); return *s_pInstance; }
//------------------------------------------------------------------------------
// Function : static void Instantiate
// Description :
//------------------------------------------------------------------------------
/**
* @fn static void Instantiate(const A& a)
* @brief Instantiates class of type T that have constructors with an argument
*
* This might be a source of confusion. These templatized
* functions are used to instantiate classes of type T that
* have constructors with arguments. For n arguments, you
* to add a function below with n arguments. Note, these will
* only be created if they are used, since they are templates.
* I've added 4 below, for 1-4 arguments. If you get a
* compilation error, add one for the number of arguments you
* need. Also need a SkySingleton protected constructor with
* the same number of arguments.
*/
template<class A>
static void Instantiate(const A& a)
{
assert(!s_pInstance);
s_pInstance = new SkySingleton(a);
}
//------------------------------------------------------------------------------
// Function : Instantiate
// Description :
//------------------------------------------------------------------------------
/**
* @fn Instantiate(const A& a, const B& b)
* @brief Instantiates class of type T that have constructors with 2 args
*/
template<class A, class B>
static void Instantiate(const A& a, const B& b)
{
assert(!s_pInstance);
s_pInstance = new SkySingleton(a, b);
}
//------------------------------------------------------------------------------
// Function : Instantiate
// Description :
//------------------------------------------------------------------------------
/**
* @fn Instantiate(const A& a, const B& b, const C& c)
* @brief Instantiates class of type T that have constructors with 3 args
*/
template<class A, class B, class C>
static void Instantiate(const A& a, const B& b, const C& c)
{
assert(!s_pInstance);
s_pInstance = new SkySingleton(a, b, c);
}
//------------------------------------------------------------------------------
// Function : Instantiate
// Description :
//------------------------------------------------------------------------------
/**
* @fn Instantiate(const A& a, const B& b, const C& c, const D& d)
* @brief Instantiates class of type T that have constructors with 4 args
*/
template<class A, class B, class C, class D>
static void Instantiate(const A& a, const B& b, const C& c, const D& d)
{
assert(!s_pInstance);
s_pInstance = new SkySingleton(a, b, c, d);
}
protected:
// although the instance is of type SkySingleton<T>, the Instance***() funcs
// above implicitly cast it to type T.
static SkySingleton* s_pInstance;
private:
//------------------------------------------------------------------------------
// Function : SkySingleton
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySingleton()
* @brief Hidden so that the singleton can only be instantiated via public static Instantiate function.
*/
SkySingleton() : T() {}
//------------------------------------------------------------------------------
// Function : Singleton
// Description :
//------------------------------------------------------------------------------
/**
* @fn Singleton(const A& a)
* @brief Used by the templatized public Instantiate() functions.
*/
template<class A>
SkySingleton(const A& a) : T(a) {}
//------------------------------------------------------------------------------
// Function : Singleton
// Description :
//------------------------------------------------------------------------------
/**
* @fn Singleton(const A& a, const B& b)
* @brief Used by the templatized public Instantiate() functions.
*/
template<class A, class B>
SkySingleton(const A& a, const B& b) : T(a, b) {}
//------------------------------------------------------------------------------
// Function : Singleton
// Description :
//------------------------------------------------------------------------------
/**
* @fn Singleton(const A& a, const B& b, const C& c)
* @brief Used by the templatized public Instantiate() functions.
*/
template<class A, class B, class C>
SkySingleton(const A& a, const B& b, const C& c) : T(a, b, c) {}
//------------------------------------------------------------------------------
// Function : Singleton
// Description :
//------------------------------------------------------------------------------
/**
* @fn Singleton(const A& a, const B& b, const C &c, const D& d)
* @brief Used by the templatized public Instantiate() functions.
*/
template<class A, class B, class C, class D>
SkySingleton(const A& a, const B& b, const C &c, const D& d) : T(a, b, c, d) {}
//------------------------------------------------------------------------------
// Function : SkySingleton
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkySingleton(const SkySingleton&)
* @brief Hidden because you can't copy a singleton!
*/
SkySingleton(const SkySingleton&) {} // hide the copy ctor: singletons can'
//------------------------------------------------------------------------------
// Function : ~SkySingleton
// Description :
//------------------------------------------------------------------------------
/**
* @fn ~SkySingleton()
* @brief Destructor, hidden, destroy via the public static Destroy() method.
*/
~SkySingleton() {} // hide the dtor:
};
// declare the static instance pointer
template<class T> SkySingleton<T>* SkySingleton<T>::s_pInstance = NULL;
#endif //__SKYSINGLETON_HPP__

View File

@@ -0,0 +1,100 @@
//------------------------------------------------------------------------------
// File : SkyTexture.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyTexture.hpp
*
* Interface definition for class SkyTexture, a texture class.
*/
#ifndef __SKYTEXTURE_HPP__
#define __SKYTEXTURE_HPP__
// #pragma warning( disable : 4786 )
#define __glext_h_
#define __GLEXT_H_
#define __glext_h_
#define __GLEXT_H_
#include <GL/glut.h>
//------------------------------------------------------------------------------
/**
* @class SkyTexture
* @brief A basic texture class.
*
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
*/
class SkyTexture
{
public:
//! Default Constructor.
SkyTexture() : _iID(0), _iWidth(0), _iHeight(0) {}
//! Constructor.
SkyTexture(unsigned int iWidth, unsigned int iHeight, unsigned int iTextureID)
: _iID(iTextureID), _iWidth(iWidth), _iHeight(iHeight) {}
//! Destructor.
~SkyTexture() {}
//! Sets the texture width in texels.
void SetWidth(unsigned int iWidth) { _iWidth = iWidth; }
//! Sets the texture height in texels.
void SetHeight(unsigned int iHeight) { _iHeight = iHeight; }
//! Sets the texture ID as created by OpenGL.
void SetID(unsigned int iTextureID) { _iID = iTextureID; }
//! Returns the texture width in texels.
unsigned int GetWidth() const { return _iWidth; }
//! Returns the texture height in texels.
unsigned int GetHeight() const { return _iHeight; }
//! Returns the texture ID as created by OpenGL.
unsigned int GetID() const { return _iID; }
inline SKYRESULT Destroy();
protected:
unsigned int _iID;
unsigned int _iWidth;
unsigned int _iHeight;
};
//------------------------------------------------------------------------------
// Function : SkyTexture::Destroy
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTexture::Destroy()
* @brief Destroys the OpenGL texture object represented by this SkyTexture object.
*
* Fails if the GL texture has not been created (i.e. its ID is zero).
*/
inline SKYRESULT SkyTexture::Destroy()
{
if (0 == _iID)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL,
"SkyTexture::Destroy(): Error: attempt to destroy unallocated texture.");
}
else
{
glDeleteTextures(1, &_iID);
_iID = 0;
}
return SKYRESULT_OK;
}
#endif //__SKYTEXTURE_HPP__

View File

@@ -0,0 +1,883 @@
//------------------------------------------------------------------------------
// File : SkyTextureManager.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyTextureManager.cpp
*
* Implementation of a manager that keeps track of texture resource locations and sharing.
*/
#pragma warning( disable : 4786)
#include "SkyTextureManager.hpp"
#include "SkyContext.hpp"
//#include "glvu.hpp"
//#include "ppm.hpp"
//#include "tga.hpp"
//#include "fileutils.hpp"
bool SkyTextureManager::s_bSlice3DTextures = false;
//------------------------------------------------------------------------------
// Function : SkyTextureManager::SkyTextureManager
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::SkyTextureManager(bool bSlice3DTextures)
* @brief Constructor.
*
*/
SkyTextureManager::SkyTextureManager(bool bSlice3DTextures /* = false */)
{
s_bSlice3DTextures = bSlice3DTextures;
// this should be put somewhere more safe -- like done once in the functions that actually
// use these extensions.
/*GraphicsContext::InstancePtr()->InitializeExtensions("GL_ARB_texture_cube_map "
"GL_VERSION_1_2");*/
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::~SkyTextureManager
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::~SkyTextureManager()
* @brief destructor.
*
* @todo <WRITE EXTENDED SkyTextureManager::~SkyTextureManager FUNCTION DOCUMENTATION>
*/
SkyTextureManager::~SkyTextureManager()
{
_texturePaths.clear();
for ( TextureIterator iter = _textures.begin();
iter != _textures.end();
++iter)
{
DestroyTextureObject(iter->second);
}
_textures.clear();
for ( TextureList::iterator uncachedIter = _uncachedTextures.begin();
uncachedIter != _uncachedTextures.end();
++uncachedIter)
{
DestroyTextureObject(*uncachedIter);
}
_uncachedTextures.clear();
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::AddPath
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::AddPath(const string &path)
* @brief Adds a texture path to the list of active search paths.
*
*/
void SkyTextureManager::AddPath(const string &path)
{
_texturePaths.push_back(path);
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::Get2DTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::Get2DTexture(const string& filename, SkyTexture& texture, bool bMipmap)
* @brief Returns a 2D texture object from the texture set.
*
* If the texture is already loaded, it is returned. If it is not, the texture is loaded from
* file, added to the texture set, and returned.
*
* If the image cannot be loaded, returns an error. Otherwise returns success.
*/
SKYRESULT SkyTextureManager::Get2DTexture(const string& filename,
SkyTexture& texture,
bool bMipmap /* = false */)
{
TextureIterator iter = _textures.find(filename);
if (iter != _textures.end())
{ // the texture is already loaded, just return it.
texture = iter->second;
}
else
{ // the texture is being requested for the first time, load and return it
FAIL_RETURN(Clone2DTexture(filename, texture, bMipmap));
_textures.insert(make_pair(filename, texture));
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::Get3DTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::Get3DTexture(const string& filename, SkyTexture& texture, unsigned int iDepth, bool bMipmap, bool bLoadFromSliceFiles)
* @brief Returns a 3D texture object from the texture set.
*
* If the texture is already loaded, it is returned. If it is not, the texture is loaded from
* file, added to the texture set, and returned. If the image cannot be loaded, returns an error.
* Otherwise returns success.
*
* For 3D textures, this simply loads a 2D image file, and duplicates it across each slice. The
* parameter iDepth must be set in order to use a 2D texture image for a 3D texture.
*/
SKYRESULT SkyTextureManager::Get3DTexture(const string& filename,
SkyTexture& texture,
unsigned int iDepth,
bool bMipmap /* = false */,
bool bLoadFromSliceFiles /* = false */)
{
TextureIterator iter = _textures.find(filename);
if (iter != _textures.end())
{ // the texture is already loaded, just return it.
texture = iter->second;
}
else
{ // the texture is being requested for the first time, load and return it
FAIL_RETURN(Clone3DTexture(filename, texture, iDepth, bMipmap, bLoadFromSliceFiles));
_textures.insert(make_pair(filename, texture));
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : roundPowerOf2
// Description :
//------------------------------------------------------------------------------
static int roundPowerOf2(int n)
{
int m;
for (m = 1; m < n; m *= 2);
// m >= n
if (m - n <= n - m/2)
return m;
else
return m/2;
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::Clone2DTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::Clone2DTexture( const string &filename, SkyTexture& texture, bool bMipmap)
* @brief Returns a 2D texture object.
*
* Ignores texture set. This always loads the file, if it exists, and creates and returns the texture.
*
* If the image cannot be loaded, returns an error. Otherwise returns success.
*/
SKYRESULT SkyTextureManager::Clone2DTexture(const string &filename,
SkyTexture& texture,
bool bMipmap /* = false */)
{
string pathFilename;
unsigned char *pImageData = NULL;
int iWidth = 0;
int iHeight = 0;
int iChannels = 0;
enum ImageType
{
IMAGE_PPM,
IMAGE_TGA
};
ImageType eType;
/****
// first get the image type from its extension.
if (filename.find(".tga") != string.npos || filename.find(".TGA") != string.npos)
eType = IMAGE_TGA;
else if (filename.find(".ppm") != string.npos || filename.find(".PPM") != string.npos)
eType = IMAGE_PPM;
else
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureManager error: invalid image format");
****/
// first try the filename sent in in case it includes a path.
//if (FileUtils::FileExists(filename.c_str()))
//{
// printf("Filename is %s\n", filename.c_str() );
//eType = IMAGE_TGA;
/* switch (eType)
{
case IMAGE_PPM:
LoadPPM(filename.c_str(), pImageData, iWidth, iHeight);
iChannels = 3;
break;
case IMAGE_TGA:
LoadTGA(filename.c_str(), pImageData, iWidth, iHeight, iChannels);
break;
default:
break;
}*/
//}
if (!pImageData) // image not found in current directory. Check the paths...
{
for ( StringList::iterator iter = _texturePaths.begin();
iter != _texturePaths.end();
++iter)
{ // loop over all texture paths, looking for the filename
// get just the filename without path.
int iPos = filename.find_last_of("/");
if (iPos == filename.npos)
iPos = filename.find_last_of("/");
// tack on the paths from the texture path list.
if (iPos != filename.npos)
pathFilename = (*iter) + "/" + filename.substr(iPos+1);
else
pathFilename = (*iter) + "/" + filename;
//if (FileUtils::FileExists(pathFilename.c_str()))
//{
/* switch (eType)
{
case IMAGE_PPM:
LoadPPM(pathFilename.c_str(), pImageData, iWidth, iHeight);
break;
case IMAGE_TGA:
LoadTGA(pathFilename.c_str(), pImageData, iWidth, iHeight, iChannels);
break;
default:
break;
}*/
//if (pImageData)
//break;
//}
}
}
if (!pImageData)
{
char buffer[256];
sprintf(buffer, "SkyTextureManager::Clone2DTexture(): Could not load image. %s.\n", filename.c_str());
FAIL_RETURN_MSG(SKYRESULT_OK, buffer);
}
// make sure it is power of 2 resolution.
int iNewWidth = roundPowerOf2(iWidth);
int iNewHeight = roundPowerOf2(iHeight);
int iMaxsize;
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
if (iNewWidth > iMaxsize)
{
iNewWidth = iMaxsize;
}
if (iNewHeight> iMaxsize)
{
iNewHeight = iMaxsize;
}
GLenum eFormat = (4 == iChannels) ? GL_RGBA : GL_RGB;
if (iNewWidth != iWidth || iNewHeight != iHeight)
{
unsigned char *pScaledImageData = new unsigned char[iChannels * iNewWidth * iNewHeight];
gluScaleImage(eFormat, iWidth, iHeight, GL_UNSIGNED_BYTE, pImageData,
iNewWidth, iNewHeight, GL_UNSIGNED_BYTE, pScaledImageData);
SAFE_DELETE_ARRAY(pImageData);
pImageData = pScaledImageData;
}
_Create2DTextureObject( texture, iNewWidth, iNewHeight, eFormat, pImageData);
SAFE_DELETE_ARRAY(pImageData);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::Clone3DTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::Clone3DTexture( const string &filename, SkyTexture& texture, unsigned int iDepth, bool bMipmap, bool bLoadFromSliceFiles)
* @brief Returns a 3D texture object.
*
* Ignores texture set. This always loads the file, if it exists, and creates and returns the texture.
* If the image cannot be loaded, returns an error. Otherwise returns success.
*/
SKYRESULT SkyTextureManager::Clone3DTexture(const string &filename,
SkyTexture& texture,
unsigned int iDepth,
bool bMipmap /* = false */,
bool bLoadFromSliceFiles /* = false */)
{
string pathFilename;
/*QImage image;
QDir dir;
unsigned char *pBits = NULL;
if (!bLoadFromSliceFiles)
{
// first try the filename sent in in case it includes a path.
if (image.load(filename))
{
image = QGLWidget::convertToGLFormat(image);
}
else
{
image.reset();
for ( QStringList::Iterator iter = _texturePaths.begin();
iter != _texturePaths.end();
iter++)
{ // loop over all texture paths, looking for the filename
pathFilename = (*iter) + "\\" + filename;
if (image.load(pathFilename))
{
image = QGLWidget::convertToGLFormat(image);
break;
}
else
image.reset();
}
}
if (image.isNull())
{
qWarning("SkyTextureManager::GetTexture(): Could not load image "
"%s.\n", filename);
return false;
}
// make sure it is power of 2 resolutions.
int iWidth = roundPowerOf2(image.width());
int iHeight = roundPowerOf2(image.height());
int iMaxsize;
if (s_bSlice3DTextures)
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
else
glGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &iMaxsize );
if (iWidth > iMaxsize)
{
iWidth = iMaxsize;
}
if (iHeight> iMaxsize)
{
iHeight = iMaxsize;
}
if (iWidth != image.width() || iHeight != image.height())
image = image.smoothScale(iWidth, iHeight);
// first build an array of repeated 2D textures...
QImage inverted(image.mirror());
pBits = new unsigned char[image.numBytes() * iDepth];
unsigned int iSliceSize = image.numBytes();
int bInverted = false;
int iInvertedCount = 8;
for (unsigned int iSlice = 0; iSlice < iDepth; ++iSlice)
{
memcpy(&(pBits[iSlice * iSliceSize]),
(bInverted) ? inverted.bits() : image.bits(),
image.numBytes());
if (--iInvertedCount <= 0)
{
iInvertedCount = 8;
bInverted = !bInverted;
}
}
}
else /// Load from a set of files matching the file pattern
{
QFileInfo fi(filename);
fi.refresh();
QString baseFilename = fi.baseName();
int truncPos = baseFilename.find(QRegExp("[0-9]"));
if (truncPos >= 0)
baseFilename.truncate(truncPos);
dir.setFilter(QDir::Files);
dir.setNameFilter(baseFilename + "*." + fi.extension());
dir.setSorting(QDir::Name);
QStringList files = dir.entryList();
bool bFound = true;
if (files.count() < iDepth)
{
bFound = false;
for ( QStringList::Iterator iter = _texturePaths.begin();
iter != _texturePaths.end();
iter++)
{
dir.setCurrent(*iter);
files = dir.entryList();
if (files.count() >= iDepth)
{
bFound = true;
break;
}
}
}
if (!bFound)
{
qWarning("SkyTextureManager::Clone3DTexture: ERROR: could not find %d files matching "
"%s", iDepth, filename.latin1());
return false;
}
else
{
unsigned int iSlice = 0;
unsigned int iSliceSize = 0;
for ( QStringList::Iterator iter = files.begin();
iter != files.end() && iSlice < iDepth;
iter++)
{
if (image.load(*iter))
{
image = QGLWidget::convertToGLFormat(image);
// make sure it is power of 2 resolution.
int iWidth = roundPowerOf2(image.width());
int iHeight = roundPowerOf2(image.height());
int iMaxsize;
if (s_bSlice3DTextures)
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &iMaxsize );
else
glGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &iMaxsize );
if (iWidth > iMaxsize)
{
iWidth = iMaxsize;
}
if (iHeight> iMaxsize)
{
iHeight = iMaxsize;
}
if (iWidth != image.width() || iHeight != image.height())
image = image.smoothScale(iWidth, iHeight);
if (0 == iSlice)
{
pBits = new unsigned char[image.numBytes() * iDepth];
iSliceSize = image.numBytes();
}
memcpy(&(pBits[iSlice * iSliceSize]), image.bits(), image.numBytes());
++iSlice;
}
else
{
qWarning("SkyTextureManager::Clone3DTexture: ERROR: could not find %d files matching "
"%s", iDepth, filename);
return false;
}
}
}
}
_Create3DTextureObject(texture,
image.width(),
image.height(),
iDepth,
GL_RGBA,
pBits);
*/
return SKYRESULT_FAIL;
}
//!
/*! */
//------------------------------------------------------------------------------
// Function : SkyTextureManager::GetCubeMapTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::GetCubeMapTexture(const string& filename, SkyTexture& texture, bool bMipmap)
* @brief Returns a cube map texture object from the texture set
*
* If the texture is already loaded, it is returned. If it is not, the texture is loaded from file,
* added to the texture set, and returned. If any of the 6 images cannot be loaded, returns an error.
* Otherwise returns success.
*/
SKYRESULT SkyTextureManager::GetCubeMapTexture( const string& filename,
SkyTexture& texture,
bool bMipmap)
{
TextureIterator iter = _textures.find(filename);
if (iter != _textures.end())
{ // the texture is already loaded, just return it.
texture = iter->second;
}
else
{ // the texture is being requested for the first time, load and return it
if (!CloneCubeMapTexture(filename, texture, bMipmap))
return false;
_textures.insert(make_pair(filename, texture));
}
return true;
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::CloneCubeMapTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::CloneCubeMapTexture(const string& filename, SkyTexture& texture, bool bMipmap)
* @brief Returns a cube map texture object.
*
* Ignores the texture set. This always loads the cube map texture, if all 6 face images exist,
* creates the texture, and returns it. If any of the 6 images cannot be loaded, returns an error.
* Otherwise returns success.
*/
SKYRESULT SkyTextureManager::CloneCubeMapTexture( const string& filename,
SkyTexture& texture,
bool bMipmap)
{
string pathFilename;
/*QImage images[6];
GLenum faces [] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB };
char* faceNames[] = {"posx", "negx", "posy", "negy", "posz", "negz" };
for ( QStringList::Iterator iter = _texturePaths.begin();
iter != _texturePaths.end();
iter++)
{ // loop over all texture paths, looking for the filename
for (int i = 0; i < 6; i++)
{
char buffer[FILENAME_MAX];
sprintf(buffer, filename.ascii(), faceNames[i]);
pathFilename = (*iter) + "\\" + buffer;
if (images[i].load(pathFilename))
{
images[i] = QGLWidget::convertToGLFormat(images[i]);
}
else
images[i].reset();
}
}
for (int i = 0; i < 6; i++)
{
if (images[i].isNull())
{
char buffer[FILENAME_MAX];
sprintf(buffer, filename.ascii(), faceNames[i]);
qWarning("SkyTextureManager::GetTexture(): Could not load image "
"%s.\n", buffer);
return false;
}
}
glGenTextures(1, &(texture.iTextureID));
texture.iWidth = images[0].width();
texture.iHeight = images[0].height();
// create and bind a cubemap texture object
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texture.iTextureID);
// enable automipmap generation if needed.
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_GENERATE_MIPMAP_SGIS, bMipmap);
if (bMipmap)
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
else
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
for (i = 0; i < 6; i++)
{
glTexImage2D(faces[i],
0,
GL_RGBA8,
images[i].width(),
images[i].height(),
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
images[i].bits());
}*/
return true;
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::_Create2DTextureObject
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::_Create2DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iFormat, unsigned char *pData)
* @brief Creates a 2D texture.
*
* Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
*/
SKYRESULT SkyTextureManager::_Create2DTextureObject(SkyTexture &texture,
unsigned int iWidth,
unsigned int iHeight,
unsigned int iFormat,
unsigned char *pData)
{
bool bNew = false;
unsigned int iTextureID;
if (!texture.GetID())
{
glGenTextures(1, &iTextureID);
texture.SetID(iTextureID);
bNew = true;
}
texture.SetWidth(iWidth);
texture.SetHeight(iHeight);
glBindTexture(GL_TEXTURE_2D, texture.GetID());
if (bNew)
{
GLenum iInternalFormat;
switch (iFormat)
{
case GL_LUMINANCE:
iInternalFormat = GL_LUMINANCE;
break;
case GL_LUMINANCE_ALPHA:
iInternalFormat = GL_LUMINANCE_ALPHA;
break;
default:
iInternalFormat = GL_RGBA8;
break;
}
glTexImage2D( GL_TEXTURE_2D,
0,
iInternalFormat,
iWidth, iHeight,
0,
(GLenum) iFormat,
GL_UNSIGNED_BYTE,
pData);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D,
0, 0, 0,
iWidth, iHeight,
(GLenum) iFormat,
GL_UNSIGNED_BYTE,
pData);
}
// set default filtering.
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::_Create3DTextureObject
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::_Create3DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iDepth, unsigned int iFormat, unsigned char *pData)
* @brief Creates a 3D texture
*
* Creates an OpenGL 3D texture object (or a set of 2D slices) and returns its ID and dimensions
* in a SkyTexture structure.
*/
SKYRESULT SkyTextureManager::_Create3DTextureObject(SkyTexture &texture,
unsigned int iWidth,
unsigned int iHeight,
unsigned int iDepth,
unsigned int iFormat,
unsigned char *pData)
{
/* bool bNew = false;
if (s_bSlice3DTextures) // create one 2D texture per slice!
{
if (!texture.pSliceIDs)
{
texture.pSliceIDs = new unsigned int[iDepth];
glGenTextures(iDepth, texture.pSliceIDs);
bNew = true;
}
}
else if (!texture.iTextureID)
{
glGenTextures(1, &(texture.iTextureID));
bNew = true;
}
texture.iWidth = iWidth;
texture.iHeight = iHeight;
texture.iDepth = iDepth;
texture.bSliced3D = s_bSlice3DTextures;
if (!s_bSlice3DTextures)
{
glBindTexture(GL_TEXTURE_3D, texture.iTextureID);
if (bNew)
{
unsigned int iInternalFormat;
switch (iFormat)
{
case GL_LUMINANCE:
iInternalFormat = GL_LUMINANCE;
break;
case GL_LUMINANCE_ALPHA:
iInternalFormat = GL_LUMINANCE_ALPHA;
break;
default:
iInternalFormat = GL_RGBA;
break;
}
glTexImage3D( GL_TEXTURE_3D,
0,
iInternalFormat,
iWidth, iHeight, iDepth,
0,
iFormat,
GL_UNSIGNED_BYTE,
pData);
}
else
{
glTexSubImage3D(GL_TEXTURE_3D,
0, 0, 0, 0,
iWidth, iHeight, iDepth,
iFormat,
GL_UNSIGNED_BYTE,
pData);
}
// set default filtering.
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else
{
unsigned int iInternalFormat = 0;
unsigned int iBytesPerPixel = 0;
switch (iFormat)
{
case GL_LUMINANCE:
iInternalFormat = GL_LUMINANCE;
iBytesPerPixel = 1;
break;
case GL_LUMINANCE_ALPHA:
iInternalFormat = GL_LUMINANCE_ALPHA;
iBytesPerPixel = 2;
break;
case GL_RGBA:
default:
iInternalFormat = GL_RGBA;
iBytesPerPixel = 4;
break;
}
unsigned int iSliceSize = iWidth * iHeight * iBytesPerPixel;
// create iDepth 2D texture slices...
for (unsigned int iSlice = 0; iSlice < iDepth; ++iSlice)
{
glBindTexture(GL_TEXTURE_2D, texture.pSliceIDs[iSlice]);
if (bNew)
{
glTexImage2D( GL_TEXTURE_2D,
0,
iInternalFormat,
iWidth, iHeight,
0,
iFormat,
GL_UNSIGNED_BYTE,
(pData + iSlice * iSliceSize));
}
else
{
glTexSubImage2D(GL_TEXTURE_2D,
0, 0, 0,
iWidth, iHeight,
iFormat,
GL_UNSIGNED_BYTE,
(pData + iSlice * iSliceSize));
}
// set default filtering.
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}
GLVU::CheckForGLError("SkyTextureManager::_Create3DTextureObject()");
return SKYRESULT_OK;*/
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::DestroyTextureObject
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::DestroyTextureObject(SkyTexture &texture)
* @brief destroys a SkyTexture object.
*
* Deletes the data as well as the OpenGL texture ID(s).
*/
void SkyTextureManager::DestroyTextureObject(SkyTexture &texture)
{ /*
if (texture.GetID)
glDeleteTextures(1, &(texture.iTextureID));
if (texture.bSliced3D && texture.pSliceIDs)
{
glDeleteTextures(texture.iDepth, texture.pSliceIDs);
delete [] texture.pSliceIDs;
} */
}

View File

@@ -0,0 +1,208 @@
//------------------------------------------------------------------------------
// File : SkyTextureManager.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
/**
* @file SkyTextureManager.hpp
*
* Definition of a manager that keeps track of texture locations and sharing of texture files. |
*/
#ifndef SKYTEXTUREMANAGER_HPP
#define SKYTEXTUREMANAGER_HPP
// #pragma warning( disable : 4786)
#include "SkySingleton.hpp"
#include "SkyTexture.hpp"
#include <string>
#include <list>
#include <map>
using namespace std;
// forward declaration for singleton
class SkyTextureManager;
//! A singleton of the SkyTextureManager. Can only create the TextureManager with TextureManager::Instantiate();
typedef SkySingleton<SkyTextureManager> TextureManager;
//------------------------------------------------------------------------------
/**
* @class SkyTextureManager
* @brief A resource manager for textures.
*
* This manager allows textures to be shared. It keeps a mapping of
* filenames to texture objects, and makes it easy to use the same texture
* for multiple objects without the objects having to be aware of the
* sharing. Supports cube map textures, and 2D textures. Can also be used
* to "clone textures", which creates unmanaged texture objects from files
* that are not kept in the mapping, and thus are not shared.
*/
class SkyTextureManager
{
public: // types
typedef list<string> StringList;
public: // methods
//.-------------------------------------------------------------------------.
//| Paths to texture directories
//.-------------------------------------------------------------------------.
void AddPath(const string& path);
//! Return the list of texture paths that will be searched by Get2DTexture() and Get3DTexture().
const StringList& GetPaths() const { return _texturePaths; }
//! Clear the list of texture paths that will be searched by Get2DTexture() and Get3DTexture().
void ClearPaths() { _texturePaths.clear(); }
//.-------------------------------------------------------------------------.
//| Texture loading
//.-------------------------------------------------------------------------.
SKYRESULT Get2DTexture( const string &filename,
SkyTexture& texture,
bool bMipmap = false);
SKYRESULT Get3DTexture( const string &filename,
SkyTexture& texture,
unsigned int iDepth,
bool bMipmap = false,
bool bLoadFromSliceFiles = false);
SKYRESULT GetCubeMapTexture( const string &filename,
SkyTexture& texture,
bool bMipmap = false);
//.-------------------------------------------------------------------------.
//| Texture cloning: create a duplicate texture object: not added to set!
//.-------------------------------------------------------------------------.
SKYRESULT Clone2DTexture( const string &filename,
SkyTexture& texture,
bool bMipmap = false);
SKYRESULT Clone3DTexture( const string &filename,
SkyTexture& texture,
unsigned int iDepth,
bool bMipmap = false,
bool bLoadFromSliceFiles = false );
SKYRESULT CloneCubeMapTexture( const string &filename,
SkyTexture& texture,
bool bMipmap = false);
//.-------------------------------------------------------------------------.
//| Texture Object Creation: not added to the texture set (no filename!)
//.-------------------------------------------------------------------------.
inline SKYRESULT Create2DTextureObject(SkyTexture &texture,
unsigned int iWidth,
unsigned int iHeight,
unsigned int iFormat,
unsigned char *pData);
inline SKYRESULT Create3DTextureObject(SkyTexture &texture,
unsigned int iWidth,
unsigned int iHeight,
unsigned int iDepth,
unsigned int iFormat,
unsigned char *pData);
//.-------------------------------------------------------------------------.
//| Texture Object Destruction: use this because texture objects are structs
//| that use shallow copies!
//.-------------------------------------------------------------------------.
static void DestroyTextureObject( SkyTexture &texture);
protected:
SkyTextureManager(bool bSlice3DTextures = false);
~SkyTextureManager();
SKYRESULT _Create2DTextureObject( SkyTexture &texture,
unsigned int iWidth,
unsigned int iHeight,
unsigned int iFormat,
unsigned char *pData);
SKYRESULT _Create3DTextureObject( SkyTexture &texture,
unsigned int iWidth,
unsigned int iHeight,
unsigned int iDepth,
unsigned int iFormat,
unsigned char *pData);
private:
typedef list<SkyTexture> TextureList;
typedef map<string, SkyTexture> TextureSet;
typedef TextureSet::iterator TextureIterator;
//.-------------------------------------------------------------------------.
//| Data
//.-------------------------------------------------------------------------.
// paths searched for textures specified by filename.
StringList _texturePaths;
// cached textures
TextureSet _textures; // loaded textures
// textures created directly, not loaded from file and cached.
TextureList _uncachedTextures;
// if this is true, then 3D textures will be represented as a set of 2D slices.
static bool s_bSlice3DTextures;
};
//------------------------------------------------------------------------------
// Function : SkyTextureManager::Create2DTextureObject
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::Create2DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iFormat, unsigned char *pData)
* @brief Creates a 2D texture.
*
* Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
* This texture will be deleted by the texture manager at shutdown.
*
*/
inline SKYRESULT SkyTextureManager::Create2DTextureObject(SkyTexture &texture,
unsigned int iWidth,
unsigned int iHeight,
unsigned int iFormat,
unsigned char *pData)
{
SKYRESULT retval = _Create2DTextureObject(texture, iWidth, iHeight, iFormat, pData);
if SKYSUCCEEDED(retval)
_uncachedTextures.push_back(texture);
return retval;
}
//------------------------------------------------------------------------------
// Function : SkyTextureManager::Create3DTextureObject
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureManager::Create3DTextureObject(SkyTexture &texture, unsigned int iWidth, unsigned int iHeight, unsigned int iDepth, unsigned int iFormat, unsigned char *pData)
* @brief Creates a 3D texture.
*
* Creates an OpenGL texture object and returns its ID and dimensions in a SkyTexture structure.
* This texture will be deleted by the texture manager at shutdown, and should not be destroyed
* by the user.
*
*/
inline SKYRESULT SkyTextureManager::Create3DTextureObject(SkyTexture &texture,
unsigned int iWidth,
unsigned int iHeight,
unsigned int iDepth,
unsigned int iFormat,
unsigned char *pData)
{
SKYRESULT retval = _Create3DTextureObject(texture, iWidth, iHeight, iDepth, iFormat, pData);
if SKYSUCCEEDED(retval)
_uncachedTextures.push_back(texture);
return retval;
}
#endif //QGLVUTEXTUREMANAGER_HPP

View File

@@ -0,0 +1,351 @@
//------------------------------------------------------------------------------
// File : SkyTextureState.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyTextureState.cpp
*
* Implementation of class SkyTextureState, which encapsulates OpenGL texture state.
*/
#include "SkyTextureState.hpp"
//#include "glvu.hpp"
//------------------------------------------------------------------------------
// Static initializations.
//------------------------------------------------------------------------------
unsigned int SkyTextureState::s_iNumTextureUnits = 0;
//------------------------------------------------------------------------------
// Function : SkyTextureState::SkyTextureState
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::SkyTextureState()
* @brief Constructor.
*/
SkyTextureState::SkyTextureState()
{
if (0 == s_iNumTextureUnits)
{
int iNumTextureUnits = 0;
#ifdef GL_ARB_multitexture
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &iNumTextureUnits);
if (iNumTextureUnits > 0)
s_iNumTextureUnits = iNumTextureUnits;
else
s_iNumTextureUnits = 1;
#endif
}
_pTextureUnitState = new TexState[s_iNumTextureUnits];
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::~SkyTextureState
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::~SkyTextureState()
* @brief Destructor.
*/
SkyTextureState::~SkyTextureState()
{
SAFE_DELETE(_pTextureUnitState);
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::Activate
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::Activate()
* @brief @todo <WRITE BRIEF SkyTextureState::Activate DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyTextureState::Activate FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyTextureState::Activate()
{
SkyTextureState *pCurrent = GraphicsContext::InstancePtr()->GetCurrentTextureState();
assert(NULL != pCurrent);
//GLVU::CheckForGLError("SkyTextureState::Activate(8)");
for (unsigned int i = 0; i < s_iNumTextureUnits; ++i)
{
#ifdef GL_ARB_multitexture
if (s_iNumTextureUnits > 1)
glActiveTextureARB(GL_TEXTURE0_ARB + i);
#endif
bool bEnabled = IsTextureEnabled(i);
if (pCurrent->IsTextureEnabled(i) != bEnabled)
{
FAIL_RETURN(pCurrent->EnableTexture(i, bEnabled));
//GLVU::CheckForGLError("SkyTextureState::Activate(7)");
if (bEnabled)
glEnable(GetActiveTarget(i));
else
glDisable(GetActiveTarget(i));
}
//GLVU::CheckForGLError("SkyTextureState::Activate(6)");
if (bEnabled)
{
GLenum eTarget = GetActiveTarget(i);
unsigned int iID = GetTextureID(i);
// if ((pCurrent->GetActiveTarget(i) != eTarget) ||
// (pCurrent->GetTextureID(i) != iID))
// {
FAIL_RETURN(pCurrent->SetTexture(i, eTarget, iID));
glBindTexture(eTarget, iID);
// }
//GLVU::CheckForGLError("SkyTextureState::Activate(5)");
GLenum paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_S);
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_WRAP_S) != paramValue)
{
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_S, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, paramValue);
}
//GLVU::CheckForGLError("SkyTextureState::Activate(4)");
paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_T);
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_WRAP_T) != paramValue)
{
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_T, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, paramValue);
}
//GLVU::CheckForGLError("SkyTextureState::Activate(3)");
paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_R);
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_WRAP_R) != paramValue)
{
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_R, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_WRAP_R, paramValue);
}
//GLVU::CheckForGLError("SkyTextureState::Activate(2)");
paramValue = GetTextureParameter(i, GL_TEXTURE_MIN_FILTER);
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_MIN_FILTER) != paramValue)
{
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_MIN_FILTER, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, paramValue);
}
//GLVU::CheckForGLError("SkyTextureState::Activate(1)");
paramValue = GetTextureParameter(i, GL_TEXTURE_MAG_FILTER);
if (pCurrent->GetTextureParameter(i, GL_TEXTURE_MAG_FILTER) != paramValue)
{
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_MAG_FILTER, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, paramValue);
}
//GLVU::CheckForGLError("SkyTextureState::Activate()");
}
#ifdef GL_ARB_multitexture
if (s_iNumTextureUnits > 1)
glActiveTextureARB(GL_TEXTURE0_ARB);
#endif
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::Force
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::Force()
* @brief @todo <WRITE BRIEF SkyTextureState::Activate DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyTextureState::Activate FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyTextureState::Force()
{
SkyTextureState *pCurrent = GraphicsContext::InstancePtr()->GetCurrentTextureState();
assert(NULL != pCurrent);
//GLVU::CheckForGLError("SkyTextureState::Activate(8)");
for (unsigned int i = 0; i < s_iNumTextureUnits; ++i)
{
#ifdef GL_ARB_multitexture
if (s_iNumTextureUnits > 1)
glActiveTextureARB(GL_TEXTURE0_ARB + i);
#endif
bool bEnabled = IsTextureEnabled(i);
FAIL_RETURN(pCurrent->EnableTexture(i, bEnabled));
//GLVU::CheckForGLError("SkyTextureState::Activate(7)");
if (bEnabled)
glEnable(GetActiveTarget(i));
else
glDisable(GetActiveTarget(i));
//GLVU::CheckForGLError("SkyTextureState::Activate(6)");
GLenum eTarget = GetActiveTarget(i);
unsigned int iID = GetTextureID(i);
FAIL_RETURN(pCurrent->SetTexture(i, eTarget, iID));
glBindTexture(eTarget, iID);
//GLVU::CheckForGLError("SkyTextureState::Activate(5)");
GLenum paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_S);
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_S, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, paramValue);
//GLVU::CheckForGLError("SkyTextureState::Activate(4)");
paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_T);
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_T, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, paramValue);
//GLVU::CheckForGLError("SkyTextureState::Activate(3)");
paramValue = GetTextureParameter(i, GL_TEXTURE_WRAP_R);
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_WRAP_R, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_WRAP_R, paramValue);
//GLVU::CheckForGLError("SkyTextureState::Activate(2)");
paramValue = GetTextureParameter(i, GL_TEXTURE_MIN_FILTER);
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_MIN_FILTER, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, paramValue);
//GLVU::CheckForGLError("SkyTextureState::Activate(1)");
paramValue = GetTextureParameter(i, GL_TEXTURE_MAG_FILTER);
FAIL_RETURN(pCurrent->SetTextureParameter(i, GL_TEXTURE_MAG_FILTER, paramValue));
glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, paramValue);
#ifdef GL_ARB_multitexture
if (s_iNumTextureUnits > 1)
glActiveTextureARB(GL_TEXTURE0_ARB);
#endif
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::SetTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::SetTexture(unsigned int iTextureUnit, GLenum eTarget, SkyTexture& texture)
* @brief @todo <WRITE BRIEF SkyTextureState::BindTexture DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyTextureState::BindTexture FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyTextureState::SetTexture(unsigned int iTextureUnit,
GLenum eTarget,
SkyTexture& texture)
{
if (iTextureUnit >= s_iNumTextureUnits)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureState::BindTexture(): Invalid texture unit.");
}
_pTextureUnitState[iTextureUnit].eActiveTarget = eTarget;
_pTextureUnitState[iTextureUnit].iBoundTexture = texture.GetID();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::SetTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::SetTexture(unsigned int iTextureUnit, GLenum eTarget, unsigned int iTextureID)
* @brief @todo <WRITE BRIEF SkyTextureState::SetTexture DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyTextureState::SetTexture FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyTextureState::SetTexture(unsigned int iTextureUnit,
GLenum eTarget,
unsigned int iTextureID)
{
if (iTextureUnit >= s_iNumTextureUnits)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureState::BindTexture(): Invalid texture unit.");
}
_pTextureUnitState[iTextureUnit].eActiveTarget = eTarget;
_pTextureUnitState[iTextureUnit].iBoundTexture = iTextureID;
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::EnableTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::EnableTexture(unsigned int iTextureUnit, bool bEnable)
* @brief @todo <WRITE BRIEF SkyTextureState::EnableTexture DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyTextureState::EnableTexture FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyTextureState::EnableTexture(unsigned int iTextureUnit, bool bEnable)
{
if (iTextureUnit >= s_iNumTextureUnits)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureState::EnableTexture(): Invalid texture unit.");
}
_pTextureUnitState[iTextureUnit].bEnabled = bEnable;
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::SetTextureParameter
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::SetTextureParameter(unsigned int iTextureUnit, GLenum eParameter, GLenum eMode)
* @brief @todo <WRITE BRIEF SkyTextureState::SetTextureParameter DOCUMENTATION>
*
* @todo <WRITE EXTENDED SkyTextureState::SetTextureParameter FUNCTION DOCUMENTATION>
*/
SKYRESULT SkyTextureState::SetTextureParameter(unsigned int iTextureUnit,
GLenum eParameter,
GLenum eMode)
{
if (iTextureUnit >= s_iNumTextureUnits)
{
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTextureState::SetTextureParameter(): Invalid texture unit.");
}
switch (eParameter)
{
case GL_TEXTURE_WRAP_S:
_pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_S] = eMode;
break;
case GL_TEXTURE_WRAP_T:
_pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_T] = eMode;
break;
case GL_TEXTURE_WRAP_R:
_pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_R] = eMode;
break;
case GL_TEXTURE_MIN_FILTER:
_pTextureUnitState[iTextureUnit].eFilterMode[TexState::SKY_FILTER_MIN] = eMode;
break;
case GL_TEXTURE_MAG_FILTER:
_pTextureUnitState[iTextureUnit].eFilterMode[TexState::SKY_FILTER_MAG] = eMode;
break;
default:
FAIL_RETURN_MSG(SKYRESULT_FAIL, "SkyTExtureState::SetTextureParameter(): Invalid parameter.");
break;
}
return SKYRESULT_OK;
}

View File

@@ -0,0 +1,206 @@
//------------------------------------------------------------------------------
// File : SkyTextureState.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyTextureState.hpp
*
* Interface Definition for class SkyTextureState, which encapsulates OpenGL texture state.
*/
#ifndef __SKYTEXTURESTATE_HPP__
#define __SKYTEXTURESTATE_HPP__
#include "SkyUtil.hpp"
#include "SkyTexture.hpp"
#include "SkyContext.hpp"
#include <map>
//------------------------------------------------------------------------------
/**
* @class SkyTextureState
* @brief A wrapper for texture unit state.
*
* @todo <WRITE EXTENDED CLASS DESCRIPTION>
*/
class SkyTextureState
{
public: // methods
SkyTextureState();
~SkyTextureState();
SKYRESULT Force();
SKYRESULT Activate();
SKYRESULT SetTexture(unsigned int iTextureUnit, GLenum eTarget, SkyTexture& texture);
SKYRESULT SetTexture(unsigned int iTextureUnit, GLenum eTarget, unsigned int iTextureID);
SKYRESULT EnableTexture(unsigned int iTextureUnit, bool bEnable);
SKYRESULT SetTextureParameter(unsigned int iTextureUnit,
GLenum eParameter,
GLenum eMode);
inline GLenum GetActiveTarget(unsigned int iTextureUnit) const;
inline unsigned int GetTextureID(unsigned int iTextureUnit) const;
inline bool IsTextureEnabled(unsigned int iTextureUnit) const;
inline GLenum GetTextureParameter(unsigned int iTextureUnit, GLenum eParameter) const;
protected: // datatypes
struct TexState
{
TexState() : eActiveTarget(GL_TEXTURE_2D), iBoundTexture(0), bEnabled(false)
{
// set state to GL defaults.
int i;
for (i = 0; i < SKY_TEXCOORD_COUNT; ++i) { eWrapMode[i] = GL_REPEAT; }
eFilterMode[SKY_FILTER_MIN] = GL_NEAREST_MIPMAP_LINEAR;
eFilterMode[SKY_FILTER_MAG] = GL_LINEAR;
}
enum TexCoord
{
SKY_TEXCOORD_S,
SKY_TEXCOORD_T,
SKY_TEXCOORD_R,
SKY_TEXCOORD_COUNT
};
enum TexFilter
{
SKY_FILTER_MIN,
SKY_FILTER_MAG,
SKY_FILTER_COUNT
};
GLenum eActiveTarget;
unsigned int iBoundTexture;
bool bEnabled;
GLenum eWrapMode[SKY_TEXCOORD_COUNT];
GLenum eFilterMode[SKY_FILTER_COUNT];
};
protected: // data
TexState *_pTextureUnitState; // one per texture unit
static unsigned int s_iNumTextureUnits;
};
//------------------------------------------------------------------------------
// Function : SkyTextureState::GetActiveTarget
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::GetActiveTarget(unsigned int iTextureUnit) const
* @brief Returns the active texture target for the specified texture unit.
*
* If an invalid texture unit is specifed, returns GL_NONE.
*/
inline GLenum SkyTextureState::GetActiveTarget(unsigned int iTextureUnit) const
{
if (iTextureUnit >= s_iNumTextureUnits)
{
SkyTrace("SkyTextureState::GetActiveTexture(): Invalid texture unit.");
return GL_NONE;
}
return _pTextureUnitState[iTextureUnit].eActiveTarget;
}
//------------------------------------------------------------------------------
// Function : int SkyTextureState::GetTextureID
// Description :
//------------------------------------------------------------------------------
/**
* @fn int SkyTextureState::GetTextureID(unsigned int iTextureUnit) const
* @brief Returns the texture ID associated with the specified texture unit.
*
* If an invalid texture unit is specifed, returns GL_NONE.
*/
inline unsigned int SkyTextureState::GetTextureID(unsigned int iTextureUnit) const
{
if (iTextureUnit >= s_iNumTextureUnits)
{
SkyTrace("SkyTextureState::GetTextureID(): Invalid texture unit.");
return GL_NONE;
}
return _pTextureUnitState[iTextureUnit].iBoundTexture;
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::IsTextureEnabled
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::IsTextureEnabled(unsigned int iTextureUnit) const
* @brief Returns the status (enabled or disabled) of the specified texture unit.
*
* If an invalid texture unit is specifed, returns false.
*/
inline bool SkyTextureState::IsTextureEnabled(unsigned int iTextureUnit) const
{
if (iTextureUnit >= s_iNumTextureUnits)
{
SkyTrace("SkyTextureState::IsTextureEnabled(): Invalid texture unit.");
return false;
}
return _pTextureUnitState[iTextureUnit].bEnabled;
}
//------------------------------------------------------------------------------
// Function : SkyTextureState::GetTextureParameter
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyTextureState::GetTextureParameter(unsigned int iTextureUnit, GLenum eParamter) const
* @brief Returns the current value of @eParameter on the specified texture unit.
*
* If an invalid texture unit or parameter is specified, returns GL_NONE.
*/
inline GLenum SkyTextureState::GetTextureParameter(unsigned int iTextureUnit, GLenum eParameter) const
{
if (iTextureUnit >= s_iNumTextureUnits)
{
SkyTrace("SkyTextureState::GetTextureParamter(): Invalid texture unit.");
return GL_NONE;
}
switch (eParameter)
{
case GL_TEXTURE_WRAP_S:
return _pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_S];
break;
case GL_TEXTURE_WRAP_T:
return _pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_T];
break;
case GL_TEXTURE_WRAP_R:
return _pTextureUnitState[iTextureUnit].eWrapMode[TexState::SKY_TEXCOORD_R];
break;
case GL_TEXTURE_MIN_FILTER:
return _pTextureUnitState[iTextureUnit].eFilterMode[TexState::SKY_FILTER_MIN];
break;
case GL_TEXTURE_MAG_FILTER:
return _pTextureUnitState[iTextureUnit].eFilterMode[TexState::SKY_FILTER_MAG];
break;
default:
SkyTrace("SkyTExtureState::SetTextureParameter(): Invalid parameter.");
break;
}
return GL_NONE;
}
#endif //__SKYTEXTURESTATE_HPP__

View File

@@ -0,0 +1,50 @@
//------------------------------------------------------------------------------
// File : SkyUtil.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyUtil.cpp
*
* Implemtation of global utility functions.
*/
#include "SkyUtil.hpp"
//------------------------------------------------------------------------------
// Function : SkyTrace
// Description :
//------------------------------------------------------------------------------
/**
* SkyTrace( char* strMsg, ... )
* @brief Prints formatted output, debug only.
*
* Includes file and line number information automatically.
*/
void SkyTrace( char* strMsg, ... )
{
#if defined(DEBUG) | defined(_DEBUG)
char strBuffer[512];
va_list args;
va_start(args, strMsg);
_vsnprintf( strBuffer, 512, strMsg, args );
va_end(args);
fprintf(stderr, "[SkyTrace] %s(%d): %s\n",__FILE__, __LINE__, strBuffer);
#endif
}

View File

@@ -0,0 +1,192 @@
//------------------------------------------------------------------------------
// File : SkyUtil.hpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyUtil.hpp
* @brief Safe deallocation functions, result codes, trace functions, and macros.
*/
#ifndef __SKYUTIL_HPP__
#define __SKYUTIL_HPP__
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
//-----------------------------------------------------------------------------
// Useful constants
//-----------------------------------------------------------------------------
//! Pi.
const float SKY_PI = 4.0f * (float) atan(1.0f);
//! 1.0 / Pi
const float SKY_INV_PI = 1.0f / SKY_PI;
//! 1.0 / (4.0 * Pi)
const float SKY_INV_4PI = 1.0f / (4.0f * SKY_PI);
//-----------------------------------------------------------------------------
// Safe deallocation
//-----------------------------------------------------------------------------
//! Delete and set pointer to NULL.
#define SAFE_DELETE(p) { delete (p); (p)=NULL; }
//! Delete an array and set pointer to NULL.
#define SAFE_DELETE_ARRAY(p) { delete[] (p); (p)=NULL; }
//#define SAFE_RELEASE(p) { (p) = NULL; }
//{ if(p) { (p)->Release(); (p)=NULL; } }
//------------------------------------------------------------------------------
// Useful Macros
//------------------------------------------------------------------------------
//! Convert Degrees to Radians
#define SKYDEGREESTORADS 0.01745329252f
//! Convert Radians to Degrees
#define SKYRADSTODEGREES 57.2957795131f
//------------------------------------------------------------------------------
// Function : SkyGetLogBaseTwo
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyGetLogBaseTwo(int iNum)
* @brief Returns the integer base two logarithm of the integer input.
*/
inline int SkyGetLogBaseTwo(int iNum)
{
int i, n;
for(i = iNum-1, n = 0; i > 0; i >>= 1, n++ );
return n;
}
//------------------------------------------------------------------------------
// Function : SkyTrace
// Description :
//------------------------------------------------------------------------------
void SkyTrace( char* strMsg, ... );
//.----------------------------------------------------------------------------.
//| Result Codes |
//.----------------------------------------------------------------------------.
//! SKYRESULTs are used for returning error information that can be used to trace bugs.
typedef int SKYRESULT;
//! Returns true if the SKYRESULT is a success result.
#define SKYSUCCEEDED(Status) ((SKYRESULT)(Status) >= 0)
//! Returns true if the SKYRESULT is a failure result.
#define SKYFAILED(Status) ((SKYRESULT)(Status) < 0)
//! SKYRESULTs are used for returning error information that can be used to trace bugs.
enum SKYRESULT_CODES
{
// SUCCESS CODES: non-negative
SKYRESULT_OK = 1,
// FAILURE CODES: negative
SKYRESULT_FAIL = -1
};
//-----------------------------------------------------------------------------
// FAIL_RETURN
//-----------------------------------------------------------------------------
// Print debug messages to the WIN32 debug window
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Function : FAIL_RETURN
// Description :
//------------------------------------------------------------------------------
/**
* @fn FAIL_RETURN(p)
* @brief Prints a trace message if @a p failed, and returns the failure code.
*
* Outputs in a format that can be double-clicked in DevStudio to open the
* appropriate file and location.
*/
#if defined(DEBUG) | defined(_DEBUG)
#define FAIL_RETURN(p) \
{ \
SKYRESULT __SKYUTIL__result__; \
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
fprintf(stderr, "!!!! FAIL_RETURN TRAP !!!! %s: %d: %d\n",__FILE__, __LINE__, __SKYUTIL__result__); \
return __SKYUTIL__result__; \
} \
}
#else
#define FAIL_RETURN(p) p
#endif
//------------------------------------------------------------------------------
// Function : FAIL_RETURN_MSG
// Description :
//------------------------------------------------------------------------------
/**
* @fn FAIL_RETURN_MSG(p,str)
* @brief Similar to FAIL_RETURN, but also appends a user-supplied message.
*
* @see FAIL_RETURN, FAIL_RETURN_MSG
*/
#if defined(DEBUG) | defined(_DEBUG)
#define FAIL_RETURN_MSG(p,str) \
{ \
SKYRESULT __SKYUTIL__result__; \
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
fprintf(stderr, "!!!! FAIL_RETURN_MSG TRAP !!!! %s: %d: %d: %s\n",__FILE__,__LINE__,__SKYUTIL__result__,str); \
return __SKYUTIL__result__; \
} \
}
#else
#define FAIL_RETURN_MSG(p,str) p
#endif
//------------------------------------------------------------------------------
// Function : FAIL_RETURN_MSGBOX
// Description :
//------------------------------------------------------------------------------
/**
* @fn FAIL_RETURN_MSGBOX(p,str)
* @brief Similar to FAIL_RETURN_MSG, but also displays the error in a message box (in Windows).
*
* @see FAIL_RETURN_MSG, FAIL_RETURN
*/
#if defined(DEBUG) | defined(_DEBUG)
#ifdef USEWINDOWSOUTPUT
#define FAIL_RETURN_MSGBOX(p,str) \
{ \
SKYRESULT __SKYUTIL__result__; \
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
char msg[512]; \
sprintf(msg, "%s: %d: %d: %s\n",__FILE__,__LINE__,__SKYUTIL__result__,str); \
MessageBox(NULL, msg, "!!!! FAIL_RETURN_MSG TRAP !!!!", MB_OK); \
return __SKYUTIL__result__; \
} \
}
#else
#define FAIL_RETURN_MSGBOX(p,str) \
{ \
SKYRESULT __SKYUTIL__result__; \
if ( SKYFAILED( __SKYUTIL__result__ = (p) ) ) { \
fprintf(stderr, "!!!! FAIL_RETURN_MSG TRAP !!!! %s: %d: %d: %s\n",__FILE__,__LINE__,__D3DUTIL__hres__,str); \
return __SKYUTIL__result__; \
} \
}
#endif
#else
#define FAIL_RETURN_MSGBOX(p,str) p
#endif
#endif //__SKYUTIL_HPP__

View File

@@ -0,0 +1,84 @@
//------------------------------------------------------------------------------
// File : camdisplay.cpp
//------------------------------------------------------------------------------
// GLVU : Copyright 1997 - 2002
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The University of North Carolina at Chapel Hill makes no representations
// about the suitability of this software for any purpose. It is provided
// "as is" without express or implied warranty.
//============================================================================
// camdisplay.cpp
//============================================================================
#include <GL/glut.h>
#include "camera.hpp"
//----------------------------------------------------------------------------
// OPENGL CAMERA FRUSTUM DRAWING ROUTINES
//----------------------------------------------------------------------------
void Camera::Display() const
{
// CALC EIGHT CORNERS OF FRUSTUM (NEAR PTS AND FAR PTS)
Vec3f V[8];
CalcVerts(V);
// DRAW THE FRUSTUM IN WIREFRAME
glBegin(GL_LINE_LOOP); // TOP FACE
glVertex3fv(&(V[4].x)); glVertex3fv(&(V[5].x));
glVertex3fv(&(V[1].x)); glVertex3fv(&(V[0].x));
glEnd();
glBegin(GL_LINE_LOOP); // BOTTOM FACE
glVertex3fv(&(V[3].x)); glVertex3fv(&(V[2].x));
glVertex3fv(&(V[6].x)); glVertex3fv(&(V[7].x));
glEnd();
glBegin(GL_LINE_LOOP); // LEFT FACE
glVertex3fv(&(V[1].x)); glVertex3fv(&(V[5].x));
glVertex3fv(&(V[6].x)); glVertex3fv(&(V[2].x));
glEnd();
glBegin(GL_LINE_LOOP); // RIGHT FACE
glVertex3fv(&(V[0].x)); glVertex3fv(&(V[3].x));
glVertex3fv(&(V[7].x)); glVertex3fv(&(V[4].x));
glEnd();
glBegin(GL_LINE_LOOP); // NEAR FACE
glVertex3fv(&(V[1].x)); glVertex3fv(&(V[2].x));
glVertex3fv(&(V[3].x)); glVertex3fv(&(V[0].x));
glEnd();
glBegin(GL_LINE_LOOP); // FAR FACE
glVertex3fv(&(V[4].x)); glVertex3fv(&(V[7].x));
glVertex3fv(&(V[6].x)); glVertex3fv(&(V[5].x));
glEnd();
// DRAW PROJECTOR LINES FROM EYE TO CORNERS OF VIEWPLANE WINDOW
glBegin(GL_LINES);
glVertex3fv(&(Orig.x)); glVertex3fv(&(V[1].x));
glVertex3fv(&(Orig.x)); glVertex3fv(&(V[2].x));
glVertex3fv(&(Orig.x)); glVertex3fv(&(V[3].x));
glVertex3fv(&(Orig.x)); glVertex3fv(&(V[0].x));
glEnd();
}
void Camera::DisplayInGreen() const
{
//draws the camera in unlit green lines, then restores the GL state
glPushAttrib(GL_LIGHTING_BIT);
glDisable(GL_LIGHTING);
glPushAttrib(GL_LINE_BIT);
glLineWidth(1.0);
glColor3f(0,1,0);
Display();
glPopAttrib();
glPopAttrib();
}

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