PLIB 1.8.5+ r2173 from http://plib.svn.sourceforge.net/svnroot/plib/trunk
BIN
doc/FDS_logo.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
doc/FNT.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/JS.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/MinigolfManiacs.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
doc/NET.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/PSL.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
doc/PUI.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/PW.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
doc/SG.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
doc/SL.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
doc/SSG.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
doc/UL.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
55
doc/auxlibs/index.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>Auxiliary Libraries for PLIB.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<H1>Auxiliary Libraries for PLIB.</H1>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>
|
||||
by Steve Baker
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H2>Introduction</H2>
|
||||
PLIB/AUX is a suite of auxiliary libraries that build
|
||||
higher level classes on top of the basic PLIB libraries.
|
||||
<p>
|
||||
These will be installed and named with the same
|
||||
conventions as the base PLIB libraries, eg:
|
||||
<pre>
|
||||
|
||||
/usr/include/plib/auxXXX.h
|
||||
/usr/lib/libplibauxXXX.a
|
||||
|
||||
</pre>
|
||||
...where 'XXX' is the name of the aux library.
|
||||
<p>
|
||||
PLIB/AUX functions, classes and constants are all
|
||||
named after the base PLIB library that they logically
|
||||
belong with, hence enhancements to SSG will share the
|
||||
'ssg' prefix but add a 'u':
|
||||
<pre>
|
||||
|
||||
eg
|
||||
class ssguParticleSystem ;
|
||||
class puuFileBrowser ;
|
||||
|
||||
</pre>
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
114
doc/contacts.html
Normal file
@@ -0,0 +1,114 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>PLIB: Contacting Us.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="plib_logo.png" ALT="PLIB Logo" width=256 height=245>
|
||||
<br>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<H1>
|
||||
<FONT SIZE=9>S</FONT><FONT SIZE=5>TEVE'S</FONT>
|
||||
<FONT SIZE=9>P</FONT><FONT SIZE=5>ORTABLE</FONT>
|
||||
<FONT SIZE=9>G</FONT><FONT SIZE=5>AME</FONT>
|
||||
<FONT SIZE=9>L</FONT><FONT SIZE=5>IBRARY.</FONT>
|
||||
</H1>
|
||||
</center>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't
|
||||
get much Sleep.
|
||||
<br>
|
||||
-- Woody Allen
|
||||
</ul>
|
||||
<center>
|
||||
<A href="http://sf.net">
|
||||
<IMG src="http://sf.net/sflogo.php?group_id=382&type=1" width="88" height="31" border="0" ALT="Sourceforge Logo"></A>
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD valign=top align=left>
|
||||
<A HREF="index.html"><IMG SRC="home.png" ALT="HOME" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="whats_inside.html"><IMG SRC="whats_inside.png" ALT="WHAT'S INSIDE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="license.html"><IMG SRC="license.png" ALT="LICENSE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="contacts.html"><IMG SRC="contacts.png" ALT="CONTACTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="requirements.html"><IMG SRC="requirements.png" ALT="REQUIREMENTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="gallery.html"><IMG SRC="gallery.png" ALT="GALLERY" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="download.html"><IMG SRC="download.png" ALT="DOWNLOAD & INSTALL" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="examples.html"><IMG SRC="examples.png" ALT="EXAMPLES" BORDER="0" width=150 height=50></A><br>
|
||||
|
||||
<A HREF="sg/index.html"><IMG SRC="SG.png" ALT="SG" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="ssg/index.html"><IMG SRC="SSG.png" ALT="SSG" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="ssgAux/index.html"><IMG SRC="ssgAux.png" ALT="SSGAUX" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="fnt/index.html"><IMG SRC="FNT.png" ALT="FNT" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pui/index.html"><IMG SRC="PUI.png" ALT="PUI" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="psl/index.html"><IMG SRC="PSL.png" ALT="PSL" BORDER="0" width=75 height=25></A>
|
||||
|
||||
<A HREF="util/index.html"><IMG SRC="UL.png" ALT="UL" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="js/index.html"><IMG SRC="JS.png" ALT="JS" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="net/index.html"><IMG SRC="NET.png" ALT="NET" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="sl/index.html"><IMG SRC="SL.png" ALT="SL" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pw/index.html"><IMG SRC="PW.png" ALT="PW" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="puAux/index.html"><IMG SRC="puAux.png" ALT="PUAUX" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H2>Contacting Us - and Contributing to PLIB.</H2>
|
||||
There are three PLIB mailing lists:
|
||||
In order to keep the spam off the lists, it's set up so you have
|
||||
to subscribe in order to send mail. To do that, visit:
|
||||
<ul>
|
||||
<li>
|
||||
<A HREF="http://lists.sf.net/mailman/listinfo/plib-announce">
|
||||
http://lists.sf.net/mailman/listinfo/plib-announce</A><br>
|
||||
A very low traffic, heavily moderated list where I'll announce new versions
|
||||
of PLIB - you may not post to 'plib-announce'.<p>
|
||||
<li>
|
||||
<A HREF="http://lists.sf.net/mailman/listinfo/plib-users">
|
||||
http://lists.sf.net/mailman/listinfo/plib-users</A><br>
|
||||
A list for PLIB users - this would be the correct place
|
||||
to ask questions, report bugs and generally hang out with
|
||||
fellow sufferers.<p>
|
||||
<li>
|
||||
<A HREF="http://lists.sf.net/mailman/listinfo/plib-devel">
|
||||
http://lists.sf.net/mailman/listinfo/plib-devel</A><br>
|
||||
A list for people who wish to contribute to the development
|
||||
of PLIB - this list will have a high technical content and we'll
|
||||
try to keep discussions there focussed and on-topic.<p>
|
||||
</ul>
|
||||
<p>
|
||||
Please do not send me personal mail in situations when one of
|
||||
the public mailing lists would be an appropriate forum - I hate
|
||||
it when people do that and I'll usually ignore you.
|
||||
<p>
|
||||
The mailing list is set up to prohibit large attachments. HTML mail
|
||||
and other non-ASCII forms of posting are NOT welcome.
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
doc/contacts.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
225
doc/download.html
Normal file
@@ -0,0 +1,225 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>PLIB: Downloading and Installing PLIB.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="plib_logo.png" ALT="PLIB Logo" width=256 height=245>
|
||||
<br>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<H1>
|
||||
<FONT SIZE=9>S</FONT><FONT SIZE=5>TEVE'S</FONT>
|
||||
<FONT SIZE=9>P</FONT><FONT SIZE=5>ORTABLE</FONT>
|
||||
<FONT SIZE=9>G</FONT><FONT SIZE=5>AME</FONT>
|
||||
<FONT SIZE=9>L</FONT><FONT SIZE=5>IBRARY.</FONT>
|
||||
</H1>
|
||||
</center>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't
|
||||
get much Sleep.
|
||||
<br>
|
||||
-- Woody Allen
|
||||
</ul>
|
||||
<center>
|
||||
<A href="http://sf.net">
|
||||
<IMG src="http://sf.net/sflogo.php?group_id=382&type=1" width="88" height="31" border="0" ALT="Sourceforge Logo"></A>
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD valign=top align=left>
|
||||
<A HREF="index.html"><IMG SRC="home.png" ALT="HOME" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="whats_inside.html"><IMG SRC="whats_inside.png" ALT="WHAT'S INSIDE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="license.html"><IMG SRC="license.png" ALT="LICENSE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="contacts.html"><IMG SRC="contacts.png" ALT="CONTACTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="requirements.html"><IMG SRC="requirements.png" ALT="REQUIREMENTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="gallery.html"><IMG SRC="gallery.png" ALT="GALLERY" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="download.html"><IMG SRC="download.png" ALT="DOWNLOAD & INSTALL" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="examples.html"><IMG SRC="examples.png" ALT="EXAMPLES" BORDER="0" width=150 height=50></A><br>
|
||||
|
||||
<A HREF="sg/index.html"><IMG SRC="SG.png" ALT="SG" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="ssg/index.html"><IMG SRC="SSG.png" ALT="SSG" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="ssgAux/index.html"><IMG SRC="ssgAux.png" ALT="SSGAUX" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="fnt/index.html"><IMG SRC="FNT.png" ALT="FNT" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pui/index.html"><IMG SRC="PUI.png" ALT="PUI" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="psl/index.html"><IMG SRC="PSL.png" ALT="PSL" BORDER="0" width=75 height=25></A>
|
||||
|
||||
<A HREF="util/index.html"><IMG SRC="UL.png" ALT="UL" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="js/index.html"><IMG SRC="JS.png" ALT="JS" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="net/index.html"><IMG SRC="NET.png" ALT="NET" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="sl/index.html"><IMG SRC="SL.png" ALT="SL" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pw/index.html"><IMG SRC="PW.png" ALT="PW" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="puAux/index.html"><IMG SRC="puAux.png" ALT="PUAUX" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H1>Downloading and Installing PLIB.</H1>
|
||||
<H2>The Short Answer (for Linux and CygWin users):</H2>
|
||||
Make sure you have OpenGL installed.<br>
|
||||
Download this: <A HREF="dist/plib-1.8.4.tar.gz"> PLIB - Version 1.8.4</A>
|
||||
<br>
|
||||
Run this (as 'root'):
|
||||
<pre>
|
||||
tar xzf plib-1.8.4.tar.gz
|
||||
cd plib-1.8.4
|
||||
./configure ; make install
|
||||
</pre>
|
||||
Tadaaaa!
|
||||
<p>
|
||||
<H2>The Long Answer: Downloading PLIB.</H2>
|
||||
You can get PLIB in various versions here. We follow the common Linux
|
||||
convention where the second digit in the version number is EVEN for
|
||||
stable versions and ODD for unstable and/or experimental versions.
|
||||
<p>
|
||||
End users should generally download the latest stable version but
|
||||
application developers may wish to periodically compile their code
|
||||
against the odd-numbered version so as to keep abreast of developments
|
||||
in PLIB.
|
||||
<p>
|
||||
<ul>
|
||||
<li><A HREF="dist/plib-1.8.4.tar.gz"> PLIB - Version 1.8.4 -- Current Stable</A>
|
||||
<li><A HREF="dist/"> PLIB - Other versions</A>
|
||||
<li><A HREF="http://sf.net/project/?group_id=382"> PLIB - Latest development version (from SVN)</A>
|
||||
<li><A HREF="dist/current.tgz"> PLIB - Latest development version (tarball)</A>
|
||||
</ul>
|
||||
Download this using your browser by right-clicking on the name. If you
|
||||
have InternetExplorer, you'll probably fall victim to it's stupid bug
|
||||
where it unzips the file automatically - but forgets to
|
||||
rename it to lose the '.gz' off the end. Just rename it yourself
|
||||
before you try to un-tar it and all will be well.
|
||||
<p>
|
||||
PLIB documentation, example programs, fonts, etc are separated from
|
||||
PLIB itself to minimise your download time.
|
||||
<p>
|
||||
The <b>online</b> documentation attempts to always track the latest stable
|
||||
version of PLIB. If you are using some other version, you may want to
|
||||
download the documentation appropriate to that release which comes with
|
||||
the plib_examples tarball.
|
||||
|
||||
<A NAME="EXAMPLES"></A>
|
||||
<ul>
|
||||
<li><A HREF="dist/plib_examples-1.8.4.tar.gz">
|
||||
Example programs and Documentation for PLIB-1.8.4 or later.</A>
|
||||
<li><A HREF="dist/">PLIB_examples - Older versions</A>
|
||||
</ul>
|
||||
Un-tar this into a separate directory from PLIB itself - or else
|
||||
all the configuration and makefiles will clash. Many of the example programs
|
||||
require the GLUT library (or 'freeglut') - some other use SDL and FLTK.
|
||||
<p>
|
||||
<A NAME="DEMOS"></A>
|
||||
More extensive PLIB demonstration programs are also separated from
|
||||
PLIB itself and are individually tarballed with their own version
|
||||
numbers. Generally, they'll run with the most recent stable version
|
||||
of PLIB - but occasionally they'll rely on something in the latest
|
||||
PLIB beta.
|
||||
<p>
|
||||
<ul>
|
||||
<li><A HREF="dist/exposer-0.2.0.tar.gz">
|
||||
A character animation tool.</A>
|
||||
<li><A HREF="dist/p-guide-0.0.1.tar.gz">
|
||||
A tool for designing PUI interface panels.</A>
|
||||
<li><A HREF="dist/ttt3d-0.2.0.tar.gz">
|
||||
A complete TicTacToe game - played in 3 dimensions!</A>
|
||||
<li><A HREF="dist/">PLIB Demos - Older versions</A>
|
||||
</ul>
|
||||
Un-tar these into a separate directory from PLIB itself - or else
|
||||
all the configuration and makefiles will clash.
|
||||
|
||||
<H2>The Long Answer: Installing PLIB.</H2>
|
||||
On most Linux and other UNIX-like OS's, it's simply a matter of
|
||||
unpacking the tar-ball, changing directory into the plib_x.y.z
|
||||
directory that this creates and typing:
|
||||
<pre>
|
||||
|
||||
./configure
|
||||
make install
|
||||
|
||||
</pre>
|
||||
You'll need to
|
||||
be 'root' to perform the last step. At the end of that process,
|
||||
you should have a set of header files in /usr/include/plib
|
||||
and a set of corresponding libraries in /usr/lib. There
|
||||
are some example programs in the 'plib-x.y.z/examples' subdirectory.
|
||||
<p>
|
||||
WARNING: If you are using 'Mesa' instead of an 'Official' OpenGL,
|
||||
please make sure you followed the instructions in the Mesa installation
|
||||
notes that tell you to symbolically link /usr/lib/libGL.so
|
||||
and /usr/lib/libGLU.so to their Mesa equivelents. More modern
|
||||
versions of Mesa may install directly into that location - but
|
||||
make sure that one way or another, /usr/lib/libGL.so points to your
|
||||
current OpenGL/Mesa library.
|
||||
<p>
|
||||
Some Linux distro's install OpenGL/Mesa in /usr/X11R6/lib - that
|
||||
is now officially deprecated - if your OpenGL/Mesa is installed
|
||||
there then I suggest you add symbolic links to make the
|
||||
files appear to be in /usr/lib.
|
||||
<p>
|
||||
If you are running some non-UNIX OS, (eg MS-Windows) there may be
|
||||
instructions on how to build PLIB in README.{OS name}. If you
|
||||
have problems - or can offer to streamline the
|
||||
process, then please pass on your knowledge via the mailing list.
|
||||
In general, it isn't complicated to install - you usually just have
|
||||
to compile all of the source files in each directory and link
|
||||
each subdirectory into a separate library. Don't try to make
|
||||
PLIB into a M$ '.DLL' - it's not worth the effort!
|
||||
<p>
|
||||
If you have the Microsoft Visual C++ suite, you'll find a set
|
||||
of project files - one in each source directory - plus a master
|
||||
workspace at the top of the tree.
|
||||
<p>
|
||||
If you have all the Cygnus (CygWin) compiler/tools, then use
|
||||
the UNIX build instructions.
|
||||
<p>
|
||||
There is now a README.mac for Macintosh users.
|
||||
|
||||
<H2> Where Does PLIB Install Itself? </H2>
|
||||
This is always a controversial topic. In order to maintain
|
||||
our own sanity, we expect PLIB to be installed in one place
|
||||
and in one place only.
|
||||
<pre>
|
||||
|
||||
Libraries are in: /usr/lib/libplibXXX.a
|
||||
|
||||
Headers are in: /usr/include/plib/XXX.h
|
||||
|
||||
</pre>
|
||||
(Where 'XXX' is the short acronym for the PLIB library in question -
|
||||
in lowercase).
|
||||
<p>
|
||||
The now *VERY* obsolete PLIB 1.0.* used to install itself
|
||||
into /usr/local/plib, but from version 1.1.0 onwards, the
|
||||
modern location was adopted following discussions with
|
||||
several Linux distributors.
|
||||
<p>
|
||||
Please don't even <b>think</b> about arguing about this decision,
|
||||
it has been the topic of long and arduous discussion and it's
|
||||
NEVER going to change!
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
doc/download.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
191
doc/examples.html
Normal file
@@ -0,0 +1,191 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>PLIB: A Portable Games Library.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="plib_logo.png" ALT="PLIB Logo" width=256 height=245>
|
||||
<br>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<H1>
|
||||
<FONT SIZE=9>S</FONT><FONT SIZE=5>TEVE'S</FONT>
|
||||
<FONT SIZE=9>P</FONT><FONT SIZE=5>ORTABLE</FONT>
|
||||
<FONT SIZE=9>G</FONT><FONT SIZE=5>AME</FONT>
|
||||
<FONT SIZE=9>L</FONT><FONT SIZE=5>IBRARY.</FONT>
|
||||
</H1>
|
||||
</center>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't
|
||||
get much Sleep.
|
||||
<br>
|
||||
-- Woody Allen
|
||||
</ul>
|
||||
<center>
|
||||
<A href="http://sf.net">
|
||||
<IMG src="http://sf.net/sflogo.php?group_id=382&type=1" width="88" height="31" border="0" ALT="Sourceforge Logo"></A>
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD valign=top align=left>
|
||||
<A HREF="index.html"><IMG SRC="home.png" ALT="HOME" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="whats_inside.html"><IMG SRC="whats_inside.png" ALT="WHAT'S INSIDE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="license.html"><IMG SRC="license.png" ALT="LICENSE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="contacts.html"><IMG SRC="contacts.png" ALT="CONTACTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="requirements.html"><IMG SRC="requirements.png" ALT="REQUIREMENTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="gallery.html"><IMG SRC="gallery.png" ALT="GALLERY" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="download.html"><IMG SRC="download.png" ALT="DOWNLOAD & INSTALL" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="examples.html"><IMG SRC="examples.png" ALT="EXAMPLES" BORDER="0" width=150 height=50></A><br>
|
||||
|
||||
<A HREF="sg/index.html"><IMG SRC="SG.png" ALT="SG" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="ssg/index.html"><IMG SRC="SSG.png" ALT="SSG" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="ssgAux/index.html"><IMG SRC="ssgAux.png" ALT="SSGAUX" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="fnt/index.html"><IMG SRC="FNT.png" ALT="FNT" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pui/index.html"><IMG SRC="PUI.png" ALT="PUI" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="psl/index.html"><IMG SRC="PSL.png" ALT="PSL" BORDER="0" width=75 height=25></A>
|
||||
|
||||
<A HREF="util/index.html"><IMG SRC="UL.png" ALT="UL" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="js/index.html"><IMG SRC="JS.png" ALT="JS" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="net/index.html"><IMG SRC="NET.png" ALT="NET" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="sl/index.html"><IMG SRC="SL.png" ALT="SL" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pw/index.html"><IMG SRC="PW.png" ALT="PW" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="puAux/index.html"><IMG SRC="puAux.png" ALT="PUAUX" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
|
||||
<H1>PLIB: Example Programs and Demonstrations.</H1>
|
||||
|
||||
PLIB has three sources of sample programs to learn from.
|
||||
<ul>
|
||||
<li> EXAMPLES: There is a bundle of small programs that each show
|
||||
off one or two small aspects of PLIB and which are
|
||||
not generally all that useful by themselves.
|
||||
<li> DEMOS: These are fully worked out demonstration programs
|
||||
that use a wide range of PLIB features to create complete
|
||||
and useful programs that are still small enough to understand
|
||||
quite easily.
|
||||
<li> APPLICATIONS: Because many PLIB applications are OpenSourced,
|
||||
there are a large number of complex programs that you can
|
||||
look at to see how large games, simulations and interactive
|
||||
tools can be built using this technology.
|
||||
</ul>
|
||||
|
||||
<H2> EXAMPLES </H2>
|
||||
|
||||
The PLIB example programs are distributed in <A HREF="download.html#EXAMPLES">
|
||||
a separate tarball</A> from the main PLIB distribution - and generally, it
|
||||
is updated less often - but following the same version numbers as the
|
||||
main PLIB library.
|
||||
<p>
|
||||
When you install that package, you'll see that the 'src' directory is
|
||||
split into sections for each PLIB component library - with one or two
|
||||
different examples for each library.
|
||||
<p>
|
||||
All of the examples are licensed under GPL as bundle and are maintained
|
||||
under the PLIB SVN archive.
|
||||
<ul>
|
||||
<li>FNT:<ul>
|
||||
<li> fnt_test - a basic TXF font browser.
|
||||
<li> slideshow - a way to present a simple slide-show driven
|
||||
from an ASCII text file. Who needs PowerPoint
|
||||
when you have 'vi'? :-)
|
||||
<li> data - this directory contains 20 different TXF fonts.
|
||||
</ul>
|
||||
<li>JS:<ul>
|
||||
<li> js_demo - a program that shows the current output from
|
||||
whatever joysticks it can detect. Useful for
|
||||
testing out which buttons set which bits and
|
||||
which axes are which.
|
||||
</ul>
|
||||
<li>NET:<ul>
|
||||
<li> client-server -
|
||||
<li> http_get -
|
||||
<li> net_echo -
|
||||
</ul>
|
||||
<li>PUI:<ul>
|
||||
<li> simple - the "Hello World" of PUI programs.
|
||||
<li> complex - a fairly pointless program that shows how
|
||||
to control a spinning OpenGL cube, and use
|
||||
a variety of PUI widgets.
|
||||
<li> widget_list - draws every kind of PUI widget each
|
||||
in a separate window. This is what we used
|
||||
to make the screenshots for the PUI manual.
|
||||
</ul>
|
||||
<li>SG:<ul>
|
||||
<li> sg_quat_test - tests the SG quaternions...unsuccessfully
|
||||
I think!
|
||||
</ul>
|
||||
<li>SL:<ul>
|
||||
<li> example - plays a number of annoying sounds.
|
||||
<li> mod_demo - plays a MOD format music file.
|
||||
</ul>
|
||||
<li>SSG:<ul>
|
||||
<li> load_save - Load a 3D model - then just save it again.
|
||||
<li> majik - A test (originally written to help the Majik3D
|
||||
project) that shows Tux walking around on some
|
||||
auto-generated terrain.
|
||||
<li> state_test - Exercises some ssgSimpleState settings.
|
||||
<li> tux - A model of Tux the Penguin spins around on a
|
||||
pedestal encrusted in golden Herring.
|
||||
<li> tween_test - Demonstrated the 'tween' effect.
|
||||
<li> water - Demonstrates the ssgAux library - water/fire/lensflare/particles plus basic shapes, cube, teapot.
|
||||
<li> viewer - A program to allow you to view any 3D model
|
||||
and spin it around using the mouse.
|
||||
</ul>
|
||||
<li>UTIL:<ul>
|
||||
<li> test_dir - tests some of the directory handling features.
|
||||
</ul>
|
||||
</ul>
|
||||
<H2> DEMONSTRATIONS </H2>
|
||||
|
||||
The PLIB demonstration programs are distributed in <A HREF="download.html#DEMOS">
|
||||
their own separate tarballs</A> - each has it's own version number and it's
|
||||
own license conditions (although all of them must fall within the SourceForge
|
||||
definition for OpenSourced software in order to reside on the SourceForge
|
||||
server). All of the demonstrations are maintained under the PLIB SVN
|
||||
archive.
|
||||
|
||||
<ul>
|
||||
<li> ExPoser - A program to allow you to animate characters for your
|
||||
games using 'Skin and Bones' animation techniques.
|
||||
ExPoser needs PLIB 1.5.1 or later.
|
||||
<li> TTT3D - A complete 3D TicTacToe game played on a 4x4x4 board.
|
||||
It's theoretically possible to beat it - <b>theoretically</b>.
|
||||
TTT3D needs PLIB 1.4.0 or later.
|
||||
</ul>
|
||||
|
||||
<H2> APPLICATIONS </H2>
|
||||
|
||||
PLIB applications do not reside on the PLIB web site - but you can find
|
||||
links to many of them in <A HREF="gallery.html">our image gallery</A>.
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
doc/examples.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
doc/fgfs.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
385
doc/fnt/index.html
Normal file
@@ -0,0 +1,385 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="keywords" content="FNT, PLIB, OpenGL, font, library, portable, rendering, text, texture, map, glyph, TXF">
|
||||
<META name="description" content="The PLIB FNT Library allows you to produce text using texture maps instead of bitmaps because the latter are typically very slow on consumer-grade 3D hardware.">
|
||||
<TITLE>A Font Library for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<H1>A Font Library for OpenGL</H1>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>
|
||||
by Steve Baker
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H2>Introduction</H2>
|
||||
The FNT library was originally written to allow PUI programs to
|
||||
produce text using texture maps instead of bitmaps because the
|
||||
latter are typically very slow on consumer-grade 3D hardware.
|
||||
<H2>An Example.</H2>
|
||||
This example program is probably all you need in the
|
||||
way of documentation - so it's the first thing we'll talk
|
||||
about:
|
||||
<pre>
|
||||
|
||||
/* Declarations */
|
||||
|
||||
fntRenderer texout ;
|
||||
|
||||
/* Load some fonts */
|
||||
|
||||
fntTexFont TimesRoman ( "times_roman.txf" ) ;
|
||||
fntTexFont Courier ( "courier.txf" ) ;
|
||||
|
||||
/* Select a font and pointsize to render with... */
|
||||
|
||||
texout . setFont ( & TimesRoman ) ;
|
||||
texout . setPointSize ( 24 ) ;
|
||||
|
||||
/* Print "Hello" and "World" */
|
||||
|
||||
texout . begin () ;
|
||||
texout . start2f ( 50.0f, 80.0f ) ;
|
||||
texout . puts ( "Hello" ) ;
|
||||
texout . start2f ( 50.0f, 50.0f ) ;
|
||||
texout . puts ( "World" ) ;
|
||||
texout . end () ;
|
||||
|
||||
</pre>
|
||||
<H2>fntInit</H2>
|
||||
All programs that use the FNT library should call 'fntInit()' sometime
|
||||
after they have established a valid OpenGL rendering context and
|
||||
before they make any other FNT library calls.
|
||||
|
||||
<H2>The Classes</H2>
|
||||
There are three external classes used in FNT:
|
||||
<pre>
|
||||
|
||||
class fntFont -- An abstract base class from which all
|
||||
kinds of font representations could be
|
||||
derived.
|
||||
class fntTexFont -- A fntFont that uses texture mapping.
|
||||
class fntRenderer -- A class that draws text using a fntFont.
|
||||
|
||||
</pre>
|
||||
<H3>class fntFont</H3>
|
||||
Classes derived from the <code>fntFont</code> class all describe fonts.
|
||||
This is an abstract base class from which <code>fntTexFont</code> is derived.
|
||||
Other <code>fntFont</code> sub-classes could also be derived in the future.
|
||||
(This means that you cannot declare a fntFont - but all classes derived
|
||||
from fntFont will obey this description.)
|
||||
<p>
|
||||
This class appears quite complex since constructing and/or
|
||||
querying the contents of a texture font is a complicated
|
||||
business - and consequently, there is a lot of API to
|
||||
support your ability to do that. Fortunately, most FNT
|
||||
applications will just load a font from disk and use
|
||||
<code>fntFont::begin()</code>/
|
||||
<code>fntFont::puts()</code>/
|
||||
<code>fntFont::end()</code>
|
||||
functionality.
|
||||
<pre>
|
||||
|
||||
class fntFont
|
||||
{
|
||||
public:
|
||||
fntFont () ;
|
||||
~fntFont () ;
|
||||
void putch ( sgVec3 curpos, float pointsize, float slant, char c ) ;
|
||||
void puts ( sgVec3 curpos, float pointsize, float slant, char *s ) ;
|
||||
void begin () ;
|
||||
void end () ;
|
||||
void getBBox ( char *s, float pointsize, float slant,
|
||||
float *left, float *right,
|
||||
float *bot , float *top ) ;
|
||||
|
||||
int load ( char *fname, GLenum mag = GL_NEAREST,
|
||||
GLenum min = GL_LINEAR_MIPMAP_LINEAR ) ;
|
||||
|
||||
void setFixedPitch ( int fix ) ;
|
||||
int isFixedPitch () ;
|
||||
|
||||
void setWidth ( float w ) ;
|
||||
void setGap ( float g ) ;
|
||||
|
||||
float getWidth () ;
|
||||
float getGap () ;
|
||||
|
||||
int hasGlyph ( char c ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
<code>fntFont::getBBox()</code> returns the top, bottom, left and
|
||||
right extents (in OpenGL units) of the string 's' if it were drawn at the
|
||||
specified pointsize and slant. This routine knows how to deal with
|
||||
newline characters.
|
||||
<p>
|
||||
<code>fntFont::putch()</code> draws the character 'c' at the
|
||||
cursor position specified be 'curpos' (with the specified pointsize and slant)
|
||||
and advances the cursor
|
||||
to the right hand edge of the character it just rendered.
|
||||
<p>
|
||||
<code>fntFont::puts()</code> draws the entire string 's' at the
|
||||
cursor position specified be 'curpos'
|
||||
(with the specified pointsize and slant) and advances the cursor
|
||||
to the right hand edge of the last character it rendered.
|
||||
<p>
|
||||
Both putch and puts will automatically switch the case of letters
|
||||
from upper to lower or vice versa if the required character is
|
||||
not present in the font but the letter with the reverse case
|
||||
is present. Other missing characters will simply generate no
|
||||
output and won't update the cursor position. If a space character
|
||||
is not defined in the font, then a half-pointsize gap will be
|
||||
generated instead.
|
||||
<p>
|
||||
puts (but NOT putch) knows how to deal with newline characters,
|
||||
it drops the text down to the next line - leaving a one-third
|
||||
pointsize gap between lines.
|
||||
<p>
|
||||
<code>fntFont::begin()/end()</code> since redundant mode changes are
|
||||
costly in OpenGL, applications may optionally call <code>fntFont::begin()</code>
|
||||
before rendering some text using a specified font and call <code>fntFont::end()</code>
|
||||
at the end. Just like a <code>glBegin()</code>/<code>glEnd()</code> pair,
|
||||
there are some fairly restrictive rules about what you can do between
|
||||
a <code>fntFont::begin()</code> and a <code>fntFont::end()</code>:
|
||||
<ul>
|
||||
<li>The only OpenGL calls that are permitted are those that
|
||||
are allowed between a <code>glBegin()</code>/<code>glEnd()</code>.
|
||||
<li>You may not make calls to other member functions of other
|
||||
<code>fntFont</code> objects or to <code>fntRenderer</code> objects.
|
||||
<li>You may not call <code>fntFont::begin()</code> between another
|
||||
<code>fntFont::begin()</code>/<code>fntFont::end()</code> pair.
|
||||
</ul>
|
||||
<p>
|
||||
You may call <code>fntFont::putch()</code> and/or
|
||||
<code>fntFont::puts()</code> without
|
||||
entering a <code>fntFont::begin()</code>/<code>fntFont::end()</code>
|
||||
state - but if you do that, each call will result in
|
||||
OpenGL state switching - which may well be redundant.
|
||||
<p>
|
||||
<code>int load ( char *filename )</code> loads a font from disk,
|
||||
returns TRUE on success, FALSE for failure.
|
||||
<p>
|
||||
<code>int load ( char *filename, GLenum mag = GL_NEAREST,
|
||||
GLenum min = GL_LINEAR_MIPMAP_LINEAR )</code>...you can optionally
|
||||
specify the OpenGL texture magnification and minification filters
|
||||
- this is sometimes necessary to get the clearest possible text
|
||||
at certain point sizes. Experiment!
|
||||
<p>
|
||||
<code>void setFixedPitch ( int fixed )</code> if 'fixed' is TRUE, forces
|
||||
the font to be fixed-pitch (so each letter or 'Glyph' is a standard width),
|
||||
if 'fixed' is false then variable character widths are possible.
|
||||
<p>
|
||||
<code>void setWidth ( float w )</code> For a fixed width font, this
|
||||
sets the width of each character. If the actual characters are wider
|
||||
than this, they will overlap, if they are narrower then there will be
|
||||
a gap.
|
||||
<p>
|
||||
<code>void setGap ( float g )</code> Set the gap between letters, can be
|
||||
negative or positive.
|
||||
<p>
|
||||
The following routines allow you to query the font's setup:
|
||||
<pre>
|
||||
|
||||
int isFixedPitch ()
|
||||
float getWidth ()
|
||||
float getGap ()
|
||||
|
||||
</pre>
|
||||
<code>int hasGlyph()</code> returns TRUE if the font contains a
|
||||
glyph (graphic image) for a given ASCII character, FALSE otherwise.
|
||||
Fonts that have only uppercase (or only lowercase) letters will still
|
||||
return TRUE for corresponding characters of the opposite case because
|
||||
the putch and puts routines will automatically case-convert in that
|
||||
case.
|
||||
<H3>class fntTexFont</H3>
|
||||
<code>fntTexFont</code> is inherited from <code>fntFont</code>.
|
||||
All functions of a fntFont are implemented in fntTextFont using
|
||||
a texture map.
|
||||
<pre>
|
||||
|
||||
class fntTexFont
|
||||
{
|
||||
public:
|
||||
fntTexFont () ;
|
||||
fntTexFont ( char *fname,
|
||||
GLenum mag = GL_NEAREST,
|
||||
GLenum min = GL_LINEAR_MIPMAP_LINEAR ) ;
|
||||
~fntTexFont () ;
|
||||
void putch ( sgVec3 curpos, float pointsize, float slant, char c ) ;
|
||||
void puts ( sgVec3 curpos, float pointsize, float slant, char *s ) ;
|
||||
void begin () ;
|
||||
void end () ;
|
||||
void getBBox ( char *s, float pointsize, float slant,
|
||||
float *left, float *right,
|
||||
float *bot , float *top ) ;
|
||||
|
||||
int load ( char *fname,
|
||||
GLenum mag = GL_NEAREST,
|
||||
GLenum min = GL_LINEAR_MIPMAP_LINEAR ) ;
|
||||
|
||||
void setFixedPitch ( int fix ) ;
|
||||
int isFixedPitch () ;
|
||||
|
||||
void setWidth ( float w ) ;
|
||||
void setGap ( float g ) ;
|
||||
|
||||
float getWidth () ;
|
||||
float getGap () ;
|
||||
|
||||
void setGlyph ( char c,
|
||||
float tex_left, float tex_right,
|
||||
float tex_bot , float tex_top ,
|
||||
float vtx_left, float vtx_right,
|
||||
float vtx_bot , float vtx_top ) ;
|
||||
|
||||
int getGlyph ( char c,
|
||||
float *tex_left = NULL, float *tex_right = NULL,
|
||||
float *tex_bot = NULL, float *tex_top = NULL,
|
||||
float *vtx_left = NULL, float *vtx_right = NULL,
|
||||
float *vtx_bot = NULL, float *vtx_top = NULL) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
<code>int load ( char *filename )</code> loads a font from disk
|
||||
using the extension of the filename to determine what format it is
|
||||
stored in. Currently, the only supported format is Mark Kilgards 'texfont'
|
||||
format - which has the '.txf' filename extension. Returns TRUE for
|
||||
success, FALSE for failure.
|
||||
Details of the TXF file format can be found in
|
||||
<A HREF="http://www.opengl.org/resources/code/rendering/mjktips/TexFont/TexFont.html">
|
||||
Marks's document about Textured Fonts</A>
|
||||
<p>
|
||||
Just as with all fntFont derived classes, you can optionally specify
|
||||
the OpenGL texture filter options for the loaded texture.
|
||||
<p>
|
||||
Each font is made up of zero or more 'Glyphs' (character shapes) packed
|
||||
into a single texture map. If you didn't use 'load' to load the font
|
||||
from disk, you'll have to define where each one lies on the map and
|
||||
how big the quadrilateral it is to be drawn on is:
|
||||
<pre>
|
||||
|
||||
void setGlyph ( char c,
|
||||
float tex_left, float tex_right,
|
||||
float tex_bot , float tex_top ,
|
||||
float vtx_left, float vtx_right,
|
||||
float vtx_bot , float vtx_top ) ;
|
||||
|
||||
</pre>
|
||||
Where 'c' is the character we are defining, 'tex_*' is the
|
||||
left, right, top and bottom of the image of that character
|
||||
in the texture map. Since texture coordinates are in the
|
||||
range 0..1, these will typically be quite small numbers.
|
||||
'vtx_*' is the left, right, top and bottom of the character's
|
||||
rectangle in a coordinate system that has (0,0) at the
|
||||
baseline of the character cell, and (1,1) at the top-right
|
||||
corner of the tallest, widest character in the font. Hence,
|
||||
a lower-case 'y' would have a negative 'vtx_bot'.
|
||||
<p>
|
||||
You can also query all this information:
|
||||
<pre>
|
||||
|
||||
int getGlyph ( char c,
|
||||
float *tex_left, float *tex_right,
|
||||
float *tex_bot , float *tex_top ,
|
||||
float *vtx_left, float *vtx_right,
|
||||
float *vtx_bot , float *vtx_top ) ;
|
||||
|
||||
</pre>
|
||||
<code>fntFont::getGlyph()</code> returns TRUE if the character has
|
||||
been defined in this font, FALSE otherwise.
|
||||
<H3>class fntRenderer</H3>
|
||||
This class is the one most people are going to be using
|
||||
to render text in FNT. Most applications will declare
|
||||
a single <code>fntRenderer</code> class for all their text needs.
|
||||
<pre>
|
||||
|
||||
class fntRenderer
|
||||
{
|
||||
public:
|
||||
fntRenderer ()
|
||||
|
||||
void start3fv ( sgVec3 pos ) ;
|
||||
void start2fv ( sgVec2 pos ) ;
|
||||
void start2f ( float x, float y ) ;
|
||||
void start3f ( float x, float y, float z ) ;
|
||||
|
||||
void getCursor ( float *x, float *y, float *z )
|
||||
|
||||
fntFont *getFont () ;
|
||||
void setFont ( fntFont *f ) ;
|
||||
|
||||
void begin () ;
|
||||
void end () ;
|
||||
|
||||
void putch ( char c ) ;
|
||||
void puts ( char *s ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
<code>fntRenderer::setFont()</code> is used to tell the renderer which
|
||||
font is current. <code>fntRenderer::getFont()</code> lets you find out
|
||||
which font it is. You may not call <code>fntRenderer::setFont()</code>
|
||||
between a <code>fntRenderer::begin()</code> and <code>fntRenderer::end()</code>
|
||||
pair.
|
||||
<p>
|
||||
By default, uppercase characters of all fonts are one OpenGL unit high.
|
||||
You can make characters larger or smaller by setting
|
||||
<code>fntRenderer::setPointSize()</code>. You can also slant the characters
|
||||
to form italic or oublique fonts using <code>fntRenderer::setSlant()</code>.
|
||||
(The slant measures by how many OpenGL units the tops of uppercase
|
||||
characters are sloped to the right). You can call either setPointSize or
|
||||
setSlant between <code>fntRenderer::begin()</code> and
|
||||
<code>fntRenderer::end()</code>.
|
||||
<p>
|
||||
The various kinds of <code>fntRendered::start*()</code> calls are
|
||||
akin to the OpenGL <code>glVertex*</code> commands and they determine where
|
||||
the next chunk of text will be drawn. Since this coordinate is
|
||||
updated as text is drawn, you'll need to call
|
||||
<code>fntRenderer::getCursor()</code> to
|
||||
find out where the next chunk of text will be drawn. You can
|
||||
call <code>fntRenderer::start*()</code>,
|
||||
<code>fntRenderer::putch()</code> and
|
||||
<code>fntRenderer::puts()</code> between
|
||||
<code>fntRenderer::begin()</code>/<code>fntRenderer::end()</code>
|
||||
calls.
|
||||
<H2>Making New TXF Fonts.</H2>
|
||||
The '.txf' font format was designed by Mark Kilgard - who
|
||||
also produced some tools for dealing with them.
|
||||
<p>
|
||||
Check <A HREF="http://www.opengl.org/resources/code/rendering/mjktips/TexFont/TexFont.html">
|
||||
|
||||
Marks's document about Textured Fonts</A> for further information.
|
||||
Of particular interest is Mark's "gentexfont" program that can
|
||||
create a TXF format font from an X-windows font.
|
||||
<p>
|
||||
You can find out which X-fonts are stored on your machine using
|
||||
the <code>/usr/X11/bin/xlsfonts</code> program.
|
||||
<p>
|
||||
There are over a dozen sample TXF fonts stored
|
||||
in <code>examples/src/fnt/data</code>.
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
188
doc/gallery.html
Normal file
@@ -0,0 +1,188 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>PLIB: Gallery.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="plib_logo.png" ALT="PLIB Logo" width=256 height=245>
|
||||
<br>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<H1>
|
||||
<FONT SIZE=9>S</FONT><FONT SIZE=5>TEVE'S</FONT>
|
||||
<FONT SIZE=9>P</FONT><FONT SIZE=5>ORTABLE</FONT>
|
||||
<FONT SIZE=9>G</FONT><FONT SIZE=5>AME</FONT>
|
||||
<FONT SIZE=9>L</FONT><FONT SIZE=5>IBRARY.</FONT>
|
||||
</H1>
|
||||
</center>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't
|
||||
get much Sleep.
|
||||
<br>
|
||||
-- Woody Allen
|
||||
</ul>
|
||||
<center>
|
||||
<A href="http://sf.net">
|
||||
<IMG src="http://sf.net/sflogo.php?group_id=382&type=1" width="88" height="31" border="0" ALT="Sourceforge Logo"></A>
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD valign=top align=left>
|
||||
<A HREF="index.html"><IMG SRC="home.png" ALT="HOME" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="whats_inside.html"><IMG SRC="whats_inside.png" ALT="WHAT'S INSIDE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="license.html"><IMG SRC="license.png" ALT="LICENSE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="contacts.html"><IMG SRC="contacts.png" ALT="CONTACTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="requirements.html"><IMG SRC="requirements.png" ALT="REQUIREMENTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="gallery.html"><IMG SRC="gallery.png" ALT="GALLERY" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="download.html"><IMG SRC="download.png" ALT="DOWNLOAD & INSTALL" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="examples.html"><IMG SRC="examples.png" ALT="EXAMPLES" BORDER="0" width=150 height=50></A><br>
|
||||
|
||||
<A HREF="sg/index.html"><IMG SRC="SG.png" ALT="SG" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="ssg/index.html"><IMG SRC="SSG.png" ALT="SSG" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="ssgAux/index.html"><IMG SRC="ssgAux.png" ALT="SSGAUX" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="fnt/index.html"><IMG SRC="FNT.png" ALT="FNT" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pui/index.html"><IMG SRC="PUI.png" ALT="PUI" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="psl/index.html"><IMG SRC="PSL.png" ALT="PSL" BORDER="0" width=75 height=25></A>
|
||||
|
||||
<A HREF="util/index.html"><IMG SRC="UL.png" ALT="UL" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="js/index.html"><IMG SRC="JS.png" ALT="JS" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="net/index.html"><IMG SRC="NET.png" ALT="NET" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="sl/index.html"><IMG SRC="SL.png" ALT="SL" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pw/index.html"><IMG SRC="PW.png" ALT="PW" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="puAux/index.html"><IMG SRC="puAux.png" ALT="PUAUX" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H1>ScreenShot Gallery.</H1>
|
||||
These images come from a wide variety of PLIB applications - some OpenSourced,
|
||||
some commercial. Click on the thumbnail image for more detail and links to further
|
||||
information.
|
||||
<TABLE>
|
||||
<TR><TD>
|
||||
<H2>The FlightGear Flight Simulator.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/fgfs.html">
|
||||
<IMG WIDTH=270 HEIGHT=183 SRC="http://plib.sourceforge.net/gallery/fgfs_small.png" BORDER="0" ALT="FlightGear"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>The Chronicles of the Evil Overlord.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/evilo.html">
|
||||
<IMG WIDTH=280 HEIGHT=219 SRC="http://plib.sourceforge.net/gallery/evilo_thumbnail.png" BORDER="0" ALT="Chronicles of the Evil Overlord"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>The ExPoser Animation Tool.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/exposer.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/exposer_thumbnail.png" BORDER="0" ALT="ExPoser"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>HardBall.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/hardball.html">
|
||||
<IMG WIDTH=280 HEIGHT=225 SRC="http://plib.sourceforge.net/gallery/hardball_thumbnail.png" BORDER="0" ALT="HardBall"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>MOTE.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/mote.html">
|
||||
<IMG WIDTH=280 HEIGHT=202 SRC="http://plib.sourceforge.net/gallery/mote_thumbnail.png" BORDER="0" ALT="MOTE"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>The PrettyPoly Modeller.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/prettypoly.html">
|
||||
<IMG WIDTH=280 HEIGHT=234 SRC="http://plib.sourceforge.net/gallery/prettypoly_thumbnail.png" BORDER="0" ALT="PrettyPoly Modeller"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>TicTacToe 3D.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/ttt3d.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/ttt3d_thumbnail.png" BORDER="0" ALT="TicTacToe 3D"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>TORCS Car Racing Simulator.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/torcs.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/torcs_thumbnail.png" BORDER="0" ALT="TORCS"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>Tuxedo T. Penguin - A Quest for Herring.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/tuxaqfh.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/tuxaqfh_thumbnail.png" BORDER="0" ALT="A Quest for Herring"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>TuxKart.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/tuxkart.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/tuxkart_thumbnail.png" BORDER="0" ALT="TuxKart"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>TuxFleet.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/tuxfleet.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/tuxfleet_thumbnail.png" BORDER="0" ALT="TuxFleet"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>Wizz.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/wizz.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/wizz_thumbnail.png" BORDER="0" ALT="Wizz"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>Atlas Map Maker.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/atlas.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/atlas_thumbnail.png" BORDER="0" ALT="Atlas Map Maker"></A><br>
|
||||
</TD></TR>
|
||||
<TR><TD>
|
||||
<H2>Flight Dynamics Simulator.</H2>
|
||||
</TD>
|
||||
<TD>
|
||||
<A HREF="http://plib.sourceforge.net/gallery/FDS.html">
|
||||
<IMG WIDTH=280 HEIGHT=210 SRC="http://plib.sourceforge.net/gallery/FDS_thumbnail.png" BORDER="0" ALT="Flight Dynamics Simulator"></A><br>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
doc/gallery.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
doc/home.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
203
doc/index.html
Normal file
@@ -0,0 +1,203 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>PLIB: A Portable Games Library.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="plib_logo.png" ALT="PLIB Logo" width=256 height=245>
|
||||
<br>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<H1>
|
||||
<FONT SIZE=9>S</FONT><FONT SIZE=5>TEVE'S</FONT>
|
||||
<FONT SIZE=9>P</FONT><FONT SIZE=5>ORTABLE</FONT>
|
||||
<FONT SIZE=9>G</FONT><FONT SIZE=5>AME</FONT>
|
||||
<FONT SIZE=9>L</FONT><FONT SIZE=5>IBRARY.</FONT>
|
||||
</H1>
|
||||
</center>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't
|
||||
get much Sleep.
|
||||
<br>
|
||||
-- Woody Allen
|
||||
</ul>
|
||||
<center>
|
||||
<A href="http://sf.net">
|
||||
<IMG src="http://sf.net/sflogo.php?group_id=382&type=1" width="88" height="31" border="0" ALT="Sourceforge Logo"></A>
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD valign=top align=left>
|
||||
<A HREF="index.html"><IMG SRC="home.png" ALT="HOME" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="whats_inside.html"><IMG SRC="whats_inside.png" ALT="WHAT'S INSIDE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="license.html"><IMG SRC="license.png" ALT="LICENSE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="contacts.html"><IMG SRC="contacts.png" ALT="CONTACTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="requirements.html"><IMG SRC="requirements.png" ALT="REQUIREMENTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="gallery.html"><IMG SRC="gallery.png" ALT="GALLERY" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="download.html"><IMG SRC="download.png" ALT="DOWNLOAD & INSTALL" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="examples.html"><IMG SRC="examples.png" ALT="EXAMPLES" BORDER="0" width=150 height=50></A><br>
|
||||
|
||||
<A HREF="sg/index.html"><IMG SRC="SG.png" ALT="SG" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="ssg/index.html"><IMG SRC="SSG.png" ALT="SSG" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="ssgAux/index.html"><IMG SRC="ssgAux.png" ALT="SSGAUX" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="fnt/index.html"><IMG SRC="FNT.png" ALT="FNT" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pui/index.html"><IMG SRC="PUI.png" ALT="PUI" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="psl/index.html"><IMG SRC="PSL.png" ALT="PSL" BORDER="0" width=75 height=25></A>
|
||||
|
||||
<A HREF="util/index.html"><IMG SRC="UL.png" ALT="UL" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="js/index.html"><IMG SRC="JS.png" ALT="JS" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="net/index.html"><IMG SRC="NET.png" ALT="NET" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="sl/index.html"><IMG SRC="SL.png" ALT="SL" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pw/index.html"><IMG SRC="PW.png" ALT="PW" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="puAux/index.html"><IMG SRC="puAux.png" ALT="PUAUX" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
|
||||
<H1>PLIB: A Suite of Portable Game Libraries.</H1>
|
||||
I (and an ever increasing band of helpers) have been spending
|
||||
time to build a set of OpenSource (LGPL) libraries that will
|
||||
permit programmers to write games and other realtime interactive
|
||||
applications that are 100% portable across a wide range of hardware and
|
||||
operating systems.
|
||||
|
||||
<p>
|
||||
PLIB includes sound effects, music, a complete 3D engine, font
|
||||
rendering, a simple Windowing library, a game scripting language,
|
||||
a GUI, networking, 3D math library and a
|
||||
collection of handy utility functions. All are 100% portable
|
||||
across nearly all modern computing platforms. What's more, it's
|
||||
all available on line - and completely free. Each library component
|
||||
is fairly independent of the others - so if you want to use SDL,
|
||||
GTK, GLUT, or FLTK instead of PLIB's 'PW' windowing library, you can.
|
||||
<p>
|
||||
The latest stable version of PLIB is 1.8.4 - go to the
|
||||
<A HREF="download.html">DOWNLOAD</A> section to get a
|
||||
copy - go to the <A HREF="whats_inside.html">WHAT'S INSIDE</A>
|
||||
section for documentation and a more detailed description of
|
||||
what PLIB contains.
|
||||
|
||||
<p>
|
||||
If you are looking at other games libraries (and there are a LOT
|
||||
to choose from) - ask yourself how many games have been written
|
||||
for that library by people outside the group that wrote it. That
|
||||
is the acid test of usability and PLIB passes with flying colours.
|
||||
|
||||
<p>
|
||||
PLIB is used by many projects (not all games - and not all
|
||||
OpenSourced), here are some of the more prominent ones - there
|
||||
are at least a hundred others:
|
||||
<center>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD><center><A HREF="http://tuxaqfh.sf.net">
|
||||
<IMG BORDER=0 SRC="tux_aqfh.png" ALT="Tux_AQFH Logo" width=99 height=77></A><br>
|
||||
<A HREF="http://tuxaqfh.sf.net">Tux the Penguin -
|
||||
<br>A Quest for herring.</A></center></TD>
|
||||
|
||||
<TD><center><A HREF="http://tuxkart.sf.net">TuxKart</A><br>
|
||||
<A HREF="http://tuxkart.sf.net">
|
||||
<IMG BORDER=0 SRC="tuxkart_logo.png" ALT="TuxKart Logo" width=101 height=78></A></center></TD>
|
||||
|
||||
<TD><center><A HREF="http://www.flightgear.org">
|
||||
<IMG BORDER=0 SRC="fgfs.png" ALT="FlightGear Logo" width=111 height=58></A><br>
|
||||
<A HREF="http://www.flightgear.org">FlightGear</A></center></TD>
|
||||
|
||||
<TD><center><A HREF="http://www.majik3d.org">Majik3D</A><br>
|
||||
<A HREF="http://www.majik3d.org">
|
||||
<IMG BORDER=0 SRC="majik3d.png" ALT="Majik3D Logo" width=83 height=80></A></center></TD>
|
||||
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><center><A HREF="http://prettypoly.sf.net">
|
||||
<IMG BORDER=0 SRC="ppe_logo_1.png" ALT="PrettyPoly Logo" width=98 height=54></A><br>
|
||||
<A HREF="http://prettypoly.sf.net">
|
||||
PrettyPoly Editor</A></center></TD>
|
||||
|
||||
<TD><center><A HREF="http://tuxfleet.sf.net">TuxFleet</A><br>
|
||||
<A HREF="http://tuxfleet.sf.net">
|
||||
<IMG BORDER=0 SRC="tuxfleet_logo.png" ALT="TuxFleet Logo" width=92 height=72></A></center></TD>
|
||||
|
||||
<TD><center><A HREF="http://www.torcs.org">TORCS</A><br>
|
||||
<A HREF="http://www.torcs.org">
|
||||
<IMG BORDER=0 SRC="torcs_logo.png" ALT="TORCS Logo" width=100 height=84></A></center></TD>
|
||||
|
||||
<TD><center><A HREF="http://www.minigolfmaniacs.com">
|
||||
<IMG BORDER=0 SRC="MinigolfManiacs.png" ALT="Minigolf Maniacs Logo" width=120 height=47></A><br>
|
||||
<A HREF="http://www.minigolfmaniacs.com">
|
||||
Minigolf Maniacs</A></center></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</center>
|
||||
<center>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD><center><A HREF="http://www.flight-dynamic-simulator.de">
|
||||
<IMG BORDER=0 SRC="FDS_logo.png" ALT="FDS Logo" width=110 height=90></A><br>
|
||||
<A HREF="http://www.flight-dynamic-simulator.de">
|
||||
Flight Dynamics Simulator</A></center></TD>
|
||||
|
||||
<TD><center><A HREF="http://mote-project.org">
|
||||
<IMG BORDER=0 SRC="mote.png" ALT="MOTE Logo" width=123 height=33></A><br>
|
||||
<A HREF="http://mote-project.org">
|
||||
MOTE</A></center></TD>
|
||||
|
||||
<TD><center>
|
||||
<A HREF="http://www.spacething.org">
|
||||
<IMG BORDER=0 SRC="spacething-small.png" ALT="Spacething Logo" width=200 height=33></A><br>
|
||||
<A HREF="http://www.spacething.org">Spacething</A></center></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</center>
|
||||
<p>
|
||||
Unlike the many similar libraries, PLIB is easy to learn and
|
||||
use - and has an object-oriented C++ interface. It's built
|
||||
as a set of component libraries that you can pick and choose
|
||||
between if (for example) you don't want to use PLIB's GUI but
|
||||
you do want to use it's scene graph API.
|
||||
|
||||
<p>
|
||||
|
||||
If you are reading this document from the source distribution on
|
||||
your local disk, you can find the most up to date version of PLIB
|
||||
here:
|
||||
<ul>
|
||||
<A HREF="http://plib.sf.net">
|
||||
http://plib.sf.net</A>
|
||||
</ul>
|
||||
PLIB's web presence is currently hosted on SourceForge (with thanks to
|
||||
VA Linux Inc for providing this free service), and the
|
||||
project summary page is here:
|
||||
<ul>
|
||||
<A HREF="http://sf.net/projects/plib">
|
||||
http://sf.net/projects/plib</A>
|
||||
</ul>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
187
doc/js/index.html
Normal file
@@ -0,0 +1,187 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="keywords" content="JS, PLIB, OpenGL, joystick, library, portable, interface, games, Baker, Steve, jsJoystick">
|
||||
<META name="description" content="The PLIB Joystick Library (JS) is a portable interface that has no inherent restrictions over the number and type of joysticks it supports. It is a wrapper to make the various underlying OS mechanisms look the same to application code.">
|
||||
<TITLE>A Joystick Library.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<H1>A Joystick Library.</H1>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>
|
||||
by Steve Baker
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H2>Introduction</H2>
|
||||
JS is now just one component of <A HREF="../index.html">PLIB</A>.
|
||||
<p>
|
||||
This Joystick Library (JS) is a portable interface that
|
||||
has no inherent restrictions over the number and type
|
||||
of joysticks it supports - although in actuality, most
|
||||
implementations will simply sit on top of an underlying
|
||||
driver provided by the Operating System.
|
||||
<p>
|
||||
You should include the JS header file '/usr/include/plib/js.h'
|
||||
and link to the JS library '/usr/lib/libjs.a'.
|
||||
<p>
|
||||
Before using any JS functions, you should initialise the
|
||||
library by calling:
|
||||
<pre>
|
||||
|
||||
jsInit () ;
|
||||
|
||||
</pre>
|
||||
JS is essentially just a wrapper to make the various
|
||||
underlying OS mechanisms look the same to application code.
|
||||
<pre>
|
||||
|
||||
class jsJoystick
|
||||
{
|
||||
jsJoystick ( int id = 0 ) ;
|
||||
~jsJoystick () ;
|
||||
|
||||
const char* getName () const ;
|
||||
int getNumAxes () const ;
|
||||
int getNumButtons () const ;
|
||||
int notWorking () const ;
|
||||
void setError () ;
|
||||
|
||||
float getDeadBand ( int axis ) const ;
|
||||
void setDeadBand ( int axis, float db ) ;
|
||||
|
||||
float getSaturation ( int axis ) const ;
|
||||
void setSaturation ( int axis, float st ) ;
|
||||
|
||||
void setMinRange ( float *axes ) ;
|
||||
void setMaxRange ( float *axes ) ;
|
||||
void setCenter ( float *axes ) ;
|
||||
|
||||
void getMinRange ( float *axes ) const ;
|
||||
void getMaxRange ( float *axes ) const ;
|
||||
void getCenter ( float *axes ) const ;
|
||||
|
||||
void read ( int *buttons, float *axes ) ;
|
||||
void rawRead ( int *buttons, float *axes ) ;
|
||||
}
|
||||
|
||||
</pre>
|
||||
You pass the identifier (0..n) of the joystick you wish to
|
||||
open into the constructor function. If you leave the number
|
||||
off, it'll grab the first joystick available.
|
||||
<p>
|
||||
If the joystick is unavailable, not working, not installed or
|
||||
otherwise bad, the package will return zero for all the axes
|
||||
and all the buttons will appear to be up. If you need to
|
||||
check for the existance of a particular stick, you can
|
||||
call <code>notWorking()</code> which returns JS_TRUE if
|
||||
there is some problem with that stick, JS_FALSE otherwise.
|
||||
<p>
|
||||
<code>getName()</code> tells you the device name of the
|
||||
joystick, if available through API calls in your OS. A
|
||||
typical value is "CH PRODUCTS CH PRO PEDALS USB ". If no
|
||||
name is available, this method will return the empty string.
|
||||
<p>
|
||||
<code>getNumAxes()</code> tells you how many axes the stick
|
||||
has. Note that it is NOT safe to assume that all sticks have
|
||||
the same number of axes - or that they all have a maximum of
|
||||
three or something. When you pass axis data into and out of
|
||||
JS, your arrays MUST be sized large enough for that stick.
|
||||
<p>
|
||||
When you are testing joystick code, you need to be sure your
|
||||
program does the right thing when no joystick is installed.
|
||||
Since it's inconvenient to do keep uninstalling your stick
|
||||
to do that, we provide <code>setError()</code> which causes
|
||||
that stick to react exactly as if it were not installed.
|
||||
<p>
|
||||
To read the joystick, just call <code>read(&buttons,axes)</code>
|
||||
where 'buttons' is an integer and 'axes' is an array of
|
||||
floating point numbers. The buttons variable will be populated
|
||||
with a number that has one bit per button (0==Not Pressed, 1==Pressed)
|
||||
and the elements of the axis array will be scaled from an idealized
|
||||
-1.0 to +1.0 range. (In practice, your stick may not reach those
|
||||
limits - or it may marginally exceed them).
|
||||
<p>
|
||||
For a basic two axis stick, axis zero is Left/Right with left being
|
||||
negative and right positive. Axis one is North/South with north being
|
||||
negative and right positive (this is counter-intuitive - but that's
|
||||
what they do).
|
||||
<p>
|
||||
M$-Windows letters its stick axes X,Y,Z,R,U,V. These correspond
|
||||
to JS axes 0,1,2,3,4,5,6.
|
||||
<H2>Buttons</H2>
|
||||
One continually annoying thing about PC joysticks is the lack of
|
||||
standards for their names. Most sticks have at least two buttons -
|
||||
mine has six (maybe some have still more). The problem is to know
|
||||
how to name them. My game pad has buttons labelled A,B,C,D,R,L
|
||||
corresponding to bits 0,1,2,3,4,5 in the 'buttons' variable.
|
||||
<p>
|
||||
Anyway, some joysticks have features that operate by setting
|
||||
two or more button bits at once. This is quite easy to catch by
|
||||
masking multiple bits from the 'buttons' word.
|
||||
<H2>Demo Program</H2>
|
||||
The demo program that comes with JS is quite useful for finding out
|
||||
which buttons set which bits and which axes are which - and in
|
||||
which direction they operate.
|
||||
<H2>Calibration</H2>
|
||||
Since most joysticks are analog devices (and fairly cheap, nasty ones
|
||||
at that), you will not generally get numbers that are accurately
|
||||
in the range -1..1 with exactly zero being returned when the joystick
|
||||
is centered on it's springs. This means that you may wish to calibrate
|
||||
your joystick. The <code>rawRead</code> routine bypasses all the scaling and
|
||||
offsetting to return RAW data directly from the OS that you can use during
|
||||
calibration.
|
||||
<p>
|
||||
For each axis of the joystick, you should provide a maximum number
|
||||
(that you wish to correspond to 1.0 returned by <code>read()</code>),
|
||||
a minimum number (corresponding to -1.0) and a center point number
|
||||
(corresponding to 0.0) by calling
|
||||
<code>setMaxRange()/setMinRange()/setCenter()</code> as appropriate.
|
||||
<p>
|
||||
However, even with calibration, you should expect the joystick to
|
||||
drift somewhat over time due to the position of the cable, the
|
||||
temperature of the potentiometers and probably, the phase of the moon.
|
||||
This drift is typically not serious at the max and min limits - but
|
||||
in some applications, the user will expect (for example) for his
|
||||
character in a game to stop moving completely when he releases the
|
||||
stick. Since we cannot guarantee to get the same exact number out
|
||||
of the stick when he does this, you'll need to implement a 'dead band'
|
||||
in the middle of the stick's travel. This is done with
|
||||
<code>setDeadBand(axis,amount)</code> where 'axis' is the number of the
|
||||
axis you wish to have a dead band implemented on - and 'amount' is the
|
||||
amount of dead band either side of 0.0.
|
||||
<p>
|
||||
There are corresponding 'get' routines for each 'set'.
|
||||
<p>
|
||||
The <code>read</code> routine is auto-calibrated when you create
|
||||
the joystick class - so if the joystick is not centered at that
|
||||
moment, you will get bad data from that point onwards. This is
|
||||
quite common in games - so don't feel too badly about it. Just
|
||||
arrange to 'new' all your joysticks early on in the program - when
|
||||
your user's hands are likely to still be on the keyboard or mouse -
|
||||
and provide a hot-key to pause the game and recalibrate the stick
|
||||
on demand.
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
112
doc/license.html
Normal file
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>PLIB: Licensing.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="plib_logo.png" ALT="PLIB Logo" width=256 height=245>
|
||||
<br>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<H1>
|
||||
<FONT SIZE=9>S</FONT><FONT SIZE=5>TEVE'S</FONT>
|
||||
<FONT SIZE=9>P</FONT><FONT SIZE=5>ORTABLE</FONT>
|
||||
<FONT SIZE=9>G</FONT><FONT SIZE=5>AME</FONT>
|
||||
<FONT SIZE=9>L</FONT><FONT SIZE=5>IBRARY.</FONT>
|
||||
</H1>
|
||||
</center>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't
|
||||
get much Sleep.
|
||||
<br>
|
||||
-- Woody Allen
|
||||
</ul>
|
||||
<center>
|
||||
<A href="http://sf.net">
|
||||
<IMG src="http://sf.net/sflogo.php?group_id=382&type=1" width="88" height="31" border="0" ALT="Sourceforge Logo"></A>
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD valign=top align=left>
|
||||
<A HREF="index.html"><IMG SRC="home.png" ALT="HOME" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="whats_inside.html"><IMG SRC="whats_inside.png" ALT="WHAT'S INSIDE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="license.html"><IMG SRC="license.png" ALT="LICENSE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="contacts.html"><IMG SRC="contacts.png" ALT="CONTACTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="requirements.html"><IMG SRC="requirements.png" ALT="REQUIREMENTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="gallery.html"><IMG SRC="gallery.png" ALT="GALLERY" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="download.html"><IMG SRC="download.png" ALT="DOWNLOAD & INSTALL" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="examples.html"><IMG SRC="examples.png" ALT="EXAMPLES" BORDER="0" width=150 height=50></A><br>
|
||||
|
||||
<A HREF="sg/index.html"><IMG SRC="SG.png" ALT="SG" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="ssg/index.html"><IMG SRC="SSG.png" ALT="SSG" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="ssgAux/index.html"><IMG SRC="ssgAux.png" ALT="SSGAUX" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="fnt/index.html"><IMG SRC="FNT.png" ALT="FNT" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pui/index.html"><IMG SRC="PUI.png" ALT="PUI" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="psl/index.html"><IMG SRC="PSL.png" ALT="PSL" BORDER="0" width=75 height=25></A>
|
||||
|
||||
<A HREF="util/index.html"><IMG SRC="UL.png" ALT="UL" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="js/index.html"><IMG SRC="JS.png" ALT="JS" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="net/index.html"><IMG SRC="NET.png" ALT="NET" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="sl/index.html"><IMG SRC="SL.png" ALT="SL" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pw/index.html"><IMG SRC="PW.png" ALT="PW" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="puAux/index.html"><IMG SRC="puAux.png" ALT="PUAUX" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H2>PLIB Licensing.</H2>
|
||||
PLIB is licensed under the <A HREF="http://www.gnu.org/copyleft/library.html">Library GNU Public License</A> (LGPL).
|
||||
<p>
|
||||
Whilst this permits closed-source applications to use PLIB, you
|
||||
are bound by certain restrictions under LGPL. Please be sure
|
||||
to read and understant the 'LICENSE' file in the PLIB distribution
|
||||
directory before you distribute any work based around or upon PLIB.
|
||||
<p>
|
||||
The PLIB example programs (being complete programs) are licensed
|
||||
under the GNU General Public License (GPL).
|
||||
<p>
|
||||
Each of the demonstration programs has it's own license - but
|
||||
they are all 'OpenSource' of one kind or another (as defined by
|
||||
the SourceForge rules for OpenSourced software. Check the
|
||||
distribution directory for each one for a LICENSE file describing
|
||||
how it's licensed.
|
||||
<H2>Polite Request to Distributors.</H2>
|
||||
If you are a Linux or other OpenSource software distributor,
|
||||
please do us the courtesy of only releasing stable versions
|
||||
of PLIB and NOT versions labelled 'unstable' - or (especially)
|
||||
any snapshot you may take from SVN. We are aware that legally,
|
||||
you are entitled to do either of these things - but we ask
|
||||
that you do not because it makes supporting PLIB that much
|
||||
more difficult.
|
||||
<p>
|
||||
We would also appreciate being notified of which versions
|
||||
you plan to ship - and approximately when so that we may
|
||||
coordinate with you as to the best version to take.
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
doc/license.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
doc/majik3d.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
doc/marble.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
doc/mote.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
354
doc/net/index.html
Normal file
@@ -0,0 +1,354 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="keywords" content="NET, PLIB, Pegasus, network, library, portable, games, medusa, client, server, socket, TCP, IP, netAddress, netBuffer, netMessage, netGuid, netSocket, netChannel, netBufferChannel, netChat, netMessageChannel, netMonitorServer">
|
||||
<META name="description" content="The Pegasus Network Library is C++ library for making networked games. Pegasus is based on Medusa and it is a part of PLIB. Pegasus, like Medusa, multiplexes I/O with its various client and server connections within a single process/thread. Pegasus is supported on many platforms, including Win32, Linux, and a majority of Unix implementations.">
|
||||
<TITLE>Pegasus Network Library</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<center>
|
||||
<H1>Pegasus Network Library</H1>
|
||||
</center>
|
||||
<H2>Introduction</H2>
|
||||
Pegasus is a C++ library for making networked games. Pegasus is based on
|
||||
<a href="http://www.nightmare.com/medusa/medusa.html">Medusa</a>
|
||||
and is part of <A HREF="../index.html">PLIB</A>.
|
||||
Pegasus, like Medusa, runs as a single process, multiplexing I/O with its various
|
||||
client and server connections within a single process/thread. Pegasus is supported
|
||||
on any platform that includes a socket implementation with the select() function.
|
||||
This includes Win32, Linux, and a majority of Unix implementations.
|
||||
<p>
|
||||
This document assumes a certain degree of knowledge of
|
||||
TCP/IP and socket programming.
|
||||
<p>
|
||||
To use the NET library, you'll need to '#include <plib/net.h>' and
|
||||
link to libplibnet.a
|
||||
<H2>Symbol Conventions.</H2>
|
||||
Pegasus follows the same conventions for symbols and tokens that
|
||||
are used by OpenGL and GLUT. All Pegasus symbols for classes and
|
||||
functions start with <code>net</code> and all <code>#define</code>
|
||||
tokens start with <code>NET</code>. Words within a class or function
|
||||
name are Capitalised and NOT separated with underscores. Words
|
||||
within <code>#define</code> tokens may be separated with underscores
|
||||
to make them readable.
|
||||
<H2>Initialisation.</H2>
|
||||
The first NET call in any program must always be netInit().
|
||||
<H2>Classes</H2>
|
||||
The following class hierarchy makes up the core package - which
|
||||
can be extended to add functionality or to change some underlying
|
||||
mechanisms.
|
||||
<pre>
|
||||
|
||||
class netAddress
|
||||
|
||||
class netBuffer
|
||||
|__ class netMessage
|
||||
|
||||
class netGuid
|
||||
|
||||
class netSocket
|
||||
|__ class netChannel
|
||||
|__ class netBufferChannel
|
||||
| |__ class netChat
|
||||
| |__ class netMessageChannel
|
||||
|
|
||||
|__ class netMonitorServer
|
||||
|
||||
</pre>
|
||||
<H2><code>class netBuffer</code></h2>
|
||||
A simple buffer class.
|
||||
<pre>
|
||||
class netBuffer
|
||||
{
|
||||
public:
|
||||
netBuffer ( int max_length ) ;
|
||||
~netBuffer () ;
|
||||
|
||||
int getLength() const ;
|
||||
int getMaxLength() const ;
|
||||
char* getData() ;
|
||||
|
||||
void remove () ;
|
||||
void remove (int pos, int n) ;
|
||||
bool append (const char* s, int n) ;
|
||||
bool append (int n) ;
|
||||
} ;
|
||||
</pre>
|
||||
<H2><code>class netMessage</code></h2>
|
||||
A message buffer used to transfer binary data and handle byte swapping.
|
||||
<pre>
|
||||
class netMessage : public netBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
netMessage ( const char* s, int n ) ;
|
||||
netMessage ( int type, int to_id, int from_id ) ;
|
||||
|
||||
int getType () const ;
|
||||
int getToID () const ;
|
||||
int getFromID () const ;
|
||||
|
||||
void geta ( void* a, int n ) const ; // a=array; array should already be serialized
|
||||
void puta ( const void* a, int n ) ;
|
||||
|
||||
int getch () const ;
|
||||
void putch ( int c ) ;
|
||||
|
||||
bool getb () const ;
|
||||
void putb ( bool b ) ;
|
||||
|
||||
int getw () const ;
|
||||
void putw ( int i ) ;
|
||||
|
||||
int geti () const ;
|
||||
void puti ( int i ) ;
|
||||
|
||||
void gets ( char* s, int n ) const ;
|
||||
void puts ( const char* s ) ;
|
||||
|
||||
void print ( FILE *fd = stderr ) const ;
|
||||
};
|
||||
</pre>
|
||||
<H2><code>class netAddress</code></h2>
|
||||
This is the representation of an Internet-style machine address.
|
||||
<pre>
|
||||
class netAddress
|
||||
{
|
||||
public:
|
||||
netAddress () ;
|
||||
netAddress ( const char* host, int port ) ;
|
||||
|
||||
void set ( const char* host, int port ) ;
|
||||
|
||||
const char* getHost () const ;
|
||||
int getPort () const ;
|
||||
|
||||
static const char* getLocalHost () ;
|
||||
|
||||
bool getBroadcast () const ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
When reading from the network using one of the higher level classes,
|
||||
you can use a netAddress with an empty string as the 'host' to mean
|
||||
"accept data from any host". When writing to the network, the
|
||||
reserved host name '<broadcast>' (the < and > are literally
|
||||
there) will cause the message to be broadcast to all machines on your
|
||||
subnet.
|
||||
<p>
|
||||
Otherwise, use either the machines' network name - or it's IP address
|
||||
(as an ASCII string).
|
||||
<H2><code>class netSocket</code></h2>
|
||||
netSocket is the low-level socket class.
|
||||
<pre>
|
||||
class netSocket
|
||||
{
|
||||
public:
|
||||
netSocket () ;
|
||||
virtual ~netSocket () ;
|
||||
|
||||
int getHandle () const ;
|
||||
void setHandle (int handle) ;
|
||||
|
||||
bool open ( bool stream=true ) ;
|
||||
int bind ( cchar* host, int port ) ;
|
||||
int listen ( int backlog ) ;
|
||||
int accept ( netAddress* addr ) ;
|
||||
int connect ( cchar* host, int port ) ;
|
||||
int send ( const void * buffer, int size, int flags = 0 ) ;
|
||||
int sendto ( const void * buffer, int size, int flags, const netAddress* to ) ;
|
||||
int recv ( void * buffer, int size, int flags = 0 ) ;
|
||||
int recvfrom ( void * buffer, int size, int flags, netAddress* from ) ;
|
||||
void close ( void ) ;
|
||||
void setBlocking ( bool blocking ) ;
|
||||
} ;
|
||||
</pre>
|
||||
<H3>Example:</H3>
|
||||
This example is stripped of error checking for clarity:
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<H4>Sender:</H4>
|
||||
<pre>
|
||||
netInit () ;
|
||||
|
||||
netSocket *sock = new netSocket () ;
|
||||
sock -> open ( false ) ;
|
||||
sock -> setBlocking ( false ) ;
|
||||
sock -> connect ( host, port ) ;
|
||||
|
||||
while ( !done )
|
||||
sock -> send ( msg, len, 0 );
|
||||
|
||||
sock -> close () ;
|
||||
</pre>
|
||||
</TD>
|
||||
<TD>
|
||||
<H4>Reciever:</H4>
|
||||
<pre>
|
||||
netInit () ;
|
||||
|
||||
netSocket *sock = new netSocket () ;
|
||||
sock -> open ( false ) ;
|
||||
sock -> setBlocking ( false ) ;
|
||||
sock -> bind ( host, port ) ;
|
||||
|
||||
while ( !done )
|
||||
if ( (len = sock -> recv(msg, maxlen, 0)) >= 0 )
|
||||
...use the data...
|
||||
|
||||
sock -> close () ;
|
||||
</pre>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
This code produces a 'Datagram' connection - which is fast but unreliable
|
||||
(using UDP protocol). Passing a 'true' to sock->open() would produce a
|
||||
'Stream' connection (using TCP).
|
||||
|
||||
<H2><code>class netChannel</code></h2>
|
||||
netChannel adds event-handling to the low-level
|
||||
netSocket class. Otherwise, it can be treated as
|
||||
a normal non-blocking socket object.
|
||||
The direct interface between the poll loop and
|
||||
the channel object are the handleReadEvent and
|
||||
handleWriteEvent methods. These are called
|
||||
whenever a channel object 'fires' that event.
|
||||
The firing of these low-level events can tell us whether
|
||||
certain higher-level events have taken place, depending on
|
||||
the timing and state of the connection.
|
||||
<pre>
|
||||
class netChannel : public netSocket
|
||||
{
|
||||
public:
|
||||
|
||||
netChannel () ;
|
||||
virtual ~netChannel () ;
|
||||
|
||||
void setHandle (int s, bool is_connected = true);
|
||||
bool isConnected () const ;
|
||||
bool isClosed () const ;
|
||||
void shouldDelete () ;
|
||||
|
||||
// --------------------------------------------------
|
||||
// socket methods
|
||||
// --------------------------------------------------
|
||||
|
||||
bool open ( bool stream=true ) ;
|
||||
int listen ( int backlog ) ;
|
||||
int connect ( cchar* host, int port ) ;
|
||||
int send ( const void * buf, int size, int flags = 0 ) ;
|
||||
int recv ( void * buf, int size, int flags = 0 ) ;
|
||||
void close ( void ) ;
|
||||
|
||||
// poll() eligibility predicates
|
||||
virtual bool readable (void) ;
|
||||
virtual bool writable (void) ;
|
||||
|
||||
// --------------------------------------------------
|
||||
// event handlers
|
||||
// --------------------------------------------------
|
||||
|
||||
void handleReadEvent (void);
|
||||
void handleWriteEvent (void);
|
||||
|
||||
// These are meant to be overridden.
|
||||
virtual void handleConnect (void) ;
|
||||
virtual void handleRead (void) ;
|
||||
virtual void handleWrite (void) ;
|
||||
virtual void handleClose (void) ;
|
||||
virtual void handleAccept (void) ;
|
||||
virtual void handleError (int error) ;
|
||||
|
||||
static bool poll (u32 timeout = 0 ) ;
|
||||
static void loop (u32 timeout = 0 ) ;
|
||||
};
|
||||
</pre>
|
||||
<H2><code>class netBufferChannel</code></h2>
|
||||
netBufferChannel is a netChannel with I/O buffering.
|
||||
Clients and servers built on top of netBufferChannel
|
||||
automatically support pipelining where you can send
|
||||
multiple commands without waiting for the response
|
||||
to each command before you send the next.
|
||||
<pre>
|
||||
class netBufferChannel : public netChannel
|
||||
{
|
||||
public:
|
||||
netBufferChannel (int in_buffer_size = 512, int out_buffer_size = 4096) ;
|
||||
void closeWhenDone (void) ;
|
||||
|
||||
virtual bool bufferSend (const char* msg, int msg_len) ;
|
||||
virtual void handleBufferRead (netBuffer& buffer) ;
|
||||
};
|
||||
</pre>
|
||||
<H2><code>class netChat</code></h2>
|
||||
netChat adds support for 'chat' style protocols -
|
||||
where one side sends a 'command', and the other sends
|
||||
a response (examples would be the common internet
|
||||
protocols - smtp, nntp, ftp, etc..).
|
||||
<p>
|
||||
The handle_buffer_read() method looks at the input
|
||||
stream for the current 'terminator' (usually '\r\n'
|
||||
for single-line responses, '\r\n.\r\n' for multi-line
|
||||
<pre>
|
||||
class netChat : public netBufferChannel
|
||||
{
|
||||
public:
|
||||
netChat () ;
|
||||
|
||||
void setTerminator (const char* t);
|
||||
const char* getTerminator (void);
|
||||
|
||||
bool push (const char* s) ;
|
||||
|
||||
virtual void collectIncomingData (const char* s, int n) ;
|
||||
virtual void foundTerminator (void) ;
|
||||
};
|
||||
</pre>
|
||||
<H2><code>class netMessageChannel</code></h2>
|
||||
A channel for binary messages. Takes care of packing and unpacking them in/out of the buffers.
|
||||
<pre>
|
||||
class netMessageChannel : public netBufferChannel
|
||||
{
|
||||
public:
|
||||
netMessageChannel () ;
|
||||
|
||||
bool sendMessage ( const netMessage& msg ) ;
|
||||
virtual void handleMessage ( const netMessage& msg ) ;
|
||||
};
|
||||
</pre>
|
||||
<H2><code>class netMonitorServer</code></h2>
|
||||
The monitor server gives you remote, 'back-door' access to your server while it is running. netMonitor is a telnet command port with
|
||||
password authorization. It can be paired with and used to remotely admin another server.
|
||||
Once connected via any telnet client to the monitor, you can issue commands. The monitor can be hooked up to a python interpreter for added power. Since an ordinary telnet session is not secure, the password could be intercepted, but that level of security is usually not needed for games.
|
||||
<pre>
|
||||
class netMonitorServer : public netChannel
|
||||
{
|
||||
public:
|
||||
netMonitorServer( cchar* _name, int port ) ;
|
||||
~netMonitorServer() ;
|
||||
|
||||
cchar* getPassword () const ;
|
||||
void setPassword ( cchar* string ) ;
|
||||
void setPrompt ( cchar* string ) ;
|
||||
void setCommandFunc ( void (*func)(cchar*, netMonitorChannel*) ) ;
|
||||
} ;
|
||||
</pre>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://mcdave.cjb.net">
|
||||
Dave McClurg</A>
|
||||
<<A HREF="mailto:dpm@efn.org">dpm@efn.org</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
BIN
doc/plib_logo.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
doc/ppe_logo_1.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
430
doc/psl/appl_guide.html
Normal file
@@ -0,0 +1,430 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="PSL, PLIB, OpenGL, portable, script, language, Baker, Steve">
|
||||
<meta name="description" content="The PLIB Scripting Language (PSL) Library is a lightweight scripting language that is well suited for games or other interactive programs.">
|
||||
<title>The PLIB Scripting Language: Applications Guide.</title>
|
||||
</head>
|
||||
<body text="#B5A642" bgcolor="#005000" link="#8FFF8F" vlink="#18A515" alink="#20336B" background="../marble.png">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<center>
|
||||
<h1>The PSL Application Programmer's Guide.</h1></center>
|
||||
<center>By Steve Baker</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<H1>Introduction</H1>
|
||||
This document is to help people writing C++ applications to include
|
||||
scripting abilities using the PSL interpreter.
|
||||
<p>
|
||||
|
||||
To include PSL scripts into your application requires that you:
|
||||
<pre>
|
||||
|
||||
#include <plib/psl.h>
|
||||
|
||||
</pre>
|
||||
...and link with '<code>-lplibpsl</code>'
|
||||
<p>
|
||||
Then, sometime before you call any other PSL functions, you must call:
|
||||
<pre>
|
||||
|
||||
pslInit () ;
|
||||
|
||||
</pre>
|
||||
Each PSL script is represented by an object of class <code>pslProgram</code>
|
||||
<H1>Example Application</H1>
|
||||
This is the simplest possible PSL application, it
|
||||
loads a script called "test.psl", compiles and runs it.
|
||||
<pre>
|
||||
|
||||
#include <plib/psl.h>
|
||||
|
||||
void main ()
|
||||
{
|
||||
pslInit () ;
|
||||
pslExtension extensions [] = { { NULL, 0, NULL } } ;
|
||||
pslProgram *prog = new pslProgram ( extensions, "Program1" ) ;
|
||||
prog -> compile ( "test.psl" ) ;
|
||||
while ( prog -> step () != PSL_PROGRAM_END ) /* Nothing */ ;
|
||||
}
|
||||
|
||||
</pre>
|
||||
Here is a line-by-line explanation:
|
||||
<p>
|
||||
<center>
|
||||
<TABLE border="1">
|
||||
<tr><td><code> pslInit () ;</code></td><td>
|
||||
Initialise PSL - this must be the first thing you do.</td></tr>
|
||||
<tr><td><code> pslExtension extensions [] ...</code></td><td>
|
||||
Make a list of PSL extension functions.<br>
|
||||
This program doesn't have any. </td></tr>
|
||||
<tr><td><code> pslProgram *prog = new pslProgram...</code> </td><td>
|
||||
Declare a program (called "MyProgram").</td></tr>
|
||||
<tr><td><code> prog -> compile ( "test.psl" ) ;</code></td><td>
|
||||
Compile the program to bytecode.</td></tr>
|
||||
<tr><td><code> while ( prog -> step () != PSL_PROGRAM_END )...</code>
|
||||
</td><td>
|
||||
Tell the PSL program to execute one 'step'
|
||||
<br>Keep doing that until we reach the end of the program.
|
||||
</td></tr>
|
||||
</TABLE>
|
||||
</center>
|
||||
<p>
|
||||
Easy!
|
||||
<p>
|
||||
Now let's look at <code>class pslProgram</code> in more detail.
|
||||
<H1><code>class pslProgram</code></H1>
|
||||
Each PSL script is represented by an object of class <code>pslProgram</code>.
|
||||
<pre>
|
||||
|
||||
class pslProgram
|
||||
{
|
||||
public:
|
||||
|
||||
pslProgram ( const pslExtension *extns, const char *name ) ;
|
||||
|
||||
pslProgram ( pslProgram *prog, const char *name ) ;
|
||||
|
||||
|
||||
void setUserData ( void *data ) ;
|
||||
void *getUserData () const ;
|
||||
|
||||
void setProgName ( const char *name ) ;
|
||||
char *getProgName () const ;
|
||||
|
||||
void dump () const ;
|
||||
void reset () ;
|
||||
pslResult step () ;
|
||||
pslResult trace () ;
|
||||
|
||||
int compile ( const char *memptr, const char *fname ) ;
|
||||
int compile ( const char *fname ) ;
|
||||
int compile ( FILE *fd ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
<H1><code>pslProgram::pslProgram</code></H1>
|
||||
There are two constructor functions to choose from. The first
|
||||
takes an array of 'extension functions' and the name by which
|
||||
this program will be known (for error messages and such). The
|
||||
second constructor takes an existing, compiled PSL program and
|
||||
makes a copy of it - it too needs a program name.
|
||||
<p>
|
||||
The second version of the constructor is especially efficient
|
||||
because this enables the script to be compiled just once - and
|
||||
run multiple times in parallel. The second and subsequent
|
||||
copies of the program consume much less RAM than the first
|
||||
copy because they share the 'code' part of the script.
|
||||
<p>
|
||||
For example, you can run two copies of a script in parallel
|
||||
like this:
|
||||
<pre>
|
||||
|
||||
pslInit () ;
|
||||
|
||||
pslProgram *prog_1 = new pslProgram ( extensions, "code1" ) ;
|
||||
prog_1 -> compile ( "data/test.psl" ) ;
|
||||
|
||||
pslProgram *prog_2 = new pslProgram ( prog_1, "code2" ) ;
|
||||
|
||||
while ( prog_1 -> step () != PSL_PROGRAM_END &&
|
||||
prog_2 -> step () != PSL_PROGRAM_END )
|
||||
/* NOTHING */ ;
|
||||
|
||||
</pre>
|
||||
<H1><code>pslProgram::compile</code></H1>
|
||||
When you compile a PSL program, any errors or warnings are reported
|
||||
to stderr (by default) and the number of fatal compilation errors
|
||||
is returned as the result of the 'compile' function. Programs may
|
||||
choose to ignore any compilation errors - but executing the resulting
|
||||
program will immediately produce a PSL_PROGRAM_END.
|
||||
<p>
|
||||
You can pass to the compiler either:
|
||||
<ol>
|
||||
<li> The filename of the file containing the PSL source code...or...
|
||||
<li> A 'FILE *' descriptor for the file containing the PSL source...or...
|
||||
<li> The address of a null terminated string containing the
|
||||
program source PLUS a name to use for the program when reporting
|
||||
errors, etc.
|
||||
</ol>
|
||||
If you pass the filename (1) or the address of the source with a name (3),
|
||||
then error messages from PSL will refer to that name. But if you pass a
|
||||
file destriptor then the program name that you passed to the constructor
|
||||
function will be reported.
|
||||
<p>
|
||||
Applications that would like to report scripting errors in a more elegant
|
||||
way, may register a callback function that will be called whenever there
|
||||
is a problem within PSL:
|
||||
<pre>
|
||||
|
||||
void pslSetErrorCallback ( void (*CB) ( pslProgram *, int, char *,
|
||||
int, char * ) ) ;
|
||||
</pre>
|
||||
Your function will be called with five parameters:
|
||||
<pre>
|
||||
|
||||
void myErrorCB ( pslProgram *prog, int severity,
|
||||
char *progname, int lineno, char *message ) ) ;
|
||||
</pre>
|
||||
<ul>
|
||||
<li> The 'prog' parameter is a pointer to the pslProgram that had the
|
||||
problem.
|
||||
<li> The 'severity' parameter is the error type and severity:
|
||||
<ul>
|
||||
<li> PSL_COMPILETIME_WARNING - A problem was found while
|
||||
compiling the PSL program - but it may not be serious enough
|
||||
to prevent it from running.
|
||||
<li> PSL_COMPILETIME_ERROR - A serious problem was found while
|
||||
compiling the PSL program - it won't run correctly.
|
||||
<li> PSL_RUNTIME_WARNING - A problem was found while running
|
||||
the PSL program - but it wasn't serious enough to prevent
|
||||
the program from continuing to execute.
|
||||
<li> PSL_RUNTIME_ERROR - The PSL program 'crashed' while being
|
||||
executed.
|
||||
</ul>
|
||||
<li> The 'progname' parameter is the name of the program.
|
||||
<li> The 'lineno' parameter is the line number at which the problem
|
||||
occurred (if compiling) or the byte-code address at which it
|
||||
failed (if at runtime). The latter isn't much use unless you
|
||||
are a developer of the PSL interpreter.
|
||||
<li> The 'message' parameter is the actual text of the error message.
|
||||
</ul>
|
||||
Notice that at compiletime, the 'progname' parameter is the name of the
|
||||
file or string being compiled (if that's known to the compiler). Since it's
|
||||
possible for one PSL source file to '#include' another, you should
|
||||
always use the 'progName' parameter in your error messages in preference
|
||||
to <code>prog->getProgName()</code> member function.
|
||||
<H1><code>pslExtension</code></H1>
|
||||
We have not yet talked about this mysterious 'extensions' array that's passed
|
||||
into the pslProgram constructor function.
|
||||
<p>
|
||||
It's important that your PSL scripts are able to interact with your C++
|
||||
program - and this is done by creating a number of C++ functions that
|
||||
can be called by the PSL program as it executes. These are called
|
||||
'extensions' because they extend the functionality of PSL.
|
||||
<p>
|
||||
The extension parameter to the pslProgram constructor is an array of
|
||||
pslExtension structures:
|
||||
<pre>
|
||||
|
||||
class pslExtension
|
||||
{
|
||||
public:
|
||||
|
||||
const char *symbol ;
|
||||
int argc ;
|
||||
pslValue (*func) ( int, pslValue *, pslProgram *p ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
<ul>
|
||||
<li>The 'symbol' field is the name of the extension function AS IT APPEARS INSIDE
|
||||
PSL PROGRAMS. This doesn't have to be the same as the actual name of
|
||||
your C++ function.
|
||||
<li>The 'argc' field is the number of parameters the function expects. You can
|
||||
set 'argc' to -1 to allow any number of parameters to be passed - so that you
|
||||
can create functions that work like 'printf' does.
|
||||
<li>The 'func' field is a pointer to your C++ function.
|
||||
</ul>
|
||||
The list of pslExtensions is terminated by a <code>{ NULL, 0, NULL}</code>
|
||||
entry.
|
||||
<p>
|
||||
The C++ function has to look like this:
|
||||
<pre>
|
||||
|
||||
pslValue my_func ( int argc, pslValue *argv, pslProgram *p )
|
||||
|
||||
</pre>
|
||||
<ul>
|
||||
<li>The 'argc' parameter to the C++ function is the number of
|
||||
PSL parameters that were passed to it. It's useful to know this
|
||||
number when your pslExtension had 'argc' set to -1.
|
||||
<p>
|
||||
<li>The 'argv' parameter is an array containing the parameters
|
||||
that PSL is passing to this function. Each element is a 'pslValue'
|
||||
class which could contain any of the PSL variable types.
|
||||
<p>
|
||||
<li>The 'p' parameter is a pointer to the pslProgram that was
|
||||
running at the time this function was called. Notice that pslProgram's
|
||||
can have user data associated with them - so this gives you quite a
|
||||
bit of scope for accessing script-specific data structures.
|
||||
<p>
|
||||
<li>When your script has finished doing it's job, it has to return
|
||||
some kind of result. This is another one of those 'pslValue'
|
||||
class objects.
|
||||
</ul>
|
||||
<H3>Example Extension Function</H3>
|
||||
This C++ function prints it's arguments to stdout and returns the
|
||||
value 123.456.
|
||||
<pre>
|
||||
|
||||
pslValue print ( int argc, pslValue *argv, pslProgram *p )
|
||||
{
|
||||
for ( int i = 0 ; i < argc ; i++ )
|
||||
{
|
||||
switch ( argv[i].getType () )
|
||||
{
|
||||
case PSL_INT : printf ( "%d ", argv[i].getInt () ) ; break ;
|
||||
case PSL_FLOAT : printf ( "%f ", argv[i].getFloat () ) ; break ;
|
||||
case PSL_STRING : printf ( "%s ", argv[i].getString () ) ; break ;
|
||||
case PSL_VOID : printf ( "(void) " ) ; break ;
|
||||
default : printf ( "Illegal parameter passed to 'print'." ) ; break ;
|
||||
}
|
||||
}
|
||||
|
||||
pslValue ret ;
|
||||
ret.set ( 123.456f ) ;
|
||||
return ret ;
|
||||
}
|
||||
|
||||
</pre>
|
||||
Adding this to the example program above, requires only that you
|
||||
change the declaration of 'extensions' as follows:
|
||||
<pre>
|
||||
|
||||
pslExtension extensions [] =
|
||||
{
|
||||
{ "print", -1, print },
|
||||
{ NULL, 0, NULL }
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
Now, now you can write "Hello World" in PSL script:
|
||||
<pre>
|
||||
|
||||
int main ()
|
||||
{
|
||||
print ( "Hello World.\n" ) ;
|
||||
}
|
||||
|
||||
</pre>
|
||||
...and your C++ function 'print' will be called with one parameter
|
||||
that'll contain the string value "Hello World.\n".
|
||||
<H3><code>pslValue</code></H3>
|
||||
The 'pslValue' class is used to pass numbers into and out of extension
|
||||
functions. It contains the type and value of a number or string in PSL
|
||||
and it looks like this:
|
||||
<pre>
|
||||
|
||||
class pslValue
|
||||
{
|
||||
public:
|
||||
|
||||
pslType getType () const ;
|
||||
|
||||
int getInt () const ;
|
||||
float getFloat () const ;
|
||||
char *getString () const ;
|
||||
|
||||
void set () ;
|
||||
void set ( int v ) ;
|
||||
void set ( float v ) ;
|
||||
void set ( const char *v ) ;
|
||||
void set ( const pslNumber *v ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
Setting <b>nothing</b> into your pslValue ("my_value->set()") is used to
|
||||
return a 'void' result from your extension function - that is the default
|
||||
type for a pslValue.
|
||||
<p>
|
||||
The 'getType' call returns the type of this value - currently,
|
||||
it can be: PSL_INT, PSL_FLOAT, PSL_STRING or PSL_VOID. If you 'set' the
|
||||
pslValue, it automatically changes it's 'getType' result to match.
|
||||
<p>
|
||||
Doing a 'get' for a type that DOESN'T match the 'getType' of the pslValue
|
||||
causes it to try to convert to that type. However, a 'getString' on a
|
||||
non-string pslValue will return NULL. Doing a 'getInt' or 'getFloat'
|
||||
on a PSL_STRING will perform an atoi() or atof() (respectively) in an
|
||||
attempt to get a number from the string.
|
||||
<H1>Running, Tracing, Debugging.</H1>
|
||||
You run the PSL program one byte-code instruction at a time by calling the
|
||||
<code>pslProgram::step()</code> function. A byte-code
|
||||
instruction is rather like the 'machine code' of a physical computer and
|
||||
it typically takes several byte-code instructions to implement each line
|
||||
of PSL source code.
|
||||
<p>
|
||||
The 'step' function returns one of three possible results:
|
||||
<ul>
|
||||
<li> PSL_PROGRAM_CONTINUE -- The PSL program is running normally.
|
||||
<li> PSL_PROGRAM_END -- The PSL program has finished running. This
|
||||
could be because it simply ended normally - but it could also
|
||||
be because it 'crashed' with a fatal runtime problem of some kind.
|
||||
<li> PSL_PROGRAM_PAUSE -- There is a special 'pause' statement in PSL
|
||||
and when that statement is executed, it causes 'step' to return
|
||||
this value.
|
||||
</ul>
|
||||
The PSL_PROGRAM_PAUSE return is intended to cope with the specific
|
||||
case when PSL is being used in an interactive graphical application.
|
||||
Typically, such applications will not want to run PSL scripts to
|
||||
completion every frame - but instead run them up to the next 'pause'
|
||||
statement.
|
||||
<p>
|
||||
A typical game might have dozens of PSL scripts running in parallel
|
||||
and wish to run each of them until the script 'pause's.
|
||||
<p>
|
||||
So, your application's main loop might look something like this:
|
||||
<pre>
|
||||
|
||||
read_the_joystick () ;
|
||||
|
||||
for ( int i = 0 ; i < num_scripts ; i++ )
|
||||
while ( program [ i ] -> step () == PSL_PROGRAM_CONTINUE )
|
||||
/* Do Nothing */ ;
|
||||
|
||||
render_the_graphics () ;
|
||||
swap_the_doublebuffer () ;
|
||||
|
||||
</pre>
|
||||
Then, one of those scripts (to move a monster for example)
|
||||
might look like this:
|
||||
<pre>
|
||||
|
||||
int main ()
|
||||
{
|
||||
int i = getMyMonster () ;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
moveMonster ( i ) ;
|
||||
pause ;
|
||||
}
|
||||
}
|
||||
|
||||
</pre>
|
||||
The 'pause' command indicates that this script has completed it's
|
||||
work for this frame.
|
||||
<p>
|
||||
Alternatively, some applications may wish to run the scripts for
|
||||
fixed amounts of time, fixed numbers of byte-codes - or until
|
||||
some other criterion is satisfied.
|
||||
<H3> Resetting a Script </H3>
|
||||
There is a <code>pslProgram::reset()</code> function that
|
||||
restarts the PSL program from the beginning having first
|
||||
reset all of its internal variables.
|
||||
<H3> Debugging PSL scripts </H3>
|
||||
For debugging PSL scripts, you may replace the 'step' call with
|
||||
'trace' - which causes the byte-code for each instruction to be
|
||||
printed to stderr as it's executed.
|
||||
<p>
|
||||
You can also call <code>pslProgram::dump()</code> to print out
|
||||
all of the byte-code and the PSL symbol table for the program.
|
||||
<H3> Include paths. </H3>
|
||||
By default, PSL searches for files with relative pathnames in
|
||||
the current directory - but you can override this by setting:
|
||||
<pre>
|
||||
|
||||
|
||||
pslScriptPath ( "directory" ) ;
|
||||
|
||||
</pre>
|
||||
<hr>
|
||||
<address>
|
||||
<a href="http://www.sjbaker.org">Steve J. Baker.</a> <<a href="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</a>></address>
|
||||
</body>
|
||||
</html>
|
||||
463
doc/psl/impl_guide.html
Normal file
@@ -0,0 +1,463 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="PSL, PLIB, OpenGL, portable, script, language, Baker, Steve">
|
||||
<meta name="description" content="The PLIB Scripting Language (PSL) Library is a lightweight scripting language that is well suited for games or other interactive programs.">
|
||||
<title>The PLIB Scripting Language: Implementation Guide.</title>
|
||||
</head>
|
||||
<body text="#B5A642" bgcolor="#005000" link="#8FFF8F" vlink="#18A515" alink="#20336B" background="../marble.png">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<center>
|
||||
<h1>The PSL Implementation Guide.</h1></center>
|
||||
<center>By Steve Baker</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<H1>Introduction</H1>
|
||||
This document describes the virtual machine that the PSL byte code
|
||||
interpreter implements.
|
||||
<p>
|
||||
The machine has 65536 bytes of instruction memory (and hence, 16 bit
|
||||
code addresses) and 256 variables (and hence 8 bit data addresses).
|
||||
Each variable can be a 32 bit integer, an IEEE single precision float
|
||||
or a character string of arbitary length.
|
||||
<p>
|
||||
In addition, there is a 256 element stack - each entry of which can
|
||||
contain any PSL data type.
|
||||
<p>
|
||||
The machine has just two registers - the Program Counter (PC) and
|
||||
the Stack Pointer (SP) - neither of which are accessible to running
|
||||
programs directly.
|
||||
<H1>The Instruction Set</H1>
|
||||
Each instruction consists of a one byte opcode and some number of
|
||||
bytes of data.
|
||||
<p>
|
||||
The hex numbers for these opcodes are listed in plib/src/psl/pslOpcodes.h
|
||||
<p>
|
||||
<H3> OPCODE_BAD </H3>
|
||||
INTRUCTION BYTES: 1<br>
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Produces a 'Suspicious Opcode' error message and halts the program.<br>
|
||||
Generally, programs
|
||||
that run amok for some reason (eg an error in the compiler) will
|
||||
hit a zero byte fairly soon afterwards. Hence instruction 0x00
|
||||
is reserved to be the BAD instruction. Other unrecognised
|
||||
instructions are also flagged as errors - but it's useful to
|
||||
explicitly reserve opcode 0x00 for this function due to the
|
||||
high probability of it being executed by broken programs.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_LINE_NUMBER </H3>
|
||||
INTRUCTION BYTES: 3
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Updates the 'current line number' from the two bytes
|
||||
embedded in the instruction.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_PUSH_INT_CONSTANT </H3>
|
||||
|
||||
INTRUCTION BYTES: 5
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Takes four bytes from the instruction and pushes them
|
||||
onto the stack as an integer.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_PUSH_FLOAT_CONSTANT </H3>
|
||||
INTRUCTION BYTES: 5
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Takes four bytes from the instruction and pushes them
|
||||
onto the stack as a float.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_PUSH_STRING_CONSTANT </H3>
|
||||
INTRUCTION BYTES: 1 + strlen string + 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Takes a null-terminated string from the instruction
|
||||
stream and pushes it onto the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_GET_PARAMETER </H3>
|
||||
INTRUCTION BYTES: 3
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Fetches the value of a function's parameter from the
|
||||
depths of the stack and puts it into a local variable.
|
||||
<p>
|
||||
The second byte of the instruction is the
|
||||
index of the variable. The third byte is a small
|
||||
integer offset - which is the number of the parameter
|
||||
you want.
|
||||
<p>
|
||||
Look at the number two down from the top of the stack
|
||||
(which should be
|
||||
the number of parameters of a recently called
|
||||
function).
|
||||
<p>
|
||||
Now copy the stack element at
|
||||
<code> sp - ( nargs + 2 ) + offset </code>
|
||||
into the variable.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_POP </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Throws away the top element of the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_CALLEXT </H3>
|
||||
INTRUCTION BYTES: 3
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The second byte of the instruction is the index of
|
||||
a PSL 'extension function', the third
|
||||
is the number of arguments being passed to it.
|
||||
<p>
|
||||
Pop that number of values off the stack and pass them
|
||||
to the extension function.
|
||||
<p>
|
||||
Call the extension function.
|
||||
Push the result onto the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_CALL </H3>
|
||||
INTRUCTION BYTES: 6
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> [The number of aguments will already have been pushed
|
||||
onto the stack.]
|
||||
<p>
|
||||
The four bytes after the instruction is the function address.
|
||||
The fifth byte is the number of arguments.
|
||||
<p>
|
||||
Push return address.<br>
|
||||
PC = address of function.
|
||||
<p>
|
||||
popNumber ( &result ) ;<br>
|
||||
pc = popInt () ;<br>
|
||||
nargs = popInt () ;<br>
|
||||
popVoid ( nargs ) ;<br>
|
||||
pushNumber ( &result ) ;</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_STACK_DUPLICATE </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Duplicate the top element of the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_EXCHANGE </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Exchange the top two elements of the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<H3> OPCODE_LESS </H3>
|
||||
<H3> OPCODE_LESSEQUAL </H3>
|
||||
<H3> OPCODE_GREATER </H3>
|
||||
<H3> OPCODE_GREATEREQUAL </H3>
|
||||
<H3> OPCODE_NOTEQUAL </H3>
|
||||
<H3> OPCODE_EQUAL </H3>
|
||||
<H3> OPCODE_ADD </H3>
|
||||
<H3> OPCODE_SUB </H3>
|
||||
<H3> OPCODE_SHIFTLEFT </H3>
|
||||
<H3> OPCODE_SHIFTRIGHT </H3>
|
||||
<H3> OPCODE_OROR </H3>
|
||||
<H3> OPCODE_ANDAND </H3>
|
||||
<H3> OPCODE_OR </H3>
|
||||
<H3> OPCODE_AND </H3>
|
||||
<H3> OPCODE_XOR </H3>
|
||||
<H3> OPCODE_DIV </H3>
|
||||
<H3> OPCODE_MOD </H3>
|
||||
<H3> OPCODE_MULT </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Pop the top element from the stack and operate on it
|
||||
and the next element down - leaving the result on
|
||||
the stack in it's place. So (for example) if the
|
||||
operation was 'SUB' (Subtract), and A is on top of
|
||||
the stack and B is beneath it - then the result of
|
||||
this operation would be to leave (B-A) on the stack
|
||||
with no sign of either A or B.
|
||||
<p>
|
||||
The 'ADD' operator also works with strings by concatenating
|
||||
them.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_NOT </H3>
|
||||
<H3> OPCODE_TWIDDLE </H3>
|
||||
<H3> OPCODE_NEG </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Perform the C unary '!', '~' or '-' operator on the top
|
||||
element of the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_PAUSE </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Informs application program that the script wishes
|
||||
to be paused until next frame.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_HALT </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Informs the application that the script wishes to halt.
|
||||
Even if the application ignores this request, the script
|
||||
will continue looping at this location for ever.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_PEEK_JUMP_TRUE </H3>
|
||||
<H3> OPCODE_PEEK_JUMP_FALSE </H3>
|
||||
INTRUCTION BYTES: 3
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The two bytes at the end of the instruction contain
|
||||
an address. Inspect the number off the top of the stack
|
||||
(without popping it) - and branch to the specified
|
||||
instruction if the value is TRUE (or FALSE as applicable).</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_JUMP_TRUE </H3>
|
||||
<H3> OPCODE_JUMP_FALSE </H3>
|
||||
INTRUCTION BYTES: 3
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The two bytes at the end of the instruction contain
|
||||
an address. POP the number off the top of the stack
|
||||
(without popping it) - and branch to the specified
|
||||
instruction if the value is TRUE (or FALSE as applicable).</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_JUMP </H3>
|
||||
INTRUCTION BYTES: 3
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The two bytes at the end of the instruction contain
|
||||
an address. Jump to that address.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_PUSH_VARIABLE </H3>
|
||||
INTRUCTION BYTES: 2
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The second byte of the instruction is the index of
|
||||
a variable. The value of that variable is pushed onto
|
||||
the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_POP_ADD_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_SUB_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_MUL_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_MOD_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_DIV_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_AND_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_OR_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_XOR_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_SHL_VARIABLE </H3>
|
||||
<H3> OPCODE_POP_SHR_VARIABLE </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Three things are on the stack when this function is called.<br>
|
||||
The thing on top is the result of an expression evaluation.<br>
|
||||
The thing beneath that is the index of a variable.<br>
|
||||
The thing beneath that is the dimension of the variable.<br>
|
||||
The value is added to/subtracted from/multiplied by/etc
|
||||
the variable - and stored back into the variable.<br>
|
||||
The new value of the variable is left on the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_POP_VARIABLE </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> Three things are on the stack when this function is called.<br>
|
||||
The thing on top is the result of an expression evaluation.<br>
|
||||
The thing beneath that is the index of a variable.<br>
|
||||
The thing beneath that is the dimension of the variable.<br>
|
||||
The value is stored into the variable.<br>
|
||||
The new value of the variable is left on the stack.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_SET_INT_ARRAY </H3>
|
||||
<H3> OPCODE_SET_FLOAT_ARRAY </H3>
|
||||
<H3> OPCODE_SET_STRING_ARRAY </H3>
|
||||
INTRUCTION BYTES: 2
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The second byte of the instruction is the index of an array
|
||||
variable.<br>
|
||||
On the top of the stack is an integer.<br>
|
||||
This instruction allocates that number of elements of storage to
|
||||
the array.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_SET_INT_VARIABLE </H3>
|
||||
<H3> OPCODE_SET_FLOAT_VARIABLE </H3>
|
||||
<H3> OPCODE_SET_STRING_VARIABLE </H3>
|
||||
INTRUCTION BYTES: 2
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The second byte of the instruction is the index of a variable.<br>
|
||||
That variable is created, set to the appropriate type and
|
||||
initialised appropriately.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_FETCH </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The index of a variable is on top of the stack.<br>
|
||||
The thing beneath that is the dimension of the variable.<br>
|
||||
Replace those with the value of that variable.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_INCREMENT_FETCH </H3>
|
||||
<H3> OPCODE_DECREMENT_FETCH </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The index of a variable is on top of the stack.<br>
|
||||
The thing beneath that is the dimension of the variable.<br>
|
||||
Replace those
|
||||
with the value of that variable. Post-increment/decrement the
|
||||
variable.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H3> OPCODE_INCREMENT_LVALUE </H3>
|
||||
<H3> OPCODE_DECREMENT_LVALUE </H3>
|
||||
INTRUCTION BYTES: 1
|
||||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
EFFECT:
|
||||
</td>
|
||||
<td> The index and dimension of a variable is on top of the stack.<br>
|
||||
Increment/decrement the variable leaving the stack
|
||||
contents undisturbed.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
<address>
|
||||
<a href="http://www.sjbaker.org">Steve J. Baker.</a> <<a href="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</a>></address>
|
||||
</body>
|
||||
</html>
|
||||
55
doc/psl/index.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="PSL, PLIB, OpenGL, portable, script, language, Baker, Steve">
|
||||
<meta name="description" content="The PLIB Scripting Language (PSL) Library is a lightweight scripting language that is well suited for games or other interactive programs.">
|
||||
<title>The PLIB Scripting Language.</title>
|
||||
</head>
|
||||
<body text="#B5A642" bgcolor="#005000" link="#8FFF8F" vlink="#18A515" alink="#20336B" background="../marble.png">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<center>
|
||||
<h1>PSL: PLIB's Scripting Language.</h1></center>
|
||||
<center>By Steve Baker</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<H1>Introduction</H1>
|
||||
Whilst applications can use any suitable scripting
|
||||
language (Python, PERL, Lua, etc) in conjunction with PLIB, there are
|
||||
attractions to using PLIB's own scripting language: PSL.
|
||||
<p>
|
||||
In particular, in using PSL, you do not add any dependancies on
|
||||
your application. If the end user has the correct version of PLIB
|
||||
installed - then the scripting language is already there - for sure.
|
||||
<p>
|
||||
PSL is a very light-weight C-like language with some features borrowed
|
||||
from C++. It's also 'stackless' and very friendly to games applications.
|
||||
<p>
|
||||
There are two PSL documents:
|
||||
<ul>
|
||||
<li><a href="appl_guide.html">The PSL-enabled Applications Guide.</a>
|
||||
-- If you are planning on including a PSL interpreter into your program,
|
||||
(making it 'PSL-enabled') then you should read the Applications Guide.
|
||||
<li><a href="prog_guide.html">The PSL Programmers Guide.</a>
|
||||
-- If you are writing scripts for a PSL-enabled application, then you'll
|
||||
only need to read the Programmer's Guide.
|
||||
<li><a href="impl_guide.html">The PSL Implementation Guide.</a>
|
||||
-- Explains some of PSL's internals, especially, the byte-code
|
||||
virtual machine.
|
||||
</ul>
|
||||
<p>
|
||||
Each application can extend PSL by providing additional built-in
|
||||
functions - so if you are a PSL programer then you'll probably need to
|
||||
read the documentation for whatever PSL-enabled application
|
||||
you are writing for. If you are writing a PSL-enabled application, then
|
||||
you'd better sit down and WRITE that document!
|
||||
<hr>
|
||||
<address>
|
||||
<a href="http://www.sjbaker.org">Steve J. Baker.</a> <<a href="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</a>></address>
|
||||
</body>
|
||||
</html>
|
||||
209
doc/psl/prog_guide.html
Normal file
@@ -0,0 +1,209 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="PSL, PLIB, OpenGL, portable, script, language, Baker, Steve">
|
||||
<meta name="description" content="The PLIB Scripting Language (PSL) Library is a lightweight scripting language that is well suited for games or other interactive programs.">
|
||||
<title>The PLIB Scripting Language: Programming Guide.</title>
|
||||
</head>
|
||||
<body text="#B5A642" bgcolor="#005000" link="#8FFF8F" vlink="#18A515" alink="#20336B" background="../marble.png">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<center>
|
||||
<h1>The PLIB Scripting Language Programming Guide </h1></center>
|
||||
<center>By Steve Baker</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<H1>Introduction</H1>
|
||||
|
||||
This document explains how to write PSL programs.
|
||||
|
||||
<p>
|
||||
|
||||
How you actually run those programs depends on which PSL-enabled
|
||||
application you are running. There is a stand-alone PSL interpreter
|
||||
in plib/examples/src/psl/psl_demo - but it doesn't include any
|
||||
application-specific language extensions - so a PSL program
|
||||
that's written for a specific application may not run
|
||||
on <code>psl_demo</code>.
|
||||
|
||||
<p>
|
||||
|
||||
However, psl_demo is great for learning to write PSL scripts.
|
||||
|
||||
<H1>The PSL Language</H1>
|
||||
|
||||
PSL is designed to be as close to the C Programming
|
||||
Language - although we
|
||||
cut a few corners - we extended the language in a few places - and
|
||||
we consciously omitted other features that are dangerous in a
|
||||
scripting language.
|
||||
|
||||
<p>
|
||||
|
||||
The following C features are implemented much as you'd expect:
|
||||
<ul>
|
||||
<li> Types 'void', 'int' and 'float' (and arrays of those things).
|
||||
<li> Function definitions.
|
||||
<li> Global variable definitions.
|
||||
<li> Statement types:
|
||||
<ul>
|
||||
<li> Local variable definitions.
|
||||
<li> Static variable definitions.
|
||||
<li> "return"
|
||||
<li> "break"
|
||||
<li> "continue"
|
||||
<li> "for"
|
||||
<li> "do/while"
|
||||
<li> "switch/case/default"
|
||||
<li> "while"
|
||||
<li> "if"
|
||||
<li> "if/else"
|
||||
<li> "{}" compound statements.
|
||||
<li> Assignment statements.
|
||||
<li> Procedure calls.
|
||||
</ul>
|
||||
<li> Most Arithmetic operators.
|
||||
<li> Comments '/*' '*/'.
|
||||
<li> C preprocessor directives:
|
||||
<ul>
|
||||
<li> "#include"
|
||||
<li> "#define" without parameters.
|
||||
<li> "#undef"
|
||||
<li> "#ifdef/#endif"
|
||||
<li> "#ifdef/#else/#endif"
|
||||
<li> "#ifndef/#endif"
|
||||
<li> "#ifndef/#else/#endif"
|
||||
</ul>
|
||||
<li> Special characters in strings:
|
||||
<ul>
|
||||
<li> "\n"
|
||||
<li> "\r"
|
||||
<li> "\a"
|
||||
<li> "\b"
|
||||
<li> "\f"
|
||||
<li> "\t"
|
||||
<li> "\\"
|
||||
<li> "\""
|
||||
</ul>
|
||||
<li> Recursion, etc.
|
||||
</ul>
|
||||
|
||||
Some new features have been added that are not part of C:
|
||||
<ul>
|
||||
<li> "pause" -- Pause the program until next frame.
|
||||
<li> "string" data type (and arrays of strings).
|
||||
<li> Casts are unnecessary between compatible types.
|
||||
<li> C++ style '//' comments.
|
||||
<li> C++ style local variable declarations.
|
||||
</ul>
|
||||
Some features of C are NOT IMPLEMENTED in PSL:
|
||||
<ul>
|
||||
<li> Pointers.
|
||||
<li> Casts.
|
||||
<li> Dynamic Memory Allocation.
|
||||
<li> ',' and '?:' operators in expressions.
|
||||
<li> "static", "auto" and "register" storage class reserved words.
|
||||
<li> "char", "short", "unsigned", "signed", "long", "double".
|
||||
<li> "typedef"
|
||||
<li> "enum", "union", bitfields.
|
||||
<li> "goto".
|
||||
<li> "#if"
|
||||
<li> "#pragma"
|
||||
<li> "#define" with parameters.
|
||||
<li> 'f' and 'l' suffixes for float and long numbers.
|
||||
<li> All preprocessor directives must have the '#' as the
|
||||
very first character on the line - they cannot be
|
||||
preceded with whitespace.
|
||||
</ul>
|
||||
|
||||
The following features are "NOT IMPLEMENTED YET" - but will
|
||||
hopefully arrive soon:
|
||||
<ul>
|
||||
<li> Multiple variable definitions like 'int i, j, k ;'
|
||||
<li> Structs.
|
||||
<li> '\' to escape the end-of-line character in strings and macro's.
|
||||
<li> Parameter passing by name.
|
||||
<li> Many of C's standard library functions are needed.
|
||||
</ul>
|
||||
|
||||
<H1> Compatibility Notes: </H1>
|
||||
<H3> C++ style local variables. </H3>
|
||||
With PSL's C++ style locals, you can say things like this:
|
||||
<pre>
|
||||
|
||||
for ( int i = 0 ; i < 10 ; i++ ) /* Do something */ ;
|
||||
|
||||
</pre>
|
||||
In standard C++, the scope of the variable 'i' is from it's
|
||||
declaration to the end of the 'for' loop. However, Microsoft's
|
||||
Visual C++ uses an obsolete version of the C++ standard that
|
||||
allows the scope of 'i' to continue to the end of the block
|
||||
that contains the for loop. So:
|
||||
<p>
|
||||
WINDOWS USERS BEWARE: PSL IMPLEMENTS THIS CORRECTLY - *NOT* LIKE
|
||||
MSVC.
|
||||
|
||||
<H1>Hard Limits</H1>
|
||||
Currently there are hard limits in many places - the number of
|
||||
variables, the size of the program, the depth of nesting, etc.
|
||||
These limits will gradually be removed as PSL is developed.
|
||||
|
||||
<H1>Debugging PSL Programs</H1>
|
||||
|
||||
Specific PSL-enabled applications may have their own
|
||||
special features to assist with debugging - but all
|
||||
PSL-enabled applications support several 'shell variables'
|
||||
that enable certain debugging features.
|
||||
<p>
|
||||
When using a command line shell, you can set these
|
||||
variables using one of the following commands before
|
||||
you run your application:
|
||||
<pre>
|
||||
setenv VARIABLE value -- csh or tcsh
|
||||
export VARIABLE=value -- bash or sh
|
||||
set VARIABLE=value -- DOS shell
|
||||
</pre>
|
||||
<H3> Byte-Code Dump </H3>
|
||||
It's possible to view the byte code that PSL generated
|
||||
by setting the shell variable 'PSL_DUMP' to either:
|
||||
<ul>
|
||||
<li> <b>never</b> (the default) -- Never produce a dump unless
|
||||
the application demands it.
|
||||
<li> <b>on_error</b> -- Produce a dump whenever the PSL program
|
||||
fails to compile for whatever reason.
|
||||
<li> <b>always</b> -- Always produce a dump after the PSL program
|
||||
finishes compiling.
|
||||
</ul>
|
||||
<H3> Byte-Code Execution Trace </H3>
|
||||
It's possible to view the byte code as it's executed
|
||||
by setting the shell variable 'PSL_TRACE' to either:
|
||||
<ul>
|
||||
<li> <b>never</b> (the default) -- Never produce a trace unless
|
||||
the application demands it.
|
||||
<li> <b>always</b> -- Always produce a trace.
|
||||
</ul>
|
||||
When the execution trace is enabled, extra instructions will be
|
||||
inserted into the byte code to enable the PSL interpreter to
|
||||
produce debug indicating which lines of the source code are
|
||||
being traced.
|
||||
<H3> Byte-Code Stack Display </H3>
|
||||
If you have PSL_TRACE turned on (either via the config variable or
|
||||
by the application program), then the shell variable 'PSL_STACK'
|
||||
can be set to display the contents of the top eight stack locations
|
||||
as the program is traced. If PSL_TRACE is disabled then PSL_STACK
|
||||
has no effect.
|
||||
<ul>
|
||||
<li> <b>never</b> (the default) -- Never produce stack dumps
|
||||
within a trace.
|
||||
<li> <b>always</b> -- Always produce a stack dump within trace.
|
||||
</ul>
|
||||
<hr>
|
||||
<address>
|
||||
<a href="http://www.sjbaker.org">Steve J. Baker.</a> <<a href="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</a>></address>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
BIN
doc/puAux.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
54
doc/puAux/index.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>SSG Auxiliary Libraries.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<H1>PUI Auxiliary Libraries.</H1>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>
|
||||
by Steve Baker
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H2>Introduction</H2>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
PLIB/puAux is a suite of auxiliary libraries that build
|
||||
higher level classes on top of the basic PUI classes.
|
||||
<p>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<p>
|
||||
<H2>Conventions</H2>
|
||||
puAux is installed and named with the same
|
||||
conventions as the base PLIB libraries.
|
||||
<br>
|
||||
ie:
|
||||
<pre>
|
||||
/usr/include/plib/puAux.h
|
||||
/usr/lib/libplibpuaux.a
|
||||
</pre>
|
||||
<p>
|
||||
PLIB/puAux functions, classes and constants are all
|
||||
named with an 'pua' or 'PUA' prefix.
|
||||
<br>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
636
doc/pui/BasicPUI.html
Normal file
@@ -0,0 +1,636 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="John F. Fay">
|
||||
<meta name="GENERATOR" content="Mozilla/4.75 [en] (Win98; U) [Netscape]">
|
||||
<meta name="keywords" content="PUI, PLIB, OpenGL, UI, user, interface, library, portable, picoscopic, widget, GUI, fast, GLUT, introduction, callback, puButton, puButtonBox, puFrame, puInput, puMenuBar, puOneShot, puText, puInit">
|
||||
<meta name="description" content="The PLIB Picoscopic User Interface (PUI) Library is designed to be a simple, easy-to-use graphical user interface. It is based on the OpenGL graphics language and requires a windowing system, either the OpenGL Utility Toolkit (GLUT) or another similar one. This document's purpose is to provide an introduction to the basics of PUI.">
|
||||
<title>BasicPUI</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<center>
|
||||
<h1>
|
||||
Introduction to Using the Picoscopic User Interface</h1></center>
|
||||
|
||||
<center>
|
||||
<h1>
|
||||
John F. Fay</h1></center>
|
||||
|
||||
<center>
|
||||
<h1>October 18, 2000</h1>
|
||||
(Updated by <a href="mailto:ude@handshake.de">Sebastian Ude</a> on October 02, 2001)
|
||||
</center>
|
||||
|
||||
<h2>
|
||||
Contents</h2>
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td>1.</td>
|
||||
<td><a href="#Introduction: Graphical User Interfaces and">Introduction:
|
||||
Graphical User Interfaces and Windowed Programs</a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>2.</td>
|
||||
<td><a href="#Elementary PUI">Elementary PUI</a></td>
|
||||
</tr>
|
||||
|
||||
<tr><td></td>
|
||||
<td>2.1 <a href="#Creating User Interface Widgets">Creating User Interface
|
||||
Widgets</a></td>
|
||||
</tr>
|
||||
|
||||
<tr><td></td>
|
||||
<td>2.2 <a href="#Invoking PUI">Invoking PUI</a></td>
|
||||
</tr>
|
||||
|
||||
<tr><td></td>
|
||||
<td>2.3 <a href="#Widget Callbacks">Widget Callbacks</a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>3.</td>
|
||||
<td><a href="#Conclusion">Conclusion</a></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<h2>
|
||||
<a NAME="Introduction: Graphical User Interfaces and"></a>1. Introduction:
|
||||
Graphical User Interfaces and Windowed Programs</h2>
|
||||
The Picoscopic User Interface (PUI) is designed to be a simple, easy-to-use
|
||||
graphical user interface. It is based on the OpenGL graphics language
|
||||
and requires a windowing system, either the OpenGL Utility Toolkit (GLUT)
|
||||
or another similar one. The gentle reader is assumed either to be
|
||||
familiar with OpenGL and his windowing system or at least to have their
|
||||
manuals at hand.
|
||||
<p>Basic to a GUI is the idea of a widget. A widget is something
|
||||
that appears on the computer screen and which transfers data from the user
|
||||
to the program or from the program to the user. The user can activate
|
||||
a widget by pressing a key, clicking a mouse button, or by using some other
|
||||
input device. This lets the user send information to the program.
|
||||
A widget can also display text or a graphic, allowing the program to transfer
|
||||
information to the user.
|
||||
<p>A windowing system requires a specific style of program which differs
|
||||
from a text-based program in several fundamental ways. First, instead
|
||||
of starting at the beginning of a problem and stopping at the end, a windowed
|
||||
program starts by creating the windows and then enters an infinite loop
|
||||
in which it responds to user inputs. Second, instead of having a
|
||||
self-contained hierarchy of functions which call each other, a windowed
|
||||
program is controlled by the windowing system which calls functions as
|
||||
it sees fit. The following diagram shows the structure of a typical
|
||||
windowed program.
|
||||
<pre>
|
||||
|
||||
+------------------+
|
||||
| Main Program | The application developer
|
||||
| Set up window(s) | supplies this.
|
||||
| and widget(s) |
|
||||
+------------------+
|
||||
|
|
||||
V
|
||||
+----------------+
|
||||
| Window Manager | The window manager library
|
||||
| (like GLUT) | supplies this.
|
||||
+----------------+
|
||||
|
|
||||
+------+--------+---------------+---------------+----> etc.
|
||||
| | | |
|
||||
V V V V
|
||||
+----------+ +----------+ +----------+ +----------+
|
||||
| Window | | Window | | Window | | Window | The application
|
||||
| Mouse | | Keyboard | | Idle | | Display | developer
|
||||
| Callback | | Callback | | Callback | | Callback | supplies these.
|
||||
+----------+ +----------+ +----------+ +----------+
|
||||
| | | |
|
||||
V V V V
|
||||
+----------+ +----------+ May call +----------+
|
||||
| PUI | | PUI | PUI functions | PUI | PUI
|
||||
| Mouse | | Keyboard | for default | Display | supplies
|
||||
| Function | | Function | behaviors | Function | these.
|
||||
+----------+ +----------+ +----------+
|
||||
| |
|
||||
+-------+-------+
|
||||
|
|
||||
+-------+-------+---------------+------> etc.
|
||||
| | |
|
||||
V V V
|
||||
+----------+ +----------+ +----------+
|
||||
| Widget 1 | | Widget 2 | | Widget 3 | The application developer
|
||||
| Callback | | Callback | | Callback | supplies these.
|
||||
+----------+ +----------+ +----------+
|
||||
|
||||
</pre>
|
||||
<p>The functions that the application developer supplies are called "callbacks"
|
||||
because the windowing system or user interface system "calls back" into
|
||||
the application.
|
||||
<p>A windowed program with a user interface, then, consists of a main program
|
||||
and a set of callbacks. The callbacks may invoke other function in
|
||||
turn, but these are all arranged in hierarchical trees underneath the callbacks.
|
||||
<p>A windowed program executes differently from a typical hierarchical
|
||||
program as well. It begins with the main program setting up the window(s)
|
||||
and the user interface. The main program then calls the window manager,
|
||||
which contains an infinite loop and never returns control to the main program.
|
||||
(GLUT in particular has this behavior; I cannot speak for all window managers.)
|
||||
When the window manager needs to redraw the display that is shown on the
|
||||
screen, it calls the application's Window Display Callback. When
|
||||
the user moves the mouse or clicks a mouse button, the window manager calls
|
||||
the application's Window Mouse Callback. When the user presses a
|
||||
key on the keyboard, the window manager calls the application's Window
|
||||
Keyboard Callback. Other input devices cause the window manager to
|
||||
call other callbacks in the application. Finally, if the user hasn't
|
||||
done anything for a while, the window manager will call the application's
|
||||
Window Idle Callback.
|
||||
<p>In building a window callback, the application developer must be sure
|
||||
to call the appropriate PUI functions. The applications's Window
|
||||
Mouse Callback, for example, must call the PUI mouse function "puMouse"
|
||||
if the user interface is to process a mouse click. The application's
|
||||
Window Display Callback, besides rendering any graphics in the window,
|
||||
must also call the PUI display function "puDisplay" in order to display
|
||||
the widgets in the user interface.
|
||||
<p>When the application developer's window callback calls the appropriate
|
||||
PUI function, PUI determines which (if any) widget the user has just activated
|
||||
with his mouse, keyboard, or other input device. PUI then calls that
|
||||
widget's callback function which the application developer must supply
|
||||
and which provides the actual heart of the interface. The callback
|
||||
for an input widget will probably read the text that the user has typed
|
||||
there and pass it on to the application. The callback for a button
|
||||
widget may turn something in the program on or off. What a callback
|
||||
does is limited only by the application developer's imagination.
|
||||
<h2>
|
||||
<a NAME="Elementary PUI"></a>2. Elementary PUI</h2>
|
||||
Using the Picoscopic User Interface on an elementary level requires three
|
||||
things: setting up the user interface widgets, invoking PUI from
|
||||
the window callbacks, and supplying the widget callbacks.
|
||||
<p>PUI was written in C++, designed to be invoked from C++ programs.
|
||||
The following text and examples will assume a program written in C++.
|
||||
<h3>
|
||||
<a NAME="Creating User Interface Widgets"></a>2.1 Creating User Interface
|
||||
Widgets</h3>
|
||||
Most (or all) widgets have certain properties in common. These are:
|
||||
<ul>
|
||||
<li>
|
||||
position - the x- and y-coordinates, in pixels, of the lower left-hand
|
||||
corner of the widget relative to the lower left-hand corner of the window</li>
|
||||
|
||||
<li>
|
||||
size - the width and height of the widget, in pixels</li>
|
||||
|
||||
<li>
|
||||
callback - the application program's function which is called when the
|
||||
widget is activated</li>
|
||||
|
||||
<li>
|
||||
value - a number or character string that is associated with the widget</li>
|
||||
|
||||
<li>
|
||||
label - text that is printed next to the widget</li>
|
||||
|
||||
<li>
|
||||
legend - text that is printed inside the widget (some widgets only)</li>
|
||||
</ul>
|
||||
PUI supports other widget properties, but these are enough to allow the
|
||||
application developer to create a simple user interface.
|
||||
<p>Each widget in the Picoscopic User Interface is an object in C++.
|
||||
The application developer creates a widget by defining a variable to point
|
||||
to the object and creating a new object:
|
||||
<pre>
|
||||
|
||||
puButton *button = new puButton ( 10, 10, 100, 30 ) ;
|
||||
|
||||
</pre>
|
||||
<p>To set the properties of a widget, the application developer calls methods
|
||||
in the object:
|
||||
<pre>
|
||||
|
||||
button->setPosition ( x, y ) ; // Sets the position of the widget to
|
||||
(x, y)
|
||||
button->setSize ( w, h ) ; // Sets the size of the widget to (w, h)
|
||||
button->setCallback ( widget_cb ) ; // Sets the callback to
|
||||
"void widget_cb ( puObject *ob )"
|
||||
button->setLegend ( "Press Me" ) ; // Sets the legend
|
||||
button->setLabel ( "A Button:" ) ; // Sets the label
|
||||
button->setLabelPlace ( PUPLACE_LOWER_LEFT ) ; // Makes the label print on the button's
|
||||
left
|
||||
|
||||
</pre>
|
||||
<p>Other allowed values for the label position are:
|
||||
|
||||
<ul>
|
||||
<li>PUPLACE_ABOVE_LEFT
|
||||
<li>PUPLACE_ABOVE_RIGHT
|
||||
<li>PUPLACE_TOP_LEFT
|
||||
<li>PUPLACE_TOP_CENTERED
|
||||
<li>PUPLACE_TOP_RIGHT
|
||||
<li>PUPLACE_UPPER_LEFT
|
||||
<li>PUPLACE_UPPER_RIGHT
|
||||
<li>PUPLACE_CENTERED_LEFT
|
||||
<li>PUPLACE_CENTERED_RIGHT
|
||||
<li>PUPLACE_LOWER_LEFT
|
||||
<li>PUPLACE_LOWER_RIGHT (default)
|
||||
<li>PUPLACE_BOTTOM_LEFT
|
||||
<li>PUPLACE_BOTTOM_CENTERED
|
||||
<li>PUPLACE_BOTTOM_RIGHT
|
||||
<li>PUPLACE_BELOW_LEFT
|
||||
<li>PUPLACE_BELOW_RIGHT
|
||||
</ul>
|
||||
<p>For a detailed description of these have a look at the
|
||||
<a href="http://plib.sf.net/pui/">PUI Programmers Guide</a>.
|
||||
<p>All of these calls are optional. If the application developer
|
||||
does not want to label a widget, he simply does not call "setLabel" or
|
||||
"setLabelPlace". Similarly, if he has set the widget's position and
|
||||
size while creating the widget, there is no need to call "setPosition"
|
||||
or "setSize".
|
||||
<p>The following subsections describe some of the widget types that PUI
|
||||
supports.
|
||||
<h4>
|
||||
2.1.1 Button</h4>
|
||||
The button ("puButton") is a rectangle, usually containing a legend, which
|
||||
is activated when the user clicks the mouse on it. It has two possible
|
||||
values, off and on; its actual value changes each time the user clicks
|
||||
on it.
|
||||
<p>The button has two possible methods of construction:
|
||||
<ul>
|
||||
<li>
|
||||
puButton ( x1, y1, x2, y2 ) - creates a button with lower left-hand coordinates
|
||||
of (x1, y1) and with upper right-hand coordinates of (x2, y2)</li>
|
||||
|
||||
<li>
|
||||
puButton ( x1, y1, "text" ) - creates a button with lower left-hand coordinates
|
||||
of (x1, y1) and containing the text "text". The size is set by the
|
||||
size of the text.</li>
|
||||
</ul>
|
||||
|
||||
<h4>
|
||||
2.1.2 Button Box</h4>
|
||||
The button box ("puButtonBox") is a large rectangle containing a set of
|
||||
buttons, each with text next to it, which the user can select. It
|
||||
is sometimes called a radio button. It is created by creating a null-terminated
|
||||
list of labels and then by calling the constructor function:
|
||||
<pre>
|
||||
|
||||
char **labels = { "Label1", "Label2", "This is Label3", "Four", NULL } ;
|
||||
puButtonBox my_box = new puButtonBox ( x1, x2, y1, y2, labels, <0|1> ) ;
|
||||
|
||||
</pre>
|
||||
<p>This creates a button box with lower left-hand coordinates of (x1, y1)
|
||||
and upper right-hand coordinates (x2, y2). The number of buttons
|
||||
is specified by the number of entries in the "labels" array; each string
|
||||
before the NULL gets a button. The final argument in the constructor
|
||||
specifies whether the user can select multiple buttons (0) or whether selecting
|
||||
a new button will deactivate the previously-selected button (1).
|
||||
<p>The button box should not be given a legend.
|
||||
<h4>
|
||||
2.1.3 Frame</h4>
|
||||
The frame ("puFrame") is a rectangular area that provides a background
|
||||
for other widgets. It should be defined before any other widgets
|
||||
that go inside it or else it will cover them up. It is constructed
|
||||
by the following function call:
|
||||
<ul>
|
||||
<li>
|
||||
puFrame ( x1, y1, x2, y2 ) - creates a frame with lower left-hand coordinates
|
||||
of (x1, y1) and with upper right-hand coordinates of (x2, y2)</li>
|
||||
</ul>
|
||||
The frame should not be given a legend. It does not support a callback
|
||||
either.
|
||||
<h4>
|
||||
2.1.4 Input Box</h4>
|
||||
The input box ("puInput") is a rectangular area into which the user can
|
||||
type text. The user must first click the mouse inside the area and
|
||||
then type the text. He concludes by pressing <Enter> or <Tab>
|
||||
or by clicking the mouse outside the input box.
|
||||
<p>An input box is constructed by the following function call:
|
||||
<ul>
|
||||
<li>
|
||||
puInput ( x1, y1, x2, y2 ) - creates an input box with lower left-hand
|
||||
coordinates of (x1, y1) and with upper right-hand coordinates of (x2, y2)</li>
|
||||
</ul>
|
||||
The input box should not be given a legend.
|
||||
<h4>
|
||||
2.1.5 Menu Bar</h4>
|
||||
The menu bar ("puMenuBar") is easily the most complicated widget written
|
||||
up here. It consists of a horizontal bar containing buttons which
|
||||
the user can click on. The bar is always situated on the left-hand
|
||||
edge of the window and is usually in the upper left-hand corner.
|
||||
It is constructed by the following function call:
|
||||
<br>
|
||||
<ul>
|
||||
<li>
|
||||
puMenuBar *menu = puMenuBar ( y ) - creates a menu bar with the lower left-hand
|
||||
corner "y" pixels above the lower left-hand corner of the window.
|
||||
A value of -1 for "y" will put the menu bar in the upper left-hand corner
|
||||
of the window.</li>
|
||||
</ul>
|
||||
|
||||
<p><br>Once the menu bar has been constructed, it must be loaded with its
|
||||
entries and submenus. A submenu is the list that drops down when
|
||||
the user clicks on an entry in the menu. A typical menu bar will
|
||||
have the entries "File", "Edit", "Search", and "Help". Under the
|
||||
"File" entry is a submenu with entries "New", "Open", "Save", "Save As",
|
||||
a separator, "Page Setup", "Print", another separator, and "Exit".
|
||||
Each entry in the submenu has its own widget callback function. To
|
||||
create a submenu, the application developer must first create two null-terminated
|
||||
lists of character strings and callback functions:
|
||||
<pre>
|
||||
|
||||
char *file_submenu [] = { "Exit", "-----", "Print", "Page Setup", "-----",
|
||||
"Save As", "Save", "Open", "New", NULL } ;
|
||||
puCallback file_submenu_cb[] = { exit_cb, NULL, print_cb, page_setup_cb, NULL,
|
||||
save_as_cb, save_cb, open_cb, new_cb, NULL } ;
|
||||
|
||||
</pre>
|
||||
<p>Notice here that the submenu entries are placed in the list from bottom
|
||||
to top. After the last character string is a NULL entry; this tells
|
||||
PUI that there aren't any more entries in the submenu. The callbacks
|
||||
for the separators are also null, indicating that there is no callback
|
||||
for the separator. The submenu is added to the menu bar with a call
|
||||
to the "add_submenu" function:
|
||||
<pre>
|
||||
|
||||
menu->add_submenu ( "File", file_submenu, file_submenu_cb ) ;
|
||||
|
||||
</pre>
|
||||
<p>Further calls to "add_submenu" add the other submenus:
|
||||
<pre>
|
||||
|
||||
char *edit_submenu [] = { "Select All", "-----", "Paste", "Copy", "Cut",
|
||||
"-----", "Undo", NULL } ;
|
||||
puCallback edit_submenu_cb[] = { select_all_cb, NULL, paste_cb, copy_cb, cut_cb,
|
||||
NULL, undo_cb, NULL } ;
|
||||
menu->add_submenu ( "Edit", edit_submenu, edit_submenu_cb ) ;
|
||||
|
||||
char *search_submenu [] = { "Find Next", "Find", NULL } ;
|
||||
puCallback search_submenu_cb[] = { find_next_cb, find_cb, NULL } ;
|
||||
menu->add_submenu ( "Search", search_submenu, search_submenu_cb ) ;
|
||||
|
||||
char *help_submenu [] = { "About", "Help", NULL } ;
|
||||
puCallback help_submenu_cb[] = { about_cb, help_cb, NULL } ;
|
||||
menu->add_submenu ( "Help", help_submenu, help_submenu_cb ) ;
|
||||
|
||||
</pre>
|
||||
<p>When the last submenu has been added, the application developer must
|
||||
close the menu bar:
|
||||
<pre>
|
||||
|
||||
menu->close() ;
|
||||
|
||||
</pre>
|
||||
<p>This is absolutely necessary or else PUI will think that any widgets
|
||||
the application defines later are supposed to go into the menu bar.
|
||||
<p>The menu bar does not support a legend. It does not support a
|
||||
callback itself, although all the entries in the submenus certainly do
|
||||
support callbacks. Repositioning and resizing a menu bar will be
|
||||
problematic as well. There may be an occasion when a menu bar can
|
||||
take a label, but this would be rare.
|
||||
<h4>
|
||||
2.1.6 One-Shot Button</h4>
|
||||
The one-shot button ("puOneShot") is a button whose value is always reset
|
||||
immediately to zero after it has been activated. In all other respects
|
||||
it is the same as the regular button. It is created in the same way
|
||||
as the button:
|
||||
<ul>
|
||||
<li>
|
||||
puOneShot ( x1, y1, x2, y2 ) - creates a one-shot button with lower left-hand
|
||||
coordinates of (x1, y1) and with upper right-hand coordinates of (x2, y2)</li>
|
||||
|
||||
<li>
|
||||
puOneShot ( x1, y1, "text" ) - creates a one-shot button with lower left-hand
|
||||
coordinates of (x1, y1) and containing the text "text". The size
|
||||
is set by the size of the text.</li>
|
||||
</ul>
|
||||
|
||||
<h4>
|
||||
2.1.7 Text Box</h4>
|
||||
The text box ("puText") is an output-only widget which displays a character
|
||||
string. It is created by the following constructor:
|
||||
<ul>
|
||||
<li>
|
||||
puText ( x, y ) - creates a text box at the point (x, y) in the window</li>
|
||||
</ul>
|
||||
The application actually adds the text by assigning a label and a label
|
||||
place to the text box. The label place will determine where relative
|
||||
to the position of the text box the text itself will appear.
|
||||
<h3>
|
||||
<a NAME="Invoking PUI"></a>2.2 Invoking PUI</h3>
|
||||
The summary of invoking PUI is very simple:
|
||||
<ul>
|
||||
<li>
|
||||
At the beginning of the program, before creating any widgets, the application
|
||||
must call the function "puInit ()".</li>
|
||||
|
||||
<li>
|
||||
If the application developer wants PUI to process a mouse click, he must
|
||||
have the application call the function "puMouse ( button, updown, x, y
|
||||
)".</li>
|
||||
|
||||
<li>
|
||||
If the application developer wants PUI to process a mouse motion, he must
|
||||
have the application call the function "puMouse ( x, y )".</li>
|
||||
|
||||
<li>
|
||||
If the application developer wants PUI to process a key from the keyboard,
|
||||
he must have the application call the function "puKeyboard ( key, updown
|
||||
)".</li>
|
||||
|
||||
<li>
|
||||
If the application developer wants PUI to display the user interface, he
|
||||
must have the application call the function "puDisplay ()".</li>
|
||||
</ul>
|
||||
The application developer must create window callbacks for the window manager
|
||||
to call when the user interacts with the computer. The following
|
||||
are taken from GLUT, but another window manager will have similar callback
|
||||
requirements.
|
||||
<h4>
|
||||
2.2.1 Main Program Code</h4>
|
||||
In the main program, the application developer usually places the following
|
||||
or similar statements:
|
||||
<pre>
|
||||
|
||||
// Create the GLUT window and the OpenGL context
|
||||
|
||||
glutCreateWindow ( "PUI Application" ) ;
|
||||
|
||||
// Set up the GLUT window callbacks
|
||||
|
||||
glutDisplayFunc ( displayfn ) ; // display the window
|
||||
glutMouseFunc ( mousefn ) ; // process mouse clicks
|
||||
glutMotionFunc ( motionfn ) ; // process mouse moves
|
||||
glutPassiveMotionFunc ( motionfn ) ;
|
||||
glutKeyboardFunc ( keyboardfn ) ; // process key presses
|
||||
glutIdleFunc ( displayfn ) ; // what to do when nothing's happening
|
||||
|
||||
// Initialize PUI
|
||||
|
||||
puInit () ;
|
||||
|
||||
// Set up the widgets here
|
||||
</pre>
|
||||
<h4>
|
||||
2.2.2 Window Callbacks</h4>
|
||||
The application's window callbacks should generally look like this.
|
||||
Again, these are written assuming GLUT; other window managers should be
|
||||
similar.
|
||||
<pre>
|
||||
|
||||
void displayfn ( void )
|
||||
{
|
||||
// stuff to display any non-PUI drawings
|
||||
|
||||
// update any PUI widgets that update by themselves ... like a timer display
|
||||
|
||||
// redisplay PUI
|
||||
|
||||
puDisplay () ;
|
||||
|
||||
// Finish up
|
||||
|
||||
glutSwapBuffers () ;
|
||||
glutPostRedisplay () ;
|
||||
}
|
||||
|
||||
void mousefn ( int button, int updown, int x, int y )
|
||||
{
|
||||
// Invoke the PUI mouse function
|
||||
|
||||
puMouse ( button, updown, x, y ) ;
|
||||
glutPostRedisplay () ;
|
||||
}
|
||||
|
||||
void motionfn ( int x, int y )
|
||||
{
|
||||
// Invoke the PUI mouse motion function
|
||||
|
||||
puMouse ( x, y ) ;
|
||||
glutPostRedisplay () ;
|
||||
}
|
||||
|
||||
void keyboardfn ( unsigned char key, int, int )
|
||||
{
|
||||
// Invoke the PUI keyboard function
|
||||
|
||||
puKeyboard ( key, PU_DOWN ) ;
|
||||
glutPostRedisplay () ;
|
||||
}
|
||||
|
||||
</pre>
|
||||
<h4>
|
||||
2.2.3 Miscellaneous Other Tidbits</h4>
|
||||
If the application developer wishes to delete a widget, he should not delete
|
||||
the object directly. Instead he should call the PUI function "puDeleteObject
|
||||
( ob )" with his widget pointer as the argument.
|
||||
<h3>
|
||||
<a NAME="Widget Callbacks"></a>2.3 Widget Callbacks</h3>
|
||||
The final pieces to the puzzle are the widget callbacks. These are
|
||||
of the form
|
||||
<pre>
|
||||
|
||||
void widget_cb ( puObject *ob )
|
||||
{
|
||||
// code goes here
|
||||
}
|
||||
|
||||
</pre>
|
||||
<p>where "puObject" is the C++ type for a generic widget. When PUI
|
||||
calls a widget callback, it passes to it the address of the widget whose
|
||||
activation caused the callback. This is useful because it allows
|
||||
a single callback for multiple widgets:
|
||||
<pre>
|
||||
|
||||
void widget_cb ( puObject *ob )
|
||||
{
|
||||
if ( ob == button ) // the button from section 2.1
|
||||
{
|
||||
...
|
||||
}
|
||||
else if ( ob == my_box ) // the button box from section 2.1.2
|
||||
{
|
||||
...
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ( "Error - unknown widget" ) ;
|
||||
}
|
||||
}
|
||||
|
||||
</pre>
|
||||
<p>A widget callback needs to be either a regular function (global
|
||||
or defined in the same file that contains the widget's definition) or a
|
||||
static member function of a class. It cannot be a regular member
|
||||
function of a class.
|
||||
<h4>
|
||||
2.3.1 Widget Values</h4>
|
||||
It is frequently very useful in a callback to know the value of a widget.
|
||||
A PUI widget has an integer value, a floating-point value, and a character
|
||||
string value. These values are kept synchronized as much as possible.
|
||||
For example, if the application assigns an integer value to a widget, the
|
||||
floating-point value is set equal to the integer and the integer is printed
|
||||
into the character string.
|
||||
<p>An application program can use the following function to retrieve the
|
||||
value of a PUI widget ("ob" is the pointer to the object):
|
||||
<pre>
|
||||
|
||||
int ivalue1 = ob->getValue () ; // No argument, return the integer value
|
||||
|
||||
int ivalue2 ;
|
||||
ob->getValue ( &ivalue2 ) ; // Place the integer value in the argument
|
||||
|
||||
float fvalue ;
|
||||
ob->getValue ( &fvalue ) ; // Place the floating-point value in the argument
|
||||
|
||||
char svalue[PUSTRING_MAX] ; // Create a string
|
||||
ob->getValue ( svalue ) ; // Copy the string value into the argument
|
||||
// Note that the argument is of type "char *"
|
||||
|
||||
char *sptr ;
|
||||
ob->getValue ( &sptr ) ; // Have the pointer point to the string value
|
||||
// Note that the argument is of type "char **"
|
||||
|
||||
</pre>
|
||||
<p>The values of the various widgets have the following meanings:
|
||||
<ul>
|
||||
<li>
|
||||
Button: 0 - turned off; 1 - turned on</li>
|
||||
|
||||
<li>
|
||||
Button Box: If only one button can be activated at a time, the value
|
||||
is the number of the button which is activated. If multiple buttons
|
||||
can be activated at once, then the bits in the integer value corresponding
|
||||
to the activated buttons are one and the bits corresponding to the inactive
|
||||
buttons are zero.</li>
|
||||
|
||||
<li>
|
||||
Frame: no value</li>
|
||||
|
||||
<li>
|
||||
Input: the string value is the character string that the user has
|
||||
typed in</li>
|
||||
|
||||
<li>
|
||||
Menu Bar: no value</li>
|
||||
|
||||
<li>
|
||||
One Shot Button: value is always zero</li>
|
||||
|
||||
<li>
|
||||
Text: no value</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="Conclusion"></a>3. Conclusion</h2>
|
||||
This has been offered as an introduction to the Picoscopic User Interface.
|
||||
It makes no warranty as to its accuracy although efforts have been made
|
||||
to make it correct. It is offered in the hope that the gentle reader
|
||||
will find it useful.
|
||||
<p>The PUI has considerably greater capabilities than have been listed
|
||||
here. There are well over a dozen additional types of widgets.
|
||||
Additionally, the application developer can do many more things with this
|
||||
widgets than have been described here.
|
||||
<p>"As to more than these, my son, beware. Of the making of many
|
||||
books there is no end, and in much study there is weariness for the flesh."
|
||||
- Ecclesiastes 12:12
|
||||
</body>
|
||||
</html>
|
||||
171
doc/pui/FAQ.html
Normal file
@@ -0,0 +1,171 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="keywords" content="PUI, PLIB, OpenGL, UI, user, interface, library, portable, picoscopic, MUI, widget, GUI, fast, FAQ, Baker, Steve">
|
||||
<META name="description" content="Here are some questions that have been asked about the PLIB Picoscopic User Interface library.">
|
||||
<TITLE>The Picoscopic User Interface: FAQ list.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="pooh.png" ALT="Imagine Pooh Here" width=60 height=77>
|
||||
</TD>
|
||||
<TD>
|
||||
<H1>PUI: A Picoscopic User Interface</H1>
|
||||
<H1>Frequently Asked Questions List.</H1>
|
||||
By Steve Baker
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
Here are some questions that have been asked about PUI:
|
||||
<ul>
|
||||
<li><A HREF="#Q1">Q1: Can I build a Windoze DLL for PUI?</A>
|
||||
<li><A HREF="#Q2">Q2: Which versions of OpenGL and GLUT will support PUI?</A>
|
||||
<li><A HREF="#Q3">Q3: Which machines/operating systems can run PUI?</A>
|
||||
<li><A HREF="#Q4">Q4: Is PUI stable? Are there known bugs?</A>
|
||||
<li><A HREF="#Q5">Q5: What changes do you expect to make in future releases?</A>
|
||||
<li><A HREF="#Q6">Q6: Where can I ask questions?</A>
|
||||
<li><A HREF="#Q7">Q7: What's the difference between PUI and MUI?</A>
|
||||
<li><A HREF="#Q8">Q8: Are there restrictions on using PUI?</A>
|
||||
<li><A HREF="#Q9">Q9: Do I have to write in C++ to use PUI?</A>
|
||||
</ul>
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
<H2><A NAME="Q1">Q1: Can I build a Windoze DLL for PUI?</A></H2>
|
||||
|
||||
Not from the present sources. Some Windoze compilers
|
||||
require an '_export' directive on functions or classes
|
||||
that are to be exported from the DLL. This is ugly and
|
||||
I refuse to add non-standard syntax to the library just
|
||||
to pander to a disgusting Windoze-ism. PUI is a VERY
|
||||
small library and there is really no need for it to
|
||||
be a DLL anyway.
|
||||
|
||||
<H2><A NAME="Q2">Q2: Which versions of OpenGL and GLUT will support PUI?</A></H2>
|
||||
|
||||
In principal, any version of GLUT since 2.0 and any
|
||||
reasonably compliant OpenGL (including Mesa) should
|
||||
be happy to support PUI.
|
||||
|
||||
<H2><A NAME="Q3">Q3: Which machines/operating systems can run PUI?</A></H2>
|
||||
|
||||
AFAIK, any machine with C++, OpenGL (or Mesa) and
|
||||
GLUT will run PUI programs without problems.
|
||||
|
||||
<H2><A NAME="Q4">Q4: Is PUI stable? Are there known bugs?</A></H2>
|
||||
|
||||
So far, there have only been a couple of bugs reported
|
||||
in PUI - the most significant is that the menu bar doesn't
|
||||
work properly after the GLUT window has been resized.
|
||||
<p>
|
||||
The 'complex' demo program seems to fail when a dialog
|
||||
box is dismissed. This may be because the dialog object
|
||||
is deleted inside a callback within a member function of
|
||||
that object. This problem only appears under Microsoft
|
||||
operating systems and so is hard for me to track down.
|
||||
The simplest thing may be for me to change the demo
|
||||
program so it just doesn't work that way.
|
||||
|
||||
<H2><A NAME="Q5">Q5: What changes do you expect to make in future releases?</A></H2>
|
||||
|
||||
I am generally unhappy about the somewhat inconsistant
|
||||
set of constructor functions for the various widgets.
|
||||
Some auto-size their widgets, some take the size directly,
|
||||
others have both. This needs to be made much more consistant
|
||||
across all the widget classes.
|
||||
<p>
|
||||
I want to write a cute interactive GUI designer program to
|
||||
write C++ source code for the PUI constructor functions
|
||||
automatically. Something along the lines of the XForms
|
||||
'fdesign' or the FLTK 'fluid' programs.
|
||||
<p>
|
||||
If GLUT ever changes to allow applications to run without
|
||||
calling 'glutMainLoop', I will greatly improve the Dialog
|
||||
box API which sucks right now. It would also spur me on
|
||||
to write a File Selector widget. The problem is that
|
||||
you'd really like to be able to write things like:
|
||||
<pre>
|
||||
|
||||
if ( ( fd = fopen ( "babble", "w" ) ) == NULL )
|
||||
{
|
||||
if ( puYesNoDialog ( "Can't open babble file",
|
||||
"Do you want to continue?" ) )
|
||||
return ;
|
||||
else
|
||||
exit ( 1 ) ;
|
||||
}
|
||||
|
||||
</pre>
|
||||
However, the 'puYesNoDialog' function can't get it's
|
||||
graphics up on the screen without returning to GLUT's
|
||||
main loop - and it can't do that since the call to
|
||||
puYesNoDialog is in a GLUT callback function.
|
||||
Look at the ugly code in 'complex' to see how to do
|
||||
this kind of thing without this facility.
|
||||
<p>
|
||||
Finally, the appearance of PUI's widgets is somehow
|
||||
not as neat as some other GUI's such as MUI and Motif.
|
||||
This should be pretty easy to fix - and it's something
|
||||
on the 'to do' list.
|
||||
|
||||
<H2><A NAME="Q6">Q6: Where can I ask questions?</A></H2>
|
||||
|
||||
Since PUI is now a part of <A HREF="../index.html">PLIB</A>,
|
||||
all user level questions, development issues and announcements
|
||||
are handled from the PLIB mailing list.
|
||||
|
||||
<H2><A NAME="Q7">Q7: What's the difference between PUI and MUI?</A></H2>
|
||||
|
||||
The main reason I wrote PUI was my disappointment
|
||||
with MUI.
|
||||
<p>
|
||||
MUI has now been 'abandoned' by it's author (Tom Davis)
|
||||
who none-the-less retains copyright over it. MUI has
|
||||
several known bugs - and the only known documentation
|
||||
was written by me - and I have never actually written
|
||||
a real application using it!
|
||||
<p>
|
||||
The MUI library (distributed with GLUT) takes
|
||||
over all of the GLUT callbacks - this makes it
|
||||
very hard to write general purpose programs with
|
||||
MUI.
|
||||
<p>
|
||||
In contrast, it is very easy to add PUI widgets to
|
||||
an existing OpenGL/GLUT application with only a
|
||||
couple of lines of code.
|
||||
<p>
|
||||
PUI also works quite well with 3D hardware such
|
||||
as 3Dfx Voodoo that 'take over' the screen. Since
|
||||
MUI and GLUT both create their menu's using the
|
||||
underlying windowing system's GUI, these menu's
|
||||
won't be visible on that kind of hardware. PUI
|
||||
uses only OpenGL to do all kinds of widgets, so
|
||||
portability onto 3Dfx hardware is assured.
|
||||
|
||||
<H2><A NAME="Q8">Q8: Are there restrictions on using PUI ?</A></H2>
|
||||
|
||||
PUI is OpenSource under the terms of LGPL. If for some reason,
|
||||
you find LGPL too restrictive and if you wish to use it in some
|
||||
major project then please talk to me about it - I can be flexible.
|
||||
|
||||
<H2><A NAME="#Q9">Q9: Do I have to write in C++ to use PUI?</A></H2>
|
||||
|
||||
Yes - there will never be a {insert favorite non-C++ language here}
|
||||
version of PUI.
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">Steve J. Baker.</A> <<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
doc/pui/complex.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
2210
doc/pui/index.html
Normal file
BIN
doc/pui/labelplaces.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
doc/pui/legendplaces.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
doc/pui/pooh.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
doc/pui/puArrowButton.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
doc/pui/puBiSlider.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
doc/pui/puButton.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
doc/pui/puButtonBox.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
doc/pui/puComboBox.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
doc/pui/puDial.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
doc/pui/puDialogBox.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
doc/pui/puFileSelector.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
doc/pui/puFrame.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
doc/pui/puInput.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
doc/pui/puLargeInput.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
doc/pui/puListBox.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
doc/pui/puMenuBar.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
doc/pui/puOneShot.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
doc/pui/puPopupMenu.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
doc/pui/puSelectBox.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
doc/pui/puSlider.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
doc/pui/puText.png
Normal file
|
After Width: | Height: | Size: 609 B |
BIN
doc/pui/puTriSlider.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
doc/pui/puVerticalMenu.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
doc/pui/simple.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
203
doc/pw/index.html
Normal file
@@ -0,0 +1,203 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="keywords" content="PW, PLIB, OpenGL, window, library, portable, interface, games, Baker, Steve, pwInit">
|
||||
<META name="description" content="The PLIB minimal Windowing Library (PW) is a portable interface that makes it as simple as possible to make an OpenGL application that can open a single window and read the mouse and keyboard. It is a wrapper to make the various underlying OS mechanisms look the same to application code.">
|
||||
<TITLE>A PLIB Windowing Library.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<H1>A PLIB Windowing Library.</H1>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>
|
||||
by Steve Baker
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H2>Introduction</H2>
|
||||
PW is now just one component of <A HREF="../index.html">PLIB</A>.
|
||||
<p>
|
||||
The PLIB minimal Windowing Library (PW) is a portable interface that makes
|
||||
it as simple as possible to make an OpenGL application that can open a
|
||||
single window and read the mouse and keyboard. It is a wrapper to make the
|
||||
various underlying OS mechanisms look the same to application code.
|
||||
<p>
|
||||
You should include the PW header file '/usr/include/plib/pw.h'
|
||||
and link to the PW library '/usr/lib/libplibpw.a'.
|
||||
<p>
|
||||
Before using any other PW functions, you should initialise the
|
||||
library by calling either:
|
||||
<pre>
|
||||
|
||||
void pwInit ( int multisample, int num_samples ) ;
|
||||
|
||||
</pre>
|
||||
...or:
|
||||
<pre>
|
||||
|
||||
void pwInit ( int x, int y, int w, int h,
|
||||
int multisample,
|
||||
char *title, int border, int num_samples ) ;
|
||||
|
||||
</pre>
|
||||
The first version creates a full-screen window with no borders,
|
||||
titles, etc (or at least as close to that as your OS can manage).
|
||||
The second version creates a window with it's origin at (x,y) of
|
||||
dimensions w x h, with the specified title string, and optionally
|
||||
with or without a border.
|
||||
<p>
|
||||
The window that's created will have the maximum number of colours
|
||||
that your system supports - double-buffered plus a Z buffer.
|
||||
<p>
|
||||
Both forms allow you to specify whether you'd like multisampling
|
||||
to be enabled or not - and if so, with how many samples. If your
|
||||
system cannot produce the number of samples requested, pwInit will
|
||||
fall back to the best it can do.
|
||||
<p>
|
||||
Then, initialise other PLIB components such as PUI. When initialisation
|
||||
is complete, call this function:
|
||||
<pre>
|
||||
|
||||
void pwCallbacks ( pwKeybdFunc *kb = NULL, pwMouseFunc *ms = NULL,
|
||||
pwMousePosFunc *mp = NULL, pwResizeCB *rcb = NULL,
|
||||
pwExitCB *ecb = NULL ) ;
|
||||
|
||||
</pre>
|
||||
These parameters are callback functions for (repectively)
|
||||
incoming keyboard keystrokes, incoming mouse button press or
|
||||
release events, mouse movements, window resize events and finally,
|
||||
a window close callback. (That's invoked by PW when the user attempts
|
||||
to close the window by pressing the exit button on the window border.)
|
||||
PW also calls the exit function when it detects a fatal error that
|
||||
occurs after the window has been successfully opened.
|
||||
<p>
|
||||
Your application has to be prepared for these callbacks to be invoked
|
||||
at any time after pwCallbacks. PW allows you to issue OpenGL calls
|
||||
any time after pwInit().
|
||||
<p>
|
||||
The specifications of these various callbacks are:
|
||||
<pre>
|
||||
|
||||
typedef void pwResizeCB ( int w, int h ) ;
|
||||
typedef void pwExitCB () ;
|
||||
typedef void pwKeybdFunc ( int key, int updown, int x, int y ) ;
|
||||
typedef void pwMouseFunc ( int button, int updown, int x, int y ) ;
|
||||
typedef void pwMousePosFunc ( int x, int y ) ;
|
||||
|
||||
</pre>
|
||||
The 'updown' parameter is set to PW_DOWN when a key or mouse button
|
||||
is pressed or to PW_UP when it's released. The 'key' parameter is
|
||||
either an ASCII character or one of:
|
||||
<pre>
|
||||
|
||||
PW_KEY_F1 PW_KEY_F2 PW_KEY_F3 PW_KEY_F4
|
||||
PW_KEY_F5 PW_KEY_F6 PW_KEY_F7 PW_KEY_F8
|
||||
PW_KEY_F9 PW_KEY_F10 PW_KEY_F11 PW_KEY_F12
|
||||
|
||||
PW_KEY_LEFT PW_KEY_UP PW_KEY_RIGHT PW_KEY_DOWN
|
||||
|
||||
PW_KEY_PAGE_UP PW_KEY_PAGE_DOWN
|
||||
|
||||
PW_KEY_HOME PW_KEY_END PW_KEY_INSERT
|
||||
|
||||
</pre>
|
||||
The 'button' parameter is one of:
|
||||
<pre>
|
||||
|
||||
PW_LEFT_BUTTON PW_MIDDLE_BUTTON PW_RIGHT_BUTTON
|
||||
|
||||
</pre>
|
||||
These constants are chosen to be identical to the similarly named
|
||||
constants used in the PLIB PUI library so that it's easy to connect
|
||||
a PUI GUI to a PW window.
|
||||
<p>
|
||||
Once the window is initialised, you may call other PLIB graphics
|
||||
initialisations (puInit, ssgInit, etc).
|
||||
<p>
|
||||
So now you have your window open, you only need to do one thing -
|
||||
call this function once per frame:
|
||||
<pre>
|
||||
|
||||
void pwSwapBuffers () ;
|
||||
|
||||
</pre>
|
||||
This function swaps the double-buffers, collects keystrokes, mouse events
|
||||
and resize events and calls whatever application-defined callbacks are
|
||||
needed. It is NOT LEGAL to call pwSwapBuffers() from inside a PW callback
|
||||
function.
|
||||
<p>
|
||||
When you wish to close the PW window, you should call:
|
||||
<pre>
|
||||
|
||||
void pwCleanup () ;
|
||||
|
||||
</pre>
|
||||
Some applications need to know when the shift/control/alt keys are being
|
||||
held down by the user:
|
||||
<pre>
|
||||
|
||||
int pwGetModifiers () ;
|
||||
|
||||
</pre>
|
||||
This returns the state of those three keys as the OR of the three constants:
|
||||
<pre>
|
||||
|
||||
PW_SHIFT PW_CTRL PW_ALT
|
||||
|
||||
</pre>
|
||||
Note that the results are only valid inside of a callback called from
|
||||
pwSwapBuffers().
|
||||
<p>
|
||||
By default, PW disallows auto-repeat of keyboard keys. This is generally what
|
||||
you want for games. However, it's possible that you may want auto-repeat to
|
||||
be enabled:
|
||||
<pre>
|
||||
|
||||
void pwSetAutoRepeatKey ( bool enable ) ;
|
||||
|
||||
</pre>
|
||||
If the user has told the windowing system that auto repeat should be off as
|
||||
some kind of a global preference then pwSetAutoRepeatKey(true) won't turn
|
||||
it back on again.
|
||||
<p>
|
||||
Finally, there are a number of functions for setting and getting the window
|
||||
position and dimensions - also to set the current cursor shape:
|
||||
<pre>
|
||||
|
||||
void pwGetSize ( int *w, int *h ) ;
|
||||
void pwSetSizeOrigin ( int x, int y, int w, int h ) ;
|
||||
void pwSetSize ( int x, int y ) ;
|
||||
void pwSetOrigin ( int w, int h ) ;
|
||||
void pwSetCursor ( int c ) ;
|
||||
|
||||
</pre>
|
||||
The available cursor shapes for pwSetCursor are:
|
||||
<pre>
|
||||
|
||||
PW_CURSOR_NONE 0
|
||||
PW_CURSOR_RIGHT 1
|
||||
PW_CURSOR_LEFT 2
|
||||
PW_CURSOR_QUERY 3
|
||||
PW_CURSOR_AIM 4
|
||||
PW_CURSOR_CIRCLE 5
|
||||
PW_CURSOR_WAIT 6
|
||||
PW_CURSOR_CROSS 7
|
||||
PW_CURSOR_CUSTOM 8
|
||||
|
||||
</pre>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
147
doc/requirements.html
Normal file
@@ -0,0 +1,147 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>PLIB: Requirements & Portability.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="plib_logo.png" ALT="PLIB Logo" width=256 height=245>
|
||||
<br>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<H1>
|
||||
<FONT SIZE=9>S</FONT><FONT SIZE=5>TEVE'S</FONT>
|
||||
<FONT SIZE=9>P</FONT><FONT SIZE=5>ORTABLE</FONT>
|
||||
<FONT SIZE=9>G</FONT><FONT SIZE=5>AME</FONT>
|
||||
<FONT SIZE=9>L</FONT><FONT SIZE=5>IBRARY.</FONT>
|
||||
</H1>
|
||||
</center>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't
|
||||
get much Sleep.
|
||||
<br>
|
||||
-- Woody Allen
|
||||
</ul>
|
||||
<center>
|
||||
<A href="http://sf.net">
|
||||
<IMG src="http://sf.net/sflogo.php?group_id=382&type=1" width="88" height="31" border="0" ALT="Sourceforge Logo"></A>
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD valign=top align=left>
|
||||
<A HREF="index.html"><IMG SRC="home.png" ALT="HOME" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="whats_inside.html"><IMG SRC="whats_inside.png" ALT="WHAT'S INSIDE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="license.html"><IMG SRC="license.png" ALT="LICENSE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="contacts.html"><IMG SRC="contacts.png" ALT="CONTACTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="requirements.html"><IMG SRC="requirements.png" ALT="REQUIREMENTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="gallery.html"><IMG SRC="gallery.png" ALT="GALLERY" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="download.html"><IMG SRC="download.png" ALT="DOWNLOAD & INSTALL" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="examples.html"><IMG SRC="examples.png" ALT="EXAMPLES" BORDER="0" width=150 height=50></A><br>
|
||||
|
||||
<A HREF="sg/index.html"><IMG SRC="SG.png" ALT="SG" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="ssg/index.html"><IMG SRC="SSG.png" ALT="SSG" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="ssgAux/index.html"><IMG SRC="ssgAux.png" ALT="SSGAUX" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="fnt/index.html"><IMG SRC="FNT.png" ALT="FNT" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pui/index.html"><IMG SRC="PUI.png" ALT="PUI" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="psl/index.html"><IMG SRC="PSL.png" ALT="PSL" BORDER="0" width=75 height=25></A>
|
||||
|
||||
<A HREF="util/index.html"><IMG SRC="UL.png" ALT="UL" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="js/index.html"><IMG SRC="JS.png" ALT="JS" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="net/index.html"><IMG SRC="NET.png" ALT="NET" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="sl/index.html"><IMG SRC="SL.png" ALT="SL" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pw/index.html"><IMG SRC="PW.png" ALT="PW" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="puAux/index.html"><IMG SRC="puAux.png" ALT="PUAUX" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H2>Hardware Requirements for Running PLIB</H2>
|
||||
To do good 3D graphics, you'll need an OpenGL-compatible 3D graphics
|
||||
accellerator that your operating system supports. Most systems can
|
||||
run OpenGL in software only - but performance is so poor as to be
|
||||
unusable in the kinds of application for which PLIB is intended.
|
||||
<p>
|
||||
If you want to hear sound effects and music, you'll obviously
|
||||
need a sound card and some speakers or headphones.
|
||||
|
||||
<H2>Software Requirements for Running PLIB</H2>
|
||||
The PLIB team works hard to minimise our dependance on other
|
||||
libraries to make it easy for end-users to install application
|
||||
software without having to visit dozens of web sites to collect
|
||||
the libraries they need.
|
||||
<ul>
|
||||
<li>3D/2D Graphics: OpenGL. If you aren't already set up to
|
||||
run OpenGL, you should check:
|
||||
<ul>
|
||||
<li> <A HREF="http://www.opengl.org">The OpenGL ARB</A> site.
|
||||
<li> Or download <A HREF="http://www.mesa3d.org">Mesa</A>
|
||||
(which is an excellent OpenGL clone by Brian Paul).
|
||||
<li> If you are a Linux user, you may wish to check the
|
||||
<A HREF="http://www.linux3d.org">Linux3D Site</A>.
|
||||
<li> If you are a Windoze or Macintosh user, you should have
|
||||
had a copy of OpenGL delivered with your operating
|
||||
system.
|
||||
</ul>
|
||||
<li>Windowing: From version 1.8.0, PLIB itself is completely independent of
|
||||
any other windowing library. However, some of the demo and example
|
||||
programs use <A HREF="http://freeglut.sf.net">freeglut</A> (or at a
|
||||
pinch:
|
||||
<A HREF="http://www.opengl.org/Documentation/GLUT.html">the original
|
||||
GLUT</A> (GL Utility Toolkit by Mark Kilgard).
|
||||
<A HREF="http://freeglut.sf.net">freeglut</A>
|
||||
works very well with PLIB applications and is maintained by
|
||||
many of the same people - so there is good continuity.
|
||||
It's perfectly possible to write PLIB programs that don't use
|
||||
either GLUT or freeglut - for example, you can use PLIB with
|
||||
<a href="http://www.libsdl.org">SDL</a>).
|
||||
</ul>
|
||||
|
||||
<H2>How Portable is PLIB?</H2>
|
||||
VERY!
|
||||
<ul>
|
||||
<li> All flavors of Linux are supported - on any CPU platform that
|
||||
supports Xfree86 and OpenGL.
|
||||
<li> All flavors of Win32 are
|
||||
supported, using either MSVC++ or CygWin for compilation.
|
||||
Theoretically you could use Borland C++ also, but since there is little
|
||||
user base these days, the necessary 'project' files to build PLIB
|
||||
under Borland's IDE tend to get outdated.
|
||||
<li> Most other UNIX-like systems (at least BSD, IRIX, Solaris, OS-X) providing
|
||||
they support X-windows.
|
||||
<li> MacOS-X is also reasonably well supported.
|
||||
<li> MacOS-9 runs everything except the joystick library. However, it's getting
|
||||
hard to find people to test this port - so it may have problems by the time
|
||||
you come to use it.
|
||||
<li> Support for BeOS is problematic - for some reason, people who are prepared
|
||||
to help out with porting PLIB to BeOS are hard to find. However, since
|
||||
BeOS (I'm told) has compatibility with X, OpenGL and OSS, it should
|
||||
be easy to port to and may just work 'out of the box'.
|
||||
</ul>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
doc/requirements.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
1107
doc/sg/index.html
Normal file
BIN
doc/sg/triangle_params.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
71
doc/sl/index.html
Normal file
@@ -0,0 +1,71 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="keywords" content="SL, SM, PLIB, OpenGL, sound, library, portable, games, sample, replay, mixer, OSS, Baker, Steve">
|
||||
<META name="description" content="The PLIB SL Library is targetted towards producing sound effects for games and other realtime applications. The emphasis is on low CPU impact and low latency rather than high quality and fancy MIDI/MOD facilities. The PLIB SM Library controls the audio mixer on a PC sound card.">
|
||||
<TITLE>The SL Sound and Mixer Libraries.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H1>The SL Sound and Mixer Libraries.</H1>
|
||||
By Steve Baker
|
||||
<H2>Introduction.</H2>
|
||||
The 'SL' sound library is primarily targetted towards producing sound
|
||||
effects for games, and isn't really intended for playing music (although
|
||||
you could certainly use it for doing that). The emphasis is on low
|
||||
CPU impact and low latency rather than high quality and fancy MIDI/MOD
|
||||
facilities.
|
||||
<p>
|
||||
SL is a part of <A HREF="../index.html">PLIB</A>.
|
||||
<p>
|
||||
The 'SL' sound library will eventually become a fully portable freeware
|
||||
sound library that should run on all major platforms. Right now, SL
|
||||
runs under:
|
||||
<ul>
|
||||
<li>Linux on systems with OSS (the Open Sound System) installed
|
||||
(it's usually a standard part of the kernel).
|
||||
<li>Windows NT, 95 and 98.
|
||||
<li>OpenBSD.
|
||||
<li>SGI's IRIX.
|
||||
<li>Other UNIX systems using OSS (which should include Solaris, FreeBSD,
|
||||
BSD/OS, SCO and others) should be able to run the Linux version of
|
||||
SL by adding '-DSL_USING_OSS_AUDIO' to the compile command line.
|
||||
</ul>
|
||||
At present, there is no support for Apple's MacOS sound systems
|
||||
- although it is hoped that these will be added in the near future.
|
||||
<ul>
|
||||
<li><A HREF="sl.html">The SL Library</A>
|
||||
deals with all aspects of sample replay for games and
|
||||
other realtime applications - it is designed such that it can be
|
||||
ported to other operating systems by replacing just the slDSP
|
||||
class.
|
||||
<p>
|
||||
<li><A HREF="sm.html">The SM Library</A>
|
||||
controls the audio mixer on a PC sound card and
|
||||
probably only works 100% correctly within OSS - and then probably
|
||||
only on fairly 'vanilla' Soundblaster-compatible sound cards.
|
||||
Portability of SM is patchy - regard it as a bonus.
|
||||
</ul>
|
||||
It is due to the relative non-portability of the SM routines
|
||||
that these are in a separate library. For non-portable
|
||||
applications, SL and SM can be considered as a single library.
|
||||
<p>
|
||||
<A HREF="http://www.4front-tech.com">Download the Open Sound System
|
||||
drivers (previously known as VoxWare).</A>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
BIN
doc/sl/mixer.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
1048
doc/sl/sl.html
Normal file
BIN
doc/sl/sl.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
106
doc/sl/sm.html
Normal file
@@ -0,0 +1,106 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="keywords" content="SM, PLIB, OpenGL, sound, library, mixer, OSS, Baker, Steve, smMixer">
|
||||
<META name="description" content="The PLIB SM Library allows one to drive the mixer controls of most PC-style sound cards.">
|
||||
<TITLE>The SL Mixer Library.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD><IMG SRC="mixer.png" ALT="Imagine kitchen mixers here" width=247 height=247></TD>
|
||||
<TD>
|
||||
<H1>The SL Mixer Library.</H1>
|
||||
By Steve Baker
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H2>Introduction.</H2>
|
||||
This library allows one to drive the mixer controls of
|
||||
most PC-style sound cards. It relies
|
||||
on <A HREF="http://www.4front-tech.com">the Open Sound
|
||||
System</A> drivers (formerly known as 'VoxWare')
|
||||
- which are generally a standard part of the Linux Kernel - and
|
||||
which is also available on some other UNIX platforms.
|
||||
<p>
|
||||
A port of SM to the Windows family of operating systems
|
||||
is currently underway.
|
||||
<p>
|
||||
SM does not work under SGI's IRIX.
|
||||
<H2>Using the Library.</H2>
|
||||
To use this library, you must '#include "sm.h"' and link to
|
||||
libsm.a or libsm.so.
|
||||
<H2>class smMixer.</H2>
|
||||
This library comprises a single class 'smMixer'.
|
||||
<p>
|
||||
Most programs will only ever create a single smMixer object.
|
||||
<p>
|
||||
Here are the member functions:
|
||||
<pre>
|
||||
|
||||
class smMixer
|
||||
{
|
||||
public:
|
||||
|
||||
smMixer () ;
|
||||
smMixer ( char *device ) ;
|
||||
~smMixer () ;
|
||||
|
||||
int not_working () ;
|
||||
|
||||
/* Volume/Treble/Bass controls are in integer percentages */
|
||||
|
||||
void setTreble ( int treble ) ;
|
||||
void setBass ( int bass ) ;
|
||||
|
||||
void setMasterVolume ( int volume ) ;
|
||||
void setSynthVolume ( int volume ) ;
|
||||
void setPCMVolume ( int volume ) ;
|
||||
void setSpeakerVolume( int volume ) ;
|
||||
void setLineVolume ( int volume ) ;
|
||||
void setMicVolume ( int volume ) ;
|
||||
void setCDVolume ( int volume ) ;
|
||||
|
||||
void setMasterVolume ( int left, int right ) ;
|
||||
void setSynthVolume ( int left, int right ) ;
|
||||
void setPCMVolume ( int left, int right ) ;
|
||||
void setSpeakerVolume( int left, int right ) ;
|
||||
void setLineVolume ( int left, int right ) ;
|
||||
void setMicVolume ( int left, int right ) ;
|
||||
void setCDVolume ( int left, int right ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
Basically, each of the mixer devices can be driven with either
|
||||
mono or stereo volume controls, each volume is a expressed as an
|
||||
integer percentage of maximum.
|
||||
<p>
|
||||
By default, "/dev/mixer" is the device used by this class, but
|
||||
an alternative device may be accessed if it's name is passed
|
||||
into the constructor.
|
||||
<p>
|
||||
The 'not_working()' function returns TRUE if there is any kind of
|
||||
problem with the driver. Mostly it returns TRUE if your system isn't
|
||||
set up for audio.
|
||||
<p>
|
||||
The driver will not fail if you call it's member functions when
|
||||
'not_working()' returns TRUE - so programs written for audio
|
||||
should work OK even on Linux boxes with no audio support.
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
BIN
doc/spacething-small.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
315
doc/ssg/LoaderWriter.html
Normal file
@@ -0,0 +1,315 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H2>How to write plib-loaders and writers</H2>
|
||||
|
||||
<H2>1.1 Introduction</H2>
|
||||
|
||||
This page is intended for those who wish to write loaders and writers
|
||||
for plib. If you just use plib (using the included loaders and writers), you don't
|
||||
really need to read this.
|
||||
|
||||
It is quite easy to adapt 3D-file-loaders and writers to be used by ssg. Plib
|
||||
already has many loaders and writers that may be used as examples.<p>
|
||||
|
||||
A brief note on cross platform compilation: Plib comes with
|
||||
both Makefiles (for Unix and for the CygWin-system under Windows)
|
||||
and workspace/project-files for Micro$oft Visual C++. If you
|
||||
have both, please update, test and commit both.
|
||||
Otherwise, when committing, please tell the people that something is
|
||||
missing (for example: you didn't update the workspace files) and that some
|
||||
kind soul should do so.
|
||||
<p>
|
||||
|
||||
Both loaders and writers convert between ssg's internal geometry
|
||||
representation and that of the file format. One key difference is that when
|
||||
loading, you should support all possibile
|
||||
geometry-representations of the file format. This is to ensure that
|
||||
plib can handle all the possible variations of a file format that may be generated
|
||||
by the tools that export to it. On the other hand, when writing a format, you can
|
||||
pretty safely only write to one geometry format (unless you need features peculiar
|
||||
to more than one geometry representation), because you have the final say on how the
|
||||
data is to be written.
|
||||
<p>
|
||||
|
||||
Regarding plib's geometry-representations: there are only two on the highest
|
||||
level: <code>ssgVtxTable</code> and <code>ssgVtxArray</code>. Actually, there is also
|
||||
ssgVTable, but that is deprecated.
|
||||
|
||||
<code>ssgVtxArray</code> is newer, is derived
|
||||
from ssgVtxTable and uses a index-list. Apart from that they are quite
|
||||
similar, and both have an interface <code>getNumTriangles () ; </code> and
|
||||
<code>getTriangle ( i, ...); </code>
|
||||
For this reasons, it is easier to write a writer than a loader.
|
||||
|
||||
|
||||
For both ssgVtxTable and ssgVtxArray you need to choose a
|
||||
GL-type. Currently ssgLoaderWriterMesh (more on this in the
|
||||
next section) uses <code>GL_TRIANGLES</code>.
|
||||
|
||||
|
||||
<H2>1.2 class ssgLoaderWriterMesh - an overview</H2>
|
||||
|
||||
The two main parts of writing a loader are writing the actual parser (coding
|
||||
the syntax of the format) and transferring the contents
|
||||
to ssg. The second task is fairly trivial if your contents
|
||||
obey the restrictions of ssg (which follow from OpenGL).
|
||||
<BR><BR>
|
||||
These are:
|
||||
<BR><BR>
|
||||
|
||||
1. Each ssg-node can (currently) have only one texture.
|
||||
<BR>
|
||||
2. Only one polygon or strip or fan per node. So you can't have a 3-, a 4- and a 5-sided
|
||||
poly inside one node (without subdividing the polys into triangles)
|
||||
<BR>
|
||||
3. Currently, you may have only one texture coordinate per vertex.
|
||||
<BR>
|
||||
4. You may have only one normal per vertex.
|
||||
<BR><BR>
|
||||
To modularize the two steps parsing the format and transfering it to ssg
|
||||
and to reduce redundant work, there is an intermediatory structure, the class
|
||||
ssgLoaderWriterMesh. For example, this has a member function
|
||||
<pre>
|
||||
void ssgLoaderWriterMesh::addFaceFromIntegerArray( int numVertices, int *vertices );
|
||||
</pre>
|
||||
With several calls, you can add several n-sided polys to one mesh ("one node").
|
||||
When you are done constructing the mesh from the file, you call
|
||||
<pre>
|
||||
void ssgLoaderWriterMesh::addToSSG(
|
||||
class ssgSimpleState *currentState,
|
||||
class ssgLoaderOptions* current_options,
|
||||
class ssgBranch *curr_branch_)
|
||||
</pre>
|
||||
and the class adds the information into the scene graph. It handles
|
||||
ssgs' restrictions. For example, if the polygons of the mesh use
|
||||
5 textures then at least 5 nodes will be added to the scene graph.<p>
|
||||
|
||||
Unfortunately, this class isn't completely finished. As of this
|
||||
writing, Wolfram Kuss (w_kuss@rz-online.de) has implemented those
|
||||
parts that were needed for the loaders he has finished thus far. Hopefully
|
||||
people will contribute more features as time goes on.<p>
|
||||
|
||||
If you are writing a new loader for a file format that doesn't hold to
|
||||
all restrictions of ssg (and virtually none do), you are urged to use this class.
|
||||
Your loader will be more consistent and easier to maintain and read.<p>
|
||||
|
||||
Further, there are many optimizations that can be done (For example: "If the state is
|
||||
different, but not the texture, do we need several nodes?" or "When we have multitexturing,
|
||||
can we use that?" or "Is there an optimal strip length?" or "How do I subdivide polys into
|
||||
triangles so that the stripifier will work well?"-- the list goes on
|
||||
forever). Once we have good answers to these questions (and the will
|
||||
to implement them), it will be easier to do them once in the ssgLoaderWriterMesh than in all the
|
||||
loaders seperately. It is noteable that most loaders written before
|
||||
ssgLoaderWriterMesh have had some sort of intermediatory mesh
|
||||
structure.<p>
|
||||
|
||||
In the future, ssgLoaderWriterMesh should also be used for writers, doing the opposite
|
||||
job: It takes the information from ssg with the restrictions and then looks whether
|
||||
it can optimize (for example merging nodes) by relaxing the restrictions.
|
||||
|
||||
<H2>1.3 The Class ssgLoaderWriterMesh - A Deeper Look</H2>
|
||||
At the start of your loader, you create a new <code>ssgLoaderWriterMesh</code>
|
||||
or do a <code>reInit()</code>. To insert the data into the <code>ssgLoaderWriterMesh</code>,
|
||||
you have to add vertices, faces, materials, materialindexes (saying what face uses what material)
|
||||
and, if applicable texture coordinates. For all of these, you <B>can</B> say in advance how many you have.
|
||||
If you know that you have 3712 vertices, call <code>createVertices(3712)</code> and everything is allocated
|
||||
at once and <code>addVertex</code> will be very fast. If you don't know in advance how many you have, you
|
||||
still have to call <code>createVertices()</code>, as this also allocates the vertices. In this case, a
|
||||
certain amount of vertices will be reserved and the list will dynamically grow as more are added.<p>
|
||||
|
||||
Vertices are simply sgVec3s. Faces are simply lists/arrays of vertex indexes.
|
||||
For adding faces, use <code>addFace</code> if you already have a <code>ssgIndexArray</code> or use
|
||||
<code>addFaceFromIntegerArray</code> if you have the vertex indexes in a C(++) array.
|
||||
You need to add at least one material (<code>ssgSimpleState</code>). For each face, you tell
|
||||
ssg which material to use via <code>addMaterialIndex</code>. Here is code from ssgLoadOFF, which tells
|
||||
ssg to use the <code>ssgSimpleState</code> ss for all faces:
|
||||
|
||||
<BR>
|
||||
<pre>
|
||||
|
||||
theMesh.createMaterials( 1 );
|
||||
theMesh.addMaterial( &ss );
|
||||
theMesh.createMaterialIndices( _ssgNoFacesToRead ) ;
|
||||
for(i=0;i<_ssgNoFacesToRead ;i++)
|
||||
theMesh.addMaterialIndex ( 0 ) ;
|
||||
</pre>
|
||||
<BR>
|
||||
If the file format has texture coordinates, you have to find out whether it has them
|
||||
per vertex or per vertex and face. If you look at a "straight forward" cube,
|
||||
having texture coordinates per vertex means you can have 8, but if you have
|
||||
texture coordinates per vertex and face, you can have 24 (each vertex is part of 3 faces).
|
||||
The two functions corresponding to these cases are:
|
||||
<pre>
|
||||
void createPerFaceAndVertexTextureCoordinates2( int numReservedTextureCoordinate2Lists = 3 );
|
||||
void addPerFaceAndVertexTextureCoordinate2( ssgTexCoordArray **textureCoordinateArray );
|
||||
</pre>
|
||||
or
|
||||
<pre>
|
||||
void createPerVertexTextureCoordinates2( int numReservedTextureCoordinates2 = 3 );
|
||||
void addPerVertexTextureCoordinate2( sgVec2 textureCoordinate );
|
||||
</pre>
|
||||
|
||||
|
||||
<H2>2. Loaders</H2>
|
||||
|
||||
|
||||
<H2>2.1 class ssgLoaderOptions</H2>
|
||||
|
||||
ssgLoaderOptions is a class that is defined in ssg.h.
|
||||
It is used to tell the loader some options.
|
||||
It is NOT used for user-setable options, although
|
||||
this may be nice to have at some point. For example,
|
||||
one COULD create a member-variable in it
|
||||
telling the unit that one wants. The loader would then
|
||||
be responsible to scale the object in such a way that
|
||||
the sizes are in that unit (for example: meter, millimeter, etc).
|
||||
|
||||
<BR>
|
||||
<BR>
|
||||
Regarding the reason for the callbacks in ssgLoaderOptions, Steve
|
||||
wrote:
|
||||
<BR>
|
||||
<BR>
|
||||
<blockquote>
|
||||
<i>"Whenever a branch node is created. The deal is that most file formats
|
||||
are
|
||||
missing important features at the Branch level - but many support
|
||||
comment
|
||||
fields - or long ASCII name strings or something. The idea was to allow the artists to attach an ARBITARY comment string
|
||||
in their modeller - and to have the loader trap these strings and pass
|
||||
them on to the application.</i><p>
|
||||
|
||||
<i>Hence, if the hook function is defined then when a branch node needs
|
||||
to
|
||||
be created, we call the application's callback with the ASCII string
|
||||
that was embedded in the file and let the application construct the
|
||||
ssgBranch
|
||||
node. Hence, you could put the string "~LOD: RANGE=100 meters"
|
||||
into the comment field in (say) the AC3D modeller. (AC3D calls this a
|
||||
"Data"
|
||||
field)...the application could then say to itself: "Any comment that
|
||||
starts
|
||||
with a tilde ('~') is a command to the loader" and parse such
|
||||
'comments'
|
||||
as commands. In this case, it would construct an ssgRangeSelector and
|
||||
set
|
||||
the transition range to 100m and return the application back to the
|
||||
loader.</i><p>
|
||||
|
||||
<i>Check the <a href="http://tuxkart.sf.net">Tux Kart</a> sources to see this in action."</i>
|
||||
</blockquote>
|
||||
|
||||
So much for the quote from Steve.
|
||||
<p>
|
||||
|
||||
As of this writing, the ssgLoaderOptions code has been copied from
|
||||
another loader into ssgLoaderWriterMesh.
|
||||
|
||||
|
||||
<H2>2.2 ASCII file formats</H2>
|
||||
A lexical analyzer for ascii-files is available in ssgParser.cxx and
|
||||
ssgParser.h. It converts the file into a stream of tokens and
|
||||
handles comments. In a way, it has two APIs.
|
||||
One hides the line structure from the loader. The loader just has
|
||||
to say "getNextToken".
|
||||
The other API operates in terms of exact line structure.
|
||||
You do a getLine which reads all the tokens of that line into a
|
||||
buffer and then you do a parseToken to get each token.<p>
|
||||
|
||||
The formats which currently use the parser are .X (which uses the
|
||||
line-independant API), .ase, .scenery and .off (which use the
|
||||
line-by-line-API).<p>
|
||||
Some functions are used by both APIs. For example:<p>
|
||||
|
||||
<pre>
|
||||
void openFile( const char* fname, const _ssgParserSpec* spec = 0 );
|
||||
</pre><p>
|
||||
|
||||
In ssgParserSpec, you give the parser the specification of the format.
|
||||
You say which characters start a comment, which characters are skipable,
|
||||
which characters are used for braces (which are used to determine the
|
||||
parser's level-- useful for parser's which work recursively).
|
||||
Most important are the delimiters. These determine where one token ends and the
|
||||
next one begins. For example, the first token of the line
|
||||
|
||||
<pre>
|
||||
1234,567
|
||||
</pre>
|
||||
|
||||
is <code>1234</code> if <code>","</code> is a delimiter and
|
||||
<code>1234,567</code> otherwise.
|
||||
The parser differentiates between skipable delimiters that
|
||||
are "swallowed" by the parser and non-skipable ones that are
|
||||
passed to the loader. So, regarding the example-line there
|
||||
are three possibilities:
|
||||
<BR>
|
||||
<code>","</code> is not a delimiter => The line contains one token, namely
|
||||
<code>"1234,567"</code>
|
||||
<BR>
|
||||
<code>","</code> is a skipable delimiter => The line contains two tokens, namely
|
||||
<code>"1234"</code> and <code>"567"</code>
|
||||
<BR>
|
||||
<code>","</code> is a non-skipable delimiter => The line contains three tokens,
|
||||
namely <code>"1234"</code>, <code>","</code> and <code>"567"</code>
|
||||
<BR>
|
||||
|
||||
|
||||
<H2>3. Writers</H2>
|
||||
For an example how to write out geometry and material, look at
|
||||
ssgSaveASE.
|
||||
|
||||
For an easy example (geometry only), look at <code>ssgSaveDXF</code> or <code>ssgSaveTRI</code>.
|
||||
The function
|
||||
|
||||
<pre>
|
||||
int ssgSaveXYZ ( const char *filename, ssgEntity *ent )
|
||||
</pre>
|
||||
|
||||
normally calls a function
|
||||
|
||||
<pre>
|
||||
static void save_entities ( ssgEntity *e )
|
||||
</pre>
|
||||
|
||||
which just recursively walks the scene graph.
|
||||
You should be able to use this function and just
|
||||
write a
|
||||
|
||||
<pre>
|
||||
static void save_vtx_table ( ssgVtxTable *vt )
|
||||
</pre>
|
||||
|
||||
which writes a <code>ssgVtxTable</code>.<p>
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"><a href="non_class.html"><= previous =</a></td>
|
||||
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
||||
<td width="33%" align="right"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
319
doc/ssg/branches.html
Normal file
@@ -0,0 +1,319 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H2><code>class ssgBranch</code> - A basic branch node.</H2>
|
||||
The basic ssgBranch node simply handles a node in the tree,
|
||||
with zero or more child nodes which can be any kind of ssgEntity
|
||||
except ssgRoot.
|
||||
<p>
|
||||
There are a rich set of functions for adding, deleting and
|
||||
replacing child nodes:
|
||||
<pre>
|
||||
|
||||
class ssgBranch : public ssgEntity
|
||||
{
|
||||
int getNumKids (void) ;
|
||||
ssgEntity *getKid ( int n ) ;
|
||||
ssgEntity *getNextKid (void) ;
|
||||
int searchForKid ( ssgEntity *entity ) ;
|
||||
void addKid ( ssgEntity *entity ) ;
|
||||
void removeKid ( int n ) ;
|
||||
void removeKid ( ssgEntity *entity ) ;
|
||||
void removeAllKids (void) ;
|
||||
void replaceKid ( ssgEntity *old_entity, ssgEntity *new_entity ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
Most of these are pretty self-explanatory.
|
||||
<code>ssgBranch::getNumKids()</code> returns the number of child nodes
|
||||
beneath this branch.
|
||||
<code>ssgBranch::getKid(n)</code> returns the address of the n'th child ssgEntity.
|
||||
<code>ssgBranch::getNextKid()</code> returns the address of the child entity following
|
||||
the last one returned by getKid or getNextKid - returning NULL when all child nodes
|
||||
have been exhausted.
|
||||
<code>ssgBranch::searchForKid(entity)</code> searches for the specified entity
|
||||
in the list of child nodes and returns it's index (ie the inverse of getKid).
|
||||
<code>ssgBranch::addKid(entity)</code> adds the specified entity to the list of
|
||||
child nodes - the new node is added at the end of the list and will therefore
|
||||
have the highest numbered index.
|
||||
<code>ssgBranch::removeKid(n)</code> removes the n'th child node and renumbers
|
||||
any higher numbered children so there are never any gaps in the number range.
|
||||
<code>ssgBranch::removeKid(entity)</code> same as removeKid(searchForKid(entity)).
|
||||
<code>ssgBranch::removeAllKids()</code> remove ALL child entities.
|
||||
<code>ssgBranch::replaceKid(old, new)</code> replaces <code>old</code> with <code>new</code>.
|
||||
If the entity removed by any of these commands has a ref count of
|
||||
zero, it will be deleted.
|
||||
|
||||
<H2><code>class ssgInvisible</code> - Invisible parts of a Scene Graph.</H2>
|
||||
It's sometimes useful to have sections of the scene graph that are never
|
||||
rendered to the screen. These are frequently used for collision detection
|
||||
and other non-graphical operations.
|
||||
|
||||
<H2><code>class ssgRoot</code> - The Root of the Scene Graph,</H2>
|
||||
The node at the root of the scene graph is special. At present,
|
||||
it resembles an ssgBranch externally.
|
||||
<pre>
|
||||
|
||||
class ssgRoot : public ssgBranch
|
||||
{
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
|
||||
<H2><code>class ssgTweenController</code> - A morph controller,</H2>
|
||||
This is essentially identical to an ssgBranch - but adds API to
|
||||
set the current 'bank' settings of all ssgTween leaf nodes beneath it.
|
||||
<p>
|
||||
An ssgTween is a leaf node that can hold multiple geometric
|
||||
representations that it smoothly interpolates between.
|
||||
<pre>
|
||||
|
||||
ssgTweenController::selectBank ( float b ) ;
|
||||
float ssgTweenController::getCurrBank () ;
|
||||
|
||||
</pre>
|
||||
This allows you to set which of the banks of it's daughter ssgTweens
|
||||
will be rendered. That's a "float" quantity - so if you selectBank(2.4)
|
||||
then the ssgTweens will render their vertices in a position (colour, etc)
|
||||
that's 40% of the way between the bank 2 and bank 3.
|
||||
<p>
|
||||
You can also set the behaviour when the selected bank number is larger
|
||||
than the number of banks in the model. This tends to happen when you
|
||||
simply add some amount of to the bank selector each frame in order
|
||||
to keep the animation running forever:
|
||||
<pre>
|
||||
|
||||
ssgTweenController::setMode ( int mode ) ;
|
||||
|
||||
</pre>
|
||||
'mode' can either be SSGTWEEN_STOP_AT_END or SSGTWEEN_REPEAT.
|
||||
The default is STOP_AT_END - where anytime the bank selector
|
||||
is larger than the actual number of banks in the ssgTween node,
|
||||
it is clamped to the largest possible number. If you choose
|
||||
REPEAT, then the bank number will be taken modulo the number of
|
||||
banks.
|
||||
<H2><code>class ssgSelector</code> - A switch point,</H2>
|
||||
Most ssgBranch nodes represent a collection of objects that
|
||||
are all present in the scene at the same time. ssgSelector
|
||||
nodes (and derived classes) typically represent a single
|
||||
object that can be represented in more than one way.
|
||||
<p>
|
||||
A selector contains up to 32 daughter objects and a
|
||||
32 bit unsigned integer mask. Where there is a one bit
|
||||
in the mask, that child object will be drawn, where
|
||||
there is a zero, it will not.
|
||||
<p>
|
||||
<code>ssgSelector::select(mask)</code> sets the mask,
|
||||
<code>ssgSelector::getSelect()</code> returns the current
|
||||
state of the mask, <code>ssgSelector::selectStep(n)</code>
|
||||
sets the n'th mask bit and zeroes out all the others - effectively
|
||||
causing only the n'th child object to be displayed.
|
||||
<p>
|
||||
It is quite common to have an ssgSelector with just one
|
||||
child object that can be enabled with select(1) and disabled
|
||||
with select(0).
|
||||
|
||||
<H2><code>class ssgTimedSelector</code> - An animation node,</H2>
|
||||
This is a selector in which the selection is made as a function
|
||||
of the amount of time elapsed.
|
||||
<p>
|
||||
SSG will draw each of the child objects in turn for some amount
|
||||
of time before going onto the next node in the sequence. You
|
||||
set the time for each child using:
|
||||
<pre>
|
||||
|
||||
ssgTimedSelector::setDuration ( float time, int which_child ) ;
|
||||
|
||||
</pre>
|
||||
...or you can set the same time for each of the child nodes using:
|
||||
<pre>
|
||||
|
||||
ssgTimedSelector::setDuration ( float time ) ;
|
||||
|
||||
</pre>
|
||||
(At present, times are measured in SSG update cycles - ultimately,
|
||||
there will be an option to set the times in seconds - but until
|
||||
I have a reasonably accurate portable timer library, I can't
|
||||
easily implement this).
|
||||
<p>
|
||||
The animation doesn't have to start at the first child node and
|
||||
end at the last. It is sometimes useful to be able to replay
|
||||
just a subset of them.
|
||||
<pre>
|
||||
|
||||
ssgTimedSelector::setLimits ( int start_child, int end_child ) ;
|
||||
|
||||
</pre>
|
||||
You can also choose between a number of animation algorithms:
|
||||
<pre>
|
||||
|
||||
ssgTimedSelector::setMode ( ssgAnimDirection mode ) ;
|
||||
|
||||
Where mode is one of:
|
||||
|
||||
SSG_ANIM_ONESHOT, SSG_ANIM_SHUTTLE, SSG_ANIM_SWING
|
||||
|
||||
</pre>
|
||||
<ul>
|
||||
<li>In SSG_ANIM_ONESHOT mode, the animation starts at the first child
|
||||
you specified with setLimits and ends at the last child you
|
||||
specified. Once the last child has been displayed, the animation
|
||||
will automatically go into STOP mode and continue to display
|
||||
that last object until the application intervenes.
|
||||
<li>In SSG_ANIM_SHUTTLE mode, the animation goes from the start
|
||||
child to the end child - but unlike SSG_ANIM_ONESHOT, when
|
||||
the animation has finished displaying the last child object,
|
||||
it resets to the start child and does it all over again.
|
||||
SSG_ANIM_SHUTTLE animations don't stop running unless the
|
||||
application stops them.
|
||||
<li>In SSG_ANIM_SWING mode, the animation goes from the start
|
||||
child to the end child - but when the end is reached, the
|
||||
animation reverses direction and heads back to the start
|
||||
again. The animation oscillates like a swing until the
|
||||
application stops it.
|
||||
</ul>
|
||||
<p>
|
||||
When all this preparation is done, the application must
|
||||
control the animation:
|
||||
<pre>
|
||||
|
||||
ssgTimedSelector::control ( ssgAnimEnum cntrl ) ;
|
||||
|
||||
Where 'cntrl' is one of:
|
||||
|
||||
SSG_ANIM_START, SSG_ANIM_STOP,
|
||||
SSG_ANIM_PAUSE, SSG_ANIM_RESUME
|
||||
|
||||
</pre>
|
||||
These controls work just like you'd expect. Start, Stop,
|
||||
Pause, Resume. SSG_ANIM_START resets the animation to
|
||||
the 'start' child and lets it rip. SSG_ANIM_STOP causes
|
||||
it to stop wherever it is and continue to display that
|
||||
child node indefinitely. SSG_ANIM_PAUSE pauses the
|
||||
animation wherever it is right now and SSG_ANIM_RESUME
|
||||
allows it to continue from whatever point it was paused.
|
||||
<p>
|
||||
When the animation is in SSG_ANIM_STOP mode, you can
|
||||
use this node just like a normal ssgSelector node
|
||||
using the ssgSelector API.
|
||||
<p>
|
||||
If you need to know which child object is currently being
|
||||
displayed, you cannot call ssgSelector::getSelect() because
|
||||
SSG computes the animation step only if the node is actually
|
||||
on-screen. Instead call ssgTimedSelector::getStep() which
|
||||
returns the currently selected child node.
|
||||
<H2><code>class ssgRangeSelector</code> - A level of detail node,</H2>
|
||||
This is a selector in which the selection is made automatically
|
||||
based on the range to the object. This is principally used to
|
||||
allow you to save time by drawing simpler versions of objects
|
||||
at long ranges and more complex ones close up.
|
||||
<p>
|
||||
Since an <code>ssgRangeSelector</code> is a kind of
|
||||
<code>ssgSelector</code>, you can find
|
||||
out which version of the object was most recently drawn using
|
||||
<code>getSelect()</code>. However, if the object was not drawn recently, that
|
||||
may not be a very useful thing to know. Mostly, it's useful in
|
||||
the post-cull callback.
|
||||
<p>
|
||||
You set the ranges at which each daughter object will be drawn
|
||||
by passing an array of lengths to
|
||||
<code>ssgRangeSelector::setRanges(float *ranges,int nranges)</code>.
|
||||
The first parameter is an array of ranges and the second is the
|
||||
number of elements in that array. Note that element N of the
|
||||
array is the range beyond which child object N will be drawn.
|
||||
The array should contain one more range than there are child
|
||||
objects - and beyond the last range, nothing will be drawn.
|
||||
setRanges takes a copy of your array so you can delete it after
|
||||
the call. If nranges is less than the number required, the
|
||||
remaining ranges will be set to infinity. You can query the
|
||||
current range array with <code>float getRange(int n)</code> which
|
||||
returns the n'th range in the array.
|
||||
<p>
|
||||
In some cases, you'd like to build several complete versions
|
||||
of an object such that just one of those versions will be
|
||||
drawn - and that is the default behaviour. In other cases,
|
||||
you'd like some basic object to be rendered at long range
|
||||
and for additional parts to be added to it at shorter ranges.
|
||||
This is called 'additive' mode and it is set using
|
||||
<code>setAdditive(int additive)</code>
|
||||
and queried with <code>isAdditive()</code>.
|
||||
<H2><code>class ssgBaseTransform</code> - Nodes with transformations.</H2>
|
||||
It is common to wish to move objects around in the scene, scale and rotate
|
||||
them, move their texture maps, etc. All of these operations entail
|
||||
manipulating a matrix associated with the branch node and the
|
||||
ssgBaseTransform contains the functionality to store and manipulate
|
||||
that matrix. Applications use one of the derived classes of ssgBaseTransform
|
||||
to actually do something with that matrix.
|
||||
<pre>
|
||||
|
||||
class ssgBaseTransform : ssgBranch
|
||||
{
|
||||
void getTransform ( sgMat4 xform ) ;
|
||||
virtual void setTransform ( sgVec3 xyz ) ;
|
||||
virtual void setTransform ( sgCoord *xform ) ;
|
||||
virtual void setTransform ( sgCoord *xform, float sx, float sy, float sz ) ;
|
||||
virtual void setTransform ( sgMat4 xform ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
You can set up the transformation matrix using <code>ssgBaseTransform::setTransform()</code>
|
||||
which has versions that allow you to pass either a full-blown
|
||||
4x4 matrix, a simple translation, an 'sgCoord' (which is an xyz translation
|
||||
and a hpr rotation) or an sgCoord and scale factors in each of X, Y and Z
|
||||
directions.
|
||||
<p>
|
||||
<code>ssgBaseTransform::getTransform(matrix)</code> copies the current
|
||||
transform into the matrix that you provide.
|
||||
<H2><code>class ssgTransform</code> - Nodes with spatial transformations.</H2>
|
||||
An ssgTransform is derived from ssgBaseTransform and uses the base classes'
|
||||
transform to transform all the spatial vertices and normals of it's
|
||||
child nodes. This is done by applying the current transform to the
|
||||
GL_MODELVIEW stack each frame.
|
||||
<H2><code>class ssgTexTrans</code> - Nodes with moving texture</H2>
|
||||
ssgTexTrans nodes are just like ssgTransform nodes except that the
|
||||
resulting matrix is applied to the GL_TEXTURE stack rather than
|
||||
the modelview stack. Hence, altering the transform moves the texture
|
||||
map(s) on the descendent leaf nodes.
|
||||
<H2><code>class ssgCutout</code> - turn-to-face-the-viewer nodes.</H2>
|
||||
Cutout nodes will normally contain only leaf nodes that are
|
||||
modelled with polygons in the X/Z plane. The ssgCutout will rotate
|
||||
those polygons such that they turn to continually face the viewer.
|
||||
<p>
|
||||
There are actually two distinct forms of ssgCutout - depending on
|
||||
what value is passed as a parameter to the constructor function.
|
||||
ssgCutout(TRUE) produces an object that rotates around it's
|
||||
origin such as to keep the X/Z plane parallel to the screen and
|
||||
ssgCutout(FALSE) produces one that tries to stay parallel to the
|
||||
screen - but which is only allowed to rotate about the Z axis.
|
||||
The latter form is useful for objects with cylindrical symmetry
|
||||
and the former for those with spherical symmetry.
|
||||
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"><a href="ssgLeaf.html"><= previous =</a></td>
|
||||
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
||||
<td width="33%" align="right"><a href="state.html">= next =></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
157
doc/ssg/index.html
Normal file
@@ -0,0 +1,157 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<center>
|
||||
<H1>SSG: A Simple Scene Graph API</H1>
|
||||
<H1>for OpenGL</H1>
|
||||
by Steve Baker
|
||||
</center>
|
||||
<H2>Introduction</H2>
|
||||
Simple Scene Graph (SSG) is intended to be a really simple,
|
||||
low-impact, scene graph API that layers nicely on top
|
||||
of OpenGL using C++ and which works with or without GLUT.
|
||||
<p>
|
||||
SSG is a part of <A HREF="../index.html">PLIB</A>.
|
||||
<p>
|
||||
This document assumes a certain degree of knowledge of
|
||||
OpenGL.
|
||||
<p>
|
||||
SSG includes a subsidiary library of simple matix and vector
|
||||
math with support for some intersection testing, field-of-view
|
||||
culling and such like. This is called
|
||||
<A HREF="../sg/index.html">'Simple Geometry' (SG)</A>.
|
||||
SG is used extensively by SSG - but is also useful as a
|
||||
standalone library.
|
||||
<p>
|
||||
A Scene Graph is essentially just a tree-structured database
|
||||
containing a hierarchy of branches - and a bunch of leaf nodes.
|
||||
Each leaf node does some OpenGL rendering - the branch nodes
|
||||
are intended to manage things like: field of view (FOV) culling,
|
||||
level of detail (LOD) management, transformations, and animation.
|
||||
<p>
|
||||
In addition, each leaf node has a structure tacked on to it
|
||||
to encapsulate OpenGL state information - and that in turn
|
||||
may optionally have a texture applied to it.
|
||||
<p>
|
||||
In addition to managing the scene graph, SSG contains code
|
||||
to manage the positions of cameras, lights and other rendering
|
||||
aspects of OpenGL.
|
||||
<H2>Symbol Conventions.</H2>
|
||||
Both SSG an SG follow conventions for symbols and tokens that
|
||||
are the conventions used by OpenGL and GLUT.
|
||||
<p>
|
||||
Hence, all SSG symbols for classes and functions start with <code>ssg</code>
|
||||
and all <code>#define</code> tokens start with <code>SSG</code>. Functions and symbols
|
||||
that belong to the SG library similarly start with <code>sg</code> or <code>SG</code>.
|
||||
<p>
|
||||
Words within a class or function name are Capitalised and NOT
|
||||
separated with underscores. Words within <code>#define</code> tokens may
|
||||
be separated with underscores to make them readable.
|
||||
<H2>Initialisation.</H2>
|
||||
The first SSG call in any program must always be ssgInit(). Call
|
||||
ssgInit only after you have obtained an OpenGL rendering context
|
||||
(or called glutInit() and created a rendering window if you are
|
||||
using glut).
|
||||
<H2>Classes</H2>
|
||||
The following class hierarchy makes up the core package - which
|
||||
can be extended to add functionality or to change some underlying
|
||||
mechanisms.
|
||||
<pre>
|
||||
|
||||
class ssgBase
|
||||
|__ class ssgSimpleList
|
||||
| |
|
||||
| |__ class ssgVertexArray
|
||||
| |__ class ssgNormalArray
|
||||
| |__ class ssgTexCoordArray
|
||||
| |__ class ssgColourArray
|
||||
| |__ class ssgIndexArray
|
||||
|
|
||||
|__ class ssgEntity
|
||||
| |
|
||||
| |__ class ssgLeaf
|
||||
| | |__ class ssgVTable (deprecated)
|
||||
| | |__ class ssgVtxTable
|
||||
| | |__ class ssgTween
|
||||
| | |__ class ssgVtxArray
|
||||
| |
|
||||
| |__ class ssgBranch
|
||||
| |__ class ssgRoot
|
||||
| |__ class ssgInvisible
|
||||
| |__ class ssgSelector
|
||||
| | |__ class ssgTimedSelector
|
||||
| | |__ class ssgRangeSelector
|
||||
| |
|
||||
| |__ class ssgBaseTransform
|
||||
| | |__ class ssgTransform
|
||||
| | |__ class ssgTexTrans
|
||||
| |
|
||||
| |__ class ssgCutout
|
||||
| |__ class ssgTweenController
|
||||
|
|
||||
|___ class ssgState
|
||||
| |__ class ssgSimpleState
|
||||
| |__ class ssgStateSelector
|
||||
|
|
||||
|___ class ssgTexture
|
||||
|
||||
</pre>
|
||||
The general idea is that, all geometry is contained in ssgLeaf classes,
|
||||
all data heirarchy is in a ssgBranch classes and all OpenGL state information
|
||||
is in ssgStates.
|
||||
<p>
|
||||
You may not declare instances of ssgBase, ssgEntity, ssgBaseTransform,
|
||||
ssgLeaf or ssgState since they are all abstract classes.
|
||||
<p>
|
||||
It is presumed that applications will add new kinds of leaves, branches,
|
||||
states and textures to customise SSG to their needs.
|
||||
<BR><BR>
|
||||
Here are the further chapters:
|
||||
<BR><BR>
|
||||
<A HREF="ssgBase.html">The base class</A>
|
||||
<BR>
|
||||
<A HREF="ssgEntity.html">An entity of the graph</A>
|
||||
<BR>
|
||||
<A HREF="ssgLeaf.html">A leaf of the graph</A>
|
||||
<BR>
|
||||
<A HREF="branches.html">A branch of the graph</A>
|
||||
<BR>
|
||||
<A HREF="state.html">States (material etc)</A>
|
||||
<BR>
|
||||
<A HREF="ssgContext.html">ssgContext</A>
|
||||
<BR>
|
||||
<A HREF="non_class.html">Non-class functions: Loading, saving and optimizing databases</A>
|
||||
<BR>
|
||||
<A HREF="LoaderWriter.html">How to write plib-loaders and writers</A>
|
||||
<BR><BR>
|
||||
You can go through all the SSG-documentation by clicking on the "= next =>"-links at the bottom of each page.
|
||||
<BR><BR>
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"></td>
|
||||
<td width="34%" align="center"></td>
|
||||
<td width="33%" align="right"><a href="ssgBase.html">= next =></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
936
doc/ssg/non_class.html
Normal file
@@ -0,0 +1,936 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H2>Non-class Functions.</H2>
|
||||
So, with the class functions described above, it is
|
||||
fairly simple to construct a scene graph. So, now that
|
||||
you have one, what can you do with it?
|
||||
<pre>
|
||||
void ssgCullAndDraw ( ssgRoot *root ) ;
|
||||
</pre>
|
||||
This call deals with the entire process of rendering the database.
|
||||
Your application need only call ssgInit(), build a database,
|
||||
create a current context and call ssgCullAndDraw using the root node
|
||||
of that database.
|
||||
<H3>Intersection Testing.</H3>
|
||||
Most applications need to test the scenery to see if moving
|
||||
objects have collided with it - there are several ways to do
|
||||
that - but they all share the same mechanisms:
|
||||
<pre>
|
||||
|
||||
int ssgIsect ( ssgRoot *root, sgSphere *s, sgMat4 m, ssgHit **results ) ;
|
||||
int ssgHOT ( ssgRoot *root, sgVec3 s, sgMat4 m, ssgHit **results ) ;
|
||||
int ssgLOS ( ssgRoot *root, sgVec3 s, sgMat4 m, ssgHit **results ) ;
|
||||
|
||||
</pre>
|
||||
These three calls implement various ways to test the database for collisions,
|
||||
weapon impacts and such like. In each case, the search for a collision
|
||||
starts at 'root', and the database is transformed by the matrix 'm'
|
||||
before the test is evaluated - hence, 'm' is ususally the inverse of
|
||||
the matrix describing the test object's location.
|
||||
<ul>
|
||||
<li>ssgIsect intersects a sphere against the scene.
|
||||
<li>ssgHOT intersects a vertical line starting at the point 's' (remember,
|
||||
in SSG, positive Z is 'up'). This is often used to compute
|
||||
the Height-of-Terrain - hence the name 'HOT'.
|
||||
<li>ssgLOS intersects an arbitary vector whose direction is defined by 's'.
|
||||
</ul>
|
||||
The result in either case is an integer telling
|
||||
you how many triangles impacted the sphere/vector. If you need to know more
|
||||
about these intersections, pass the address of a ssgHit * variable as
|
||||
the last parameter and it will be returned pointing at a STATIC array
|
||||
of ssgHit structures. Thats a confusing explanation - and an example
|
||||
will help:
|
||||
<pre>
|
||||
|
||||
ie:
|
||||
|
||||
ssgHit *results ;
|
||||
|
||||
int num_hits = ssgIsect ( root, &sphere, mat, &results ) ;
|
||||
|
||||
for ( int i = 0 ; i < num_hits ; i++ )
|
||||
{
|
||||
ssgHit *h = &(results [ i ]) ;
|
||||
|
||||
/* Do something with 'h' */
|
||||
}
|
||||
|
||||
</pre>
|
||||
Remember, you must finish using the results array before you do
|
||||
another ssgIsect/ssgHOT/ssgLOS because all three functions share
|
||||
the same results array.
|
||||
<p>
|
||||
By default, these functions only detect collisions with the front face
|
||||
of polygons. You can make them detect only the back faces using:
|
||||
<pre>
|
||||
|
||||
void ssgSetBackFaceCollisions ( bool b ) ;
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
An ssgHit looks like this:
|
||||
<pre>
|
||||
|
||||
class ssgHit
|
||||
{
|
||||
ssgLeaf *leaf ;
|
||||
int triangle ;
|
||||
sgVec4 plane ;
|
||||
sgMat4 matrix ;
|
||||
|
||||
ssgHit ()
|
||||
int getNumPathEntries () ;
|
||||
ssgEntity *getPathEntry ( int i ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
The 'leaf' member points at the leaf node that impacted the sphere.
|
||||
The 'triangle' member tells you which triangle within the leaf
|
||||
did the impacting. The 'plane' member contains the plane equation
|
||||
of the impacting triangle and the 'matrix' element tells you
|
||||
the net result of concatenating all the transform nodes from
|
||||
the root to the leaf to the matrix you provided in the ssgIsect call.
|
||||
<p>
|
||||
It's possible for there to be multiple paths through the
|
||||
scene graph to the leaf node. Sometimes you'll need to
|
||||
look back up the tree to see nodes above the one that we actually
|
||||
impacted with. Hence, you can read all the ssgEntities that were
|
||||
traversed on the path from the root down to the leaf. Calling
|
||||
the 'getNumPathEntries' function to find the number of nodes
|
||||
along the path - and then 'getPathEntry(n)' to get the n'th entry
|
||||
in the path. The 'root' node will always be the zeroth entry
|
||||
in the path - and the leaf node will always be the last.
|
||||
<H3>Lights.</H3>
|
||||
SSG supports the eight standard OpenGL light sources as class 'ssgLight'.
|
||||
Since there are only a finite number of these, they all exist all the
|
||||
time - you just call:
|
||||
<pre>
|
||||
|
||||
ssgLight *ssgGetLight ( int i ) ;
|
||||
|
||||
</pre>
|
||||
...to get the i'th light should you need to manipulate it.
|
||||
<pre>
|
||||
|
||||
class ssgLight
|
||||
{
|
||||
int isOn () ;
|
||||
void on () ;
|
||||
void off () ;
|
||||
|
||||
void setPosition ( const sgVec3 pos ) ;
|
||||
void setPosition ( float x, float y, float z ) ;
|
||||
|
||||
void setColour ( GLenum which , const sgVec4 colour ) ;
|
||||
void setColour ( GLenum which , float r, float g, float b ) ;
|
||||
|
||||
void setHeadlight ( int head ) ;
|
||||
int isHeadlight () ;
|
||||
|
||||
void setSpotlight ( int spot ) ;
|
||||
int isSpotlight () ;
|
||||
|
||||
void setSpotDirection ( const sgVec3 dir ) ;
|
||||
void setSpotDirection ( float x, float y, float z ) ;
|
||||
void setSpotDiffusion ( float exponent, float cutoff = 90.0f ) ;
|
||||
void setSpotAttenuation ( float constant, float linear, float quadratic ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
Each light can be turned on or off - or tested to see if it's on or off.
|
||||
<p>
|
||||
Lights are positioned with 'setPosition()' - which can be relative
|
||||
to the origin of the world - or relative to the SSG camera (in 'headlight'
|
||||
mode).
|
||||
<p>
|
||||
If the 'spotlight' mode is enabled,
|
||||
then the light intensity has a certain distribution and attenuation.
|
||||
These parameters can be set with the 'setSpotXxx' methods.
|
||||
Otherwise, the light source is considered to be directional,
|
||||
or infinitely far away (in the direction of its position).
|
||||
The 'spotlight' mode is initially disabled.
|
||||
|
||||
<H3>Miscellany.</H3>
|
||||
It's convenient to find out how much texture memory has been
|
||||
consumed:
|
||||
<pre>
|
||||
|
||||
int ssgGetNumTexelsLoaded () ;
|
||||
|
||||
</pre>
|
||||
(Bear in mind that a texel could be 16 or 32 bits depending on
|
||||
the hardware - and with MIPmapping enabled, 25% of the texels
|
||||
will be in the MIPmaps - so ssgGetNumTexelsLoaded will return
|
||||
a larger number than the total of the sizes of the input images
|
||||
might suggest.
|
||||
<H3>Loading Database Files.</H3>
|
||||
To load a model file into SSG, you can either call a loader
|
||||
function that is specific to the format of the file you
|
||||
wish to load - or you can call 'ssgLoad' - which parses
|
||||
the filename extension and calls the appropriate format-specific
|
||||
loader.
|
||||
<p>
|
||||
At time or writing, there are MANY loaders for SSG:
|
||||
<ul>
|
||||
<li> ssgLoadSSG - for '.ssg' files - the 'native' SSG format.
|
||||
<li> ssgLoadAC - for '.ac' files - a somewhat obscure format produced
|
||||
by the 'AC3D' modelling tool - reasonably well tried
|
||||
and tested.
|
||||
<li> ssgLoad3ds - for '.3ds' files as produced by 3DStudio.
|
||||
<li> ssgLoadASE - 3DSMAX ASCII EXPORT Version 2.00, well tested
|
||||
<li> ssgLoadDXF - AutoCADs famous DXF format. well tested
|
||||
<li> ssgLoadFLT - OpenFlight. Works for OpenFlight files generated by
|
||||
recent versions of MultiGen - but not for those generated by some other
|
||||
tools such as Designers' Workbench.
|
||||
<li> ssgLoadMD2 - Quake MD2
|
||||
<li> ssgLoadOBJ - Wavefront, works well
|
||||
<li> ssgLoadTRI - simple Tri format from "Andy Colbournes Editor".
|
||||
<li> ssgLoadX - Microsofts DirectX-Format. Most features work.
|
||||
<li> ssgLoadOFF - Geomview's OFF
|
||||
<li> ssgLoadM - ???
|
||||
<li> ssgLoadATG - Ascii TerraGear. Used by Flight Gear Flight Sim.
|
||||
<li> ssgLoadVRML1 - VRML1 format, only partially implemented.
|
||||
<li> ssgLoadIV - Inventor format, only partially implemented.
|
||||
<li> ssgLoadStrip - The format of a stripifier.
|
||||
</ul>
|
||||
|
||||
<pre>
|
||||
|
||||
typedef ssgBranch *(*ssgHookFunc)(char *) ;
|
||||
|
||||
ssgEntity *ssgLoad ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
|
||||
|
||||
ssgEntity *ssgLoadSSG ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
|
||||
ssgEntity *ssgLoadAC ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
|
||||
ssgEntity *ssgLoad3ds ( const char *fname, const ssgLoaderOptions *options = NULL ) ;
|
||||
...etc...
|
||||
|
||||
</pre>
|
||||
Minimally, all you need to do is to call ssgLoadAC/ssgLoad3ds with the
|
||||
name of the file to load. However, most file formats (AC3D's
|
||||
and 3Dstudio's included) lack many desirable features, and it is also often
|
||||
necessary to store application-specific information in the
|
||||
file.
|
||||
<p>
|
||||
SSG's loaders will decode the comment fields found in the
|
||||
nodes of many common file formats and pass these onto the
|
||||
application via 'hookfunc'. This function should decode
|
||||
the string and construct whatever kind of SSG node it
|
||||
considers appropriate.
|
||||
<p>
|
||||
Similarly, the application may wish to embellish the
|
||||
ssgState of a loaded node - and since state information
|
||||
rarely has a comment field in most file formats, we
|
||||
pass the texture filename instead and expect the application
|
||||
to construct the entire ssgState:
|
||||
<pre>
|
||||
|
||||
void ssgSetAppStateCallback ( ssgState *(*cb)(char *) ) ;
|
||||
|
||||
</pre>
|
||||
One common problem with file loaders is that it's
|
||||
often possible to refer to a second file from inside
|
||||
the first - but the <b>path</b> to that file is often
|
||||
not adequately defined by the original file. Hence,
|
||||
the application can specify a file path to be prepended
|
||||
to all model or texture file names.
|
||||
<pre>
|
||||
|
||||
void ssgModelPath ( char *path ) ;
|
||||
void ssgTexturePath ( char *path ) ;
|
||||
|
||||
</pre>
|
||||
You can only supply one path. If you need additional features, use the
|
||||
function <code>ulFindFile</code> (for more see util-library-doc).
|
||||
|
||||
The last three functions simply set values in the _ssgCurrentOptions
|
||||
(type ssgLoaderOptions), for example:
|
||||
|
||||
<pre>
|
||||
inline void ssgModelPath ( const char *path )
|
||||
{
|
||||
_ssgCurrentOptions -> setModelDir ( path ) ;
|
||||
}
|
||||
</pre>
|
||||
|
||||
For more on ssgLoaderOptions see also the next page of this doc.
|
||||
|
||||
<p>
|
||||
|
||||
Some loaders for file formats that use texture formats not
|
||||
supported by ssg use this functions to find textures:
|
||||
<pre>
|
||||
void ssgFindOptConvertTexture( char * filepath, char * tfname )
|
||||
</pre>
|
||||
It finds and optionally (= if necessary) converts the texture.
|
||||
This is only really implemented for Windo$ :-(, for all others it
|
||||
should just be the two lines you will find in the comment. I didn't
|
||||
test it, that's the reason I commented it out. But it will warn you
|
||||
when you have to convert something, so even for non-Windo$-users the
|
||||
new function is already a step forward.
|
||||
For the actual conversion, at first I wanted to use GIMP. So, in Deja,
|
||||
I looked for "+gimp +convert +batch" and similar strings. I found
|
||||
several people asking, but almost all the answer were to use
|
||||
ImageMagick instead. ImageMagick is free as in beer. Also, the docs I
|
||||
got with the newest gimp is extremely sparse :-(. Therefore, I tried
|
||||
ImageMagick and this worked straight away. You should find ImageMagick
|
||||
under
|
||||
<p>
|
||||
http://www.wizards.dupont.com/cristy/ImageMagick.html
|
||||
<p>
|
||||
Plib uses the ImageMagick application "convert". Since there are other
|
||||
convert.exe-programs on my computer, I had to copy the ImageMagick
|
||||
stuff into the directory of my plib-application, so that it uses the correct
|
||||
convert.exe.
|
||||
<p>
|
||||
|
||||
|
||||
Most file formats contain considerable numbers of redundant
|
||||
nodes (because of the way people build using these tools).
|
||||
This function walks a database sub-tree multiplying
|
||||
out any ssgTransform nodes and replacing them with
|
||||
ssgBranch'ed - unless they have userdata associated with them.
|
||||
Any branch nodes with zero kids are deleted - any with just
|
||||
one kid are eliminated and the child node pushed up one level.
|
||||
<pre>
|
||||
|
||||
void ssgFlatten ( ssgEntity *ent ) ;
|
||||
|
||||
</pre>
|
||||
It's important for 3D performance to optimise
|
||||
triangles into triangle strips or fans. Since most
|
||||
file formats don't record strip/fan information,
|
||||
it's useful to call:
|
||||
<pre>
|
||||
|
||||
void ssgStripify ( ssgEntity *ent ) ;
|
||||
|
||||
</pre>
|
||||
<H3>Saving Database Files.</H3>
|
||||
Most SSG programs will simply load a file and display it in
|
||||
some way - but occasionally, it's useful to be able to write
|
||||
a file back out again.
|
||||
<p>
|
||||
To write a model file from SSG, you can either call a writer
|
||||
function that is specific to the format of the file you
|
||||
wish to save - or you can call 'ssgSave' - which parses
|
||||
the filename extension and calls the appropriate format-specific
|
||||
writer.
|
||||
<p>
|
||||
Saving into ssg-format is done with these functions:
|
||||
<ul>
|
||||
<li> ssgSaveSSG - for '.ssg' files - the 'native' SSG format.
|
||||
</ul>
|
||||
<pre>
|
||||
|
||||
int ssgSave ( char *fname, ssgEntity *ent ) ;
|
||||
int ssgSaveSSG ( char *fname, ssgEntity *ent ) ;
|
||||
|
||||
</pre>
|
||||
This returns TRUE if the operation worked - FALSE if it failed.
|
||||
You will also find writers for the 3DS, AC, ASE, ATG, DXF, M, OBJ, OFF, QHI, TRI and
|
||||
X formats.
|
||||
|
||||
<H3>Features of the file formats and status of the loaders/writers</H3>
|
||||
|
||||
Here comes a table of the features of all the file formats and loaders and writers.
|
||||
VRML doesn't really work, so you won't find it here.
|
||||
The "QHI" (QHull Input - a format used by a toll to create convex hulls)
|
||||
writer only writes a point cloud and suppoorts no other features, so I also didn't add it to the table.
|
||||
BTW, if you want to create convex hulls of existing geometry, you just need a few lines. Look
|
||||
into PPE (prettypoly editor, on SourceForge as well), into the file ppeCoreFuncs.cxx,
|
||||
function addConvexHull.
|
||||
The SSG loaders/writers support all
|
||||
features of the ssg-lib, so missing features mean they miss in the library (normaly because they miss in OpenGL)
|
||||
The letters mean:
|
||||
<BR><BR>
|
||||
A = feature not in file format
|
||||
<BR>
|
||||
B = feature in file format and not implemented, not planned.
|
||||
<BR>
|
||||
C = feature in file format and not implemented, but planned.
|
||||
<BR>
|
||||
D = feature in file format and partly implemented or not tested.
|
||||
<BR>
|
||||
E = feature in file format and implemented.
|
||||
<BR><BR>
|
||||
And here are the features with some explanaitions:
|
||||
<BR><BR>
|
||||
|
||||
<ul>
|
||||
<li>Filled polys - Planar polygons. In the ssg-lib, this is the only primitive you can use to make "solid" looking models. This is a 2D primitive; it has no volume but an area.
|
||||
<li># sides - No of sides per poly. This is of course equal to number of vertices per poly. Some formats support only triangles, some
|
||||
also quads and some support n-sided polys, that is they have no restrictions.
|
||||
<li>Lines - for example used for high voltage lines in a flight simulator.
|
||||
This is a 1D primitive; it has no area but a length.
|
||||
<li>Points - for example used for small lights.
|
||||
This is a "0D" primitive; it has no length.
|
||||
<li>Sub objects - The complete model may consist of several sub models.
|
||||
There are several reasons one wants this, for example to make the structure of the model
|
||||
clearer to humans, to easily enable humans or programs to move, colour, texture, animate etc
|
||||
one part, for example one wheel of the complete model.
|
||||
<li>Hierarchie - You not only have sub objects, but there is a parent-kid relation between some,
|
||||
for example, the upper arm of a human model may be "under" the body and the lower arm "under" the upper arm etc.
|
||||
<li>DAG - direct acyclic graph means that the hierarchie may not only be a tree where
|
||||
each node has exactly one parent (apart from the root, which has zero parents), but that nodes may have more than one parent.
|
||||
Used for example in cars to have the wheel geometry only once. If the one wheel-node has four parents, this means
|
||||
it will be rendered four times when the scene is drawn.
|
||||
<li>Colours - Things can have a colour. Uncoloured objects are always white.
|
||||
<li>Textures - Texture things with 2D bitmaps.
|
||||
<li>Texture coordinates - The texture mapping is arbitrary.
|
||||
<li>Texture coord. per face AND vertex - If a vertex is part of three faces, then this feature
|
||||
allows it to have three texture coordinates. For example, a cube may have 18 texture coordinates, even if it has much fewer vertices.
|
||||
<li>Texture per face - each face may have another texture bitmap. Formats (and the ssg lib) that
|
||||
don't have this have to increase the number of nodes to get this effect.
|
||||
<li>Transparency - Some polys may be partially or completely transparent.
|
||||
<li>Animation - There may be many different sorts of animation.
|
||||
<li>Billboards - geometry that automatically rotates so it always faces the viewer. Normaly flat.
|
||||
As an example, can be used to model trees in a driving simulator.
|
||||
<li>LOD - stands for "Level of Detail" and means there can be geometries of varying
|
||||
complexity for the model, so for example, if it is near the viewer you use many polys
|
||||
and if it is far away you use few polys so that the impact on rendering speed is low.
|
||||
<li>Other switches - switch means you can switch the visibility of some nodes on and off.
|
||||
<li>Ascii or Binary - A stands for Ascii, B for Binary files.
|
||||
</ul>
|
||||
|
||||
<table width="100%" border="1" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td> Feature</td>
|
||||
<td> 3DS<BR>load</td>
|
||||
<td> AC<BR>load/<BR>save</td>
|
||||
<td> ASC<BR>save</td>
|
||||
<td> ASE<BR>load/<BR>save</td>
|
||||
<td> ATG<BR>load/<BR>save</td>
|
||||
<td> DXF<BR>load</td>
|
||||
<td> DXF<BR>save</td>
|
||||
<td> FLT<BR>load</td>
|
||||
<td> M<BR>load/<BR>save</td>
|
||||
<td> MD2<BR>load</td>
|
||||
<td> OBJ<BR>load</td>
|
||||
<td> OBJ<BR>save</td>
|
||||
<td> OFF<BR>load/<BR>save</td>
|
||||
<td> SSG<BR>load/<BR>save</td>
|
||||
<td> Strip<BR>load</td>
|
||||
<td> TRI<BR>load/<BR>save</td>
|
||||
<td> X<BR>load</td>
|
||||
<td> IV<BR>load</td>
|
||||
<td> VRML1<BR>load</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Filled polys</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E(5)</td>
|
||||
<td> E</td>
|
||||
<td> E/D</td>
|
||||
<td> ?</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> </td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> # sides</td>
|
||||
<td> </td>
|
||||
<td> n/3</td>
|
||||
<td> 3</td>
|
||||
<td> 3</td>
|
||||
<td> n</td>
|
||||
<td> 3,4(4)</td>
|
||||
<td> 3</td>
|
||||
<td> n</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> n?</td>
|
||||
<td> 3</td>
|
||||
<td> n</td>
|
||||
<td> n(4)</td>
|
||||
<td> </td>
|
||||
<td> 3?</td>
|
||||
<td> n</td>
|
||||
<td> 3,4</td>
|
||||
<td> 3,4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Lines</td>
|
||||
<td> A</td>
|
||||
<td> D/C</td>
|
||||
<td> C</td>
|
||||
<td> E</td>
|
||||
<td> A(?)</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> A?</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> A</td>
|
||||
<td> B</td>
|
||||
<td> B</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Points</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> C</td>
|
||||
<td> A(?)</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> B</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> A</td>
|
||||
<td> B</td>
|
||||
<td> B</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Sub objects</td>
|
||||
<td> E</td>
|
||||
<td> E/D</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> A(?)</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> C-D</td>
|
||||
<td> C-D</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Hierarchie</td>
|
||||
<td> A</td>
|
||||
<td> E/D</td>
|
||||
<td> E?</td>
|
||||
<td> E</td>
|
||||
<td> A(?)</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> C</td>
|
||||
<td> C</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> C</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> DAG</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A(?)</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> A(?)</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Colours</td>
|
||||
<td> E</td>
|
||||
<td> E/D</td>
|
||||
<td> E?</td>
|
||||
<td> E</td>
|
||||
<td> ?</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> D(1)</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> D</td>
|
||||
<td> C</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> E</td>
|
||||
<td> B</td>
|
||||
<td> B</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Textures</td>
|
||||
<td> D</td>
|
||||
<td> E/D</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> D</td>
|
||||
<td> C</td>
|
||||
<td> B</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Texture coord.</td>
|
||||
<td> D</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> E</td>
|
||||
<td> C</td>
|
||||
<td> B</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Texture coord.<BR>per face<BR>AND vertex</td>
|
||||
<td> D(?)</td>
|
||||
<td> D(?)</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> E</td>
|
||||
<td> C</td>
|
||||
<td> B(?)</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> C</td>
|
||||
<td> E</td>
|
||||
<td> E</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Texture per face</td>
|
||||
<td> </td>
|
||||
<td> D(?)/-</td>
|
||||
<td> C</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> B(?)</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> C</td>
|
||||
<td> B</td>
|
||||
<td> A</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Transparency</td>
|
||||
<td> D</td>
|
||||
<td> D</td>
|
||||
<td> D</td>
|
||||
<td> D</td>
|
||||
<td> A(?)</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> A?</td>
|
||||
<td> A?</td>
|
||||
<td> B(?)</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> E</td>
|
||||
<td> B</td>
|
||||
<td> B</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Animation</td>
|
||||
<td> B</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> B(2)</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> A?</td>
|
||||
<td> A?</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> B or C</td>
|
||||
<td> B</td>
|
||||
<td> A</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Billboards</td>
|
||||
<td> </td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> A</td>
|
||||
<td> B</td>
|
||||
<td> A</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> LOD</td>
|
||||
<td> </td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> A</td>
|
||||
<td> B</td>
|
||||
<td> B</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> Other switches</td>
|
||||
<td> </td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> D</td>
|
||||
<td> A</td>
|
||||
<td> ?</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> E</td>
|
||||
<td> A</td>
|
||||
<td> </td>
|
||||
<td> A</td>
|
||||
<td> D</td>
|
||||
<td> D</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> A=Ascii or<BR>B=Binary</td>
|
||||
<td> B</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> B</td>
|
||||
<td> A</td>
|
||||
<td> B</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
<td> B</td>
|
||||
<td> ?</td>
|
||||
<td> A</td>
|
||||
<td> A+B(3)</td>
|
||||
<td> A</td>
|
||||
<td> A</td>
|
||||
</tr>
|
||||
</table>
|
||||
footnotes:
|
||||
<BR><BR>
|
||||
(1) problematic for ancient files
|
||||
<BR>
|
||||
(2) DOFs are not implemented
|
||||
<BR>
|
||||
(3) There is an ascii- and a binary X-file-format.
|
||||
I only implemented the ascii-one and probably wont implement the
|
||||
binary one. There is a free (as in beer) converter by Microsoft
|
||||
running under Windo$.
|
||||
<BR>
|
||||
(4) It is possible to have polys with an arbitrary number of vertices in ssg.
|
||||
But then you may only use one poly per node. Also, you can not mix 3 and 4 sided polys in one node.
|
||||
<BR>
|
||||
(5) Some OpenGL modes, like for example Quads, are ignored. This means some parts of the model
|
||||
may dissappear when saving into DXF files.
|
||||
<BR><BR>
|
||||
Additional info on some formats:
|
||||
|
||||
<BR><BR>
|
||||
ATG:
|
||||
<BR>
|
||||
ATG stands for ascii TerraGear. Loading of TriStrips and TriFans not implemented yet.
|
||||
Untextured parts are lost, for example when you save and load
|
||||
Steve Bakers Tuxedo, you will loose the feet, since they are not
|
||||
textured.
|
||||
The files written are not optimal, they use no strips/fans,
|
||||
only have triangles etc.
|
||||
Also, one vertex that needs several texture coords is written out several
|
||||
times.
|
||||
|
||||
|
||||
<BR><BR>
|
||||
3ds-writer:
|
||||
<BR>
|
||||
I (Per) have one basicly working, but since there seems to be so much else to do
|
||||
with plib right now, I'm a bit reluctant to put my energy into it. Also, the
|
||||
only 3ds-loader I've tested files written by it with is the one in ssg :-)
|
||||
|
||||
|
||||
<BR><BR>
|
||||
OFF loader:
|
||||
<BR>
|
||||
Warning: There are two formats called OFF! We support the OFF from GeomView,
|
||||
not the one from DEC.
|
||||
We support 2D and 3D, but no higher dimensions.
|
||||
|
||||
<BR><BR>
|
||||
.SSG file loader/writer:
|
||||
<BR>
|
||||
We number .SSG file formats so that for example the loaders knows
|
||||
what to expect. Until now, there is
|
||||
<BR>
|
||||
format "0" - Used by plib 1.2.0, 1.3.x
|
||||
<BR>
|
||||
format "1" - Will be used by 1.4.0
|
||||
<BR>
|
||||
Currently, we are between "0" and "1". Normally, we want to keep at least our loader
|
||||
compatible, but the changes from zero to one would bloat the code so much and it seems
|
||||
.SSG file version zero were only used by people for temporary files, so we decided to make an incompatible break.
|
||||
If you need to read or write version zero, either get plib from SVN with the date 14.1.2001, or, if you are a Windo$ person, get
|
||||
<a href="prettypoly.sourceforge.net/download/ppewinbin_ssg_version_zero.zip">prettypoly.sourceforge.net/download/ppewinbin_ssg_version_zero.zip</a>
|
||||
This allows you to save and load .ssg version zero.
|
||||
<BR>
|
||||
One of the new features in format "1" might be worth mentioning.
|
||||
It is now possible to load and save *any* class derived from ssgBase (notably
|
||||
the ssgAux node types).
|
||||
All that is needed for saving to work is an implementation of the virtual save() method.
|
||||
Loading requires the corresponing load() method, and also means for creating
|
||||
an instance of the class, which is accomplished
|
||||
by a call to ssgRegisterType().
|
||||
See the ssgAux implementation for example usage;
|
||||
the convenience function ssgaInit() registers the ssgAux classes.
|
||||
<BR><BR>
|
||||
.X file writer:
|
||||
<BR>
|
||||
Planned.
|
||||
<BR><BR>
|
||||
.X file loader:
|
||||
<BR>
|
||||
The .X-entity "Frame" is not yet implemented.
|
||||
If you convert files into .X with "3D Exploration", you can check the
|
||||
option "without frames".
|
||||
|
||||
<BR><BR>
|
||||
VRML1/IV file loaders:
|
||||
<BR>
|
||||
These are only partially implemented, and are useful primarily for
|
||||
mesh-based models (textured or untextured). It would be useful to add
|
||||
material support to these loaders, as well as explicit normal definition.
|
||||
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"><a href="ssgContext.html"><= previous =</a></td>
|
||||
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
||||
<td width="33%" align="right"><a href="LoaderWriter.html">= next =></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
233
doc/ssg/ssgBase.html
Normal file
@@ -0,0 +1,233 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H2><code>class ssgBase</code> - The Universal Abstract Base Class.</H2>
|
||||
All significant SSG classes are derived from ssgBase - which offers a type testing
|
||||
mechanism and a means to print out the tree hierarchy in human-readable form,
|
||||
or to save/load it to/from disk.
|
||||
<pre>
|
||||
|
||||
class ssgBase
|
||||
{
|
||||
void ref () ;
|
||||
void deRef () ;
|
||||
int getRef () ;
|
||||
|
||||
int isA ( int ty ) ;
|
||||
int isAKindOf ( int ty ) ;
|
||||
|
||||
int getType (void) ;
|
||||
virtual char *getTypeName(void) ;
|
||||
|
||||
ssgBase *getUserData () ;
|
||||
void setUserData ( ssgBase *user_data ) ;
|
||||
|
||||
void setName ( char *nm ) ;
|
||||
char *getName () ;
|
||||
const char *getPrintableName () ;
|
||||
|
||||
virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ;
|
||||
virtual int load ( FILE *fd ) ;
|
||||
virtual int save ( FILE *fd = stderr ) ;
|
||||
|
||||
ssgBase *clone ( int clone_flags ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
|
||||
<H3>Reference Counting.</H3>
|
||||
All SSG classes are reference counted - that means that whenever you
|
||||
connect a node into the scene graph with <code>ssgBranch::addKid()</code>, we
|
||||
increment its reference count and each time we remove a node from
|
||||
the graph with <code>ssgBranch::removeKid()</code>, we decrement the count -
|
||||
and if it's zero, we'll delete the node to recover memory.
|
||||
<p>
|
||||
Sometimes, you need a node to stay in memory even though it may be
|
||||
be disconnected from the scene graph. You can achieve that by
|
||||
calling <code>ssgBase::ref()</code> to increment the reference count.
|
||||
If you later find you don't need that node anymore then you may
|
||||
<code>ssgBase::deRef()</code> it. If you <code>ssgBase::deRef()</code>
|
||||
a node to zero, SSG won't automatically delete it - you still need to use
|
||||
<code>delete</code> to do that. Since such deletions are recursive,
|
||||
you may delete an entire sub-branch with a single call.
|
||||
<p>
|
||||
Instead of using <code>ssgBase::deRef()</code> directly, you should use
|
||||
<code>ssgDeRefDelete()</code> which automatically deletes the node if
|
||||
the reference count drops to zero.
|
||||
<p>
|
||||
You can read the current ref count for a node
|
||||
using <code>ssgBase::getRef()</code>.
|
||||
<H3>Names.</H3>
|
||||
It's often useful to attach an ASCII name to a node in the
|
||||
scene graph - this is often derived from a name field in
|
||||
whatever modelling tool was used to create the object.
|
||||
<code>ssgBase::setName(s)</code> sets the name,
|
||||
<code>ssgBase::getName()</code> returns it.
|
||||
|
||||
<H3>User Data</H3>
|
||||
Although one can derive a new C++ class from an SSG class and thereby customise
|
||||
it's behavior, it's often more convenient to simply attach application-specific
|
||||
data structures to a basic entity. Two functions are provided:
|
||||
<code>ssgBase::getUserData()</code> and <code>ssgBase::setUserData(data)</code>.
|
||||
<p>
|
||||
Notice that user data is of class ssgBase - which means that user data
|
||||
can be named, ref-counted - and can in turn have user data of it's own.
|
||||
This allows user data to be formed into linked lists when multiple
|
||||
user data items need to be attached to a single node.
|
||||
|
||||
<H3>Destructor Functions</H3>
|
||||
When an SSG entity is NOT connected into the scene graph in any
|
||||
way, then the correct way to get rid of it and free up memory
|
||||
is to call it's destructor function. However, when the entity
|
||||
is included into the scene graph, you should disconnect it
|
||||
from the tree and let the reference count mechanism take care
|
||||
of the cleanup.
|
||||
<H3>Type Names</H3>
|
||||
SSG frequently needs to know what kind of an object an ssgBase is.
|
||||
Since C++ programs may create new classes that inherit from SSG
|
||||
classes, we provide several functions to make run time type determination
|
||||
possible. There is an external function for each type that
|
||||
returns the type token for that type:
|
||||
<pre>
|
||||
|
||||
int ssgTypeBase () ;
|
||||
int ssgTypeEntity () ;
|
||||
int ssgTypeLeaf () ;
|
||||
int ssgTypeVTable () ;
|
||||
int ssgTypeVtxTable () ;
|
||||
int ssgTypeDisplayList() ;
|
||||
int ssgTypeBranch () ;
|
||||
int ssgTypeBaseTransform ();
|
||||
int ssgTypeTransform () ;
|
||||
int ssgTypeTexTrans () ;
|
||||
int ssgTypeSelector () ;
|
||||
int ssgTypeTimedSelector () ;
|
||||
int ssgTypeRangeSelector () ;
|
||||
int ssgTypeRoot () ;
|
||||
int ssgTypeCutout () ;
|
||||
|
||||
</pre>
|
||||
Now, you can use the <code>ssgBase::isA(type)</code> or <code>ssgBase::isAKindOf</code>
|
||||
to test the type of the node. For example, if you want to test
|
||||
whether a node is a Leaf node or a Branch node, you can do this:
|
||||
<pre>
|
||||
|
||||
if ( mynode -> isAKindOf ( ssgTypeLeaf() ) )
|
||||
printf ( "Leaf node\n" ) ;
|
||||
else
|
||||
if ( mynode -> isAKindOf ( ssgTypeBranch() ) )
|
||||
printf ( "Branch node\n" ) ;
|
||||
else
|
||||
printf ( "Something else\n" ) ;
|
||||
|
||||
</pre>
|
||||
Notice that if you ran that code on (say) an ssgSelector, then it'll
|
||||
print "Branch node" since the Selector class is derived from the Branch
|
||||
class. If you wanted to tell if a node was *exactly* a Branch node -
|
||||
and not from a derived class, then you could use:
|
||||
<pre>
|
||||
|
||||
if ( mynode -> isA ( ssgTypeBranch() ) )
|
||||
printf ( "Branch node\n" ) ;
|
||||
|
||||
</pre>
|
||||
Finally, you can actually read the type of a node - either as a
|
||||
token (using <code>ssgBase::getType()</code>) or as an ASCII string
|
||||
(using <code>ssgBase::getTypeName()</code>). The latter is very useful
|
||||
for debug routines:
|
||||
<pre>
|
||||
|
||||
printf ( "ERROR - something wrong with my '%s' node.\n",
|
||||
mynode -> getTypeName () ) ;
|
||||
|
||||
</pre>
|
||||
|
||||
<H3>Printing</H3>
|
||||
It's sometimes useful during debug to print a section of the
|
||||
scene graph so you can examine it. <code>ssgBase::print(fd, indent, how_much)</code>
|
||||
does that for you - it prints out the node itself - and anything
|
||||
connected beneath it in the scene graph. <code>fd</code> is the
|
||||
file descriptor to print to (defaults to stderr) and
|
||||
<code>indent</code> is a string that will prefix all output lines
|
||||
- and is used internally within SSG to make printout of tree
|
||||
structures more legible by indenting them.
|
||||
<p>
|
||||
The values for the parameter <code>how_much</code> may be 0,1,2,3 or 4
|
||||
and determine how much is printed, with 0 meaning little
|
||||
and 4 meaning much.
|
||||
<BR>
|
||||
For how_much = 0, basic information of the branches is printed
|
||||
<BR>
|
||||
For 1, additionally there is: basic leaf info, state pointers
|
||||
<BR>
|
||||
For 2, additionally there is: states, user data, number of parents,
|
||||
bSphere
|
||||
<BR>
|
||||
For 3, additionally there is: Reference count
|
||||
<BR>
|
||||
For 4, additionally there is: contents of vertex-, normal-, colour-,
|
||||
texCoord- and index-arrays
|
||||
<BR>
|
||||
Experience tells that for <code>how_much = 0</code> you get very little
|
||||
out put, with 1, 2 and 3 a manageable amount and with 4 a huge amount,
|
||||
up to 100 MB for a medium sized model.
|
||||
|
||||
|
||||
<p>
|
||||
It would be unwise
|
||||
to attempt to parse the output of <code>ssgBase::print</code> into another
|
||||
program since it is only intended for human consumption and the
|
||||
format may change dramatically between revisions of SSG.
|
||||
|
||||
<H3>Cloning:</H3>
|
||||
All classes derived from ssgBase have a member function
|
||||
<code>ssgBase *clone(int clone_flags)</code> which new's a
|
||||
new object of that class as a copy of the calling object.
|
||||
<p>
|
||||
The 'clone_flags' is a set of tokens that you 'OR' together to
|
||||
specify how 'deep' you want the cloning to go. By default
|
||||
(with clone_flags==0), only the object itself is cloned and
|
||||
the clone will simply point to the same child structures as
|
||||
the original object. However, if you OR in 'SSG_CLONE_RECURSIVE',
|
||||
then all ssgEntities beneath this one will also be cloned.
|
||||
ORing in SSG_CLONE_GEOMETRY will cause all the per-vertex data
|
||||
at the leaf nodes to also be cloned. SSG_CLONE_STATE causes
|
||||
ssgState objects to be cloned also, SSG_CLONE_STATE_RECURSIVE
|
||||
also causes states pointed to by other states to be copied,
|
||||
SSG_CLONE_USERDATA causes user data attached to
|
||||
the original node to be referenced (NOT copied) by the clone -
|
||||
otherwise, user data for the clone is set to NULL. Finally,
|
||||
SSG_CLONE_TEXTURE causes texture maps to be replicated also.
|
||||
<p>
|
||||
Most copy operations will typically use either zero, SSG_CLONE_RECURSIVE
|
||||
or (SSG_CLONE_RECURSIVE | SSG_CLONE_GEOMETRY)
|
||||
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"><a href="index.html"><= previous =</a></td>
|
||||
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
||||
<td width="33%" align="right"><a href="ssgEntity.html">= next =></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
183
doc/ssg/ssgContext.html
Normal file
@@ -0,0 +1,183 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H2>ssgContext</H2>
|
||||
A 'context' is a set of parameters that relate to rendering
|
||||
one SSG image. It contains the camera parameters and some
|
||||
default state information.
|
||||
<pre>
|
||||
|
||||
class ssgContext
|
||||
{
|
||||
ssgContext () ;
|
||||
void forceBasicState () { basicState -> force () ; }
|
||||
|
||||
void makeCurrent () ;
|
||||
int isCurrent () ;
|
||||
|
||||
void overrideTexture ( int on_off ) ;
|
||||
void overrideCullface ( int on_off ) ;
|
||||
int textureOverridden () { return ovTexture ; }
|
||||
int cullfaceOverridden () { return ovCullface ; }
|
||||
void setCullface ( int on_off ) { cullFace = on_off ; }
|
||||
int cullfaceIsEnabled () { return cullFace ; }
|
||||
|
||||
sgFrustum *getFrustum () { return frustum ; }
|
||||
|
||||
void getNearFar ( float *n, float *f ) ;
|
||||
void getFOV ( float *w, float *h ) ;
|
||||
void getOrtho ( float *w, float *h ) ;
|
||||
void setNearFar ( float n, float f ) ;
|
||||
void setOrtho ( float w, float h ) ;
|
||||
void setFOV ( float w, float h ) ;
|
||||
|
||||
int isOrtho () { return orthographic ; }
|
||||
|
||||
void getCameraPosition ( sgVec3 pos ) ;
|
||||
void setCamera ( sgMat4 mat ) ;
|
||||
void setCamera ( sgCoord *coord ) ;
|
||||
|
||||
void loadProjectionMatrix () ;
|
||||
void loadModelviewMatrix () ;
|
||||
|
||||
void getProjectionMatrix ( sgMat4 dst ) ;
|
||||
void getModelviewMatrix ( sgMat4 dst ) ;
|
||||
|
||||
void clrClipPlane ( int i ) ;
|
||||
void setClipPlane ( int i, sgVec4 plane ) ;
|
||||
int isSetClipPlane ( int i ) ;
|
||||
float *getClipPlane ( int i ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
In all 3D rendering, you need the concept of a virtual camera - or
|
||||
eyepoint. This is set up in SSG with the following calls:
|
||||
<pre>
|
||||
|
||||
void ssgContext::setFOV ( float w, float h ) ;
|
||||
void ssgContext::setNearFar( float n, float f ) ;
|
||||
void ssgContext::setCamera ( sgCoord *coord ) ;
|
||||
|
||||
</pre>
|
||||
The setFOV call sets up the vertical and horizontal fields
|
||||
of view (in degrees), setNearFar sets the near and far
|
||||
clip planes (in whatever units your model is built in).
|
||||
Finally, you can position the virtual camera relative to
|
||||
the database origin using setCamera.
|
||||
<p>
|
||||
Very often, an SSG program contains other non-SSG routines that
|
||||
are accessing OpenGL state. Even a menu drawn using PUI or an
|
||||
overlay in raw OpenGL or using FNT will change the current
|
||||
state of OpenGL. Since SSG does 'lazy' state changes (only
|
||||
updating those states that need to be changed) - it will be
|
||||
fooled into no setting some things that some ssgLeaf nodes
|
||||
really need.
|
||||
<p>
|
||||
This isn't a problem so long as the application doesn't change states
|
||||
DURING ssgCullAndDraw (by using derived class member functions, callbacks,
|
||||
etc). If you need to do that then be sure to call forceBasicState()
|
||||
before you return to SSG.
|
||||
<pre>
|
||||
|
||||
void ssgContext::forceBasicState ( void ) ;
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
During testing, you sometimes need to disable texture rendering,
|
||||
or backface culling:
|
||||
<pre>
|
||||
|
||||
void ssgContext::overrideTexture ( int on_off ) ;
|
||||
void ssgContext::overrideCullface ( int on_off ) ;
|
||||
|
||||
</pre>
|
||||
The six standard OpenGL user-defined clipping planes
|
||||
can be setup and managed automatically using these
|
||||
calls:
|
||||
<pre>
|
||||
|
||||
void clrClipPlane ( int i ) ;
|
||||
void setClipPlane ( int i, sgVec4 plane ) ;
|
||||
int isSetClipPlane ( int i ) ;
|
||||
float *getClipPlane ( int i ) ;
|
||||
|
||||
</pre>
|
||||
setClipPlane takes the number of the plane (0 through 5) and
|
||||
a plane equation which will be applied at the next cull/draw
|
||||
cycle. clrClipPlane removes a clip plane. isSetClipPlane inquires
|
||||
about whether the i'th plane is turned on and getClipPlane returns
|
||||
the plane that's currently set as the i'th plane.
|
||||
<p>
|
||||
Once you have your context set up as you'd like, you have to
|
||||
make it become the 'current' context.
|
||||
<pre>
|
||||
|
||||
void ssgContext::makeCurrent () ;
|
||||
|
||||
</pre>
|
||||
There is a non-class function:
|
||||
<pre>
|
||||
|
||||
ssgContext *ssgGetCurrentContext() ;
|
||||
|
||||
</pre>
|
||||
...which returns the current context.
|
||||
<p>
|
||||
The 'ssgContext' class was not present in PLIB 1.0.xx, so (for
|
||||
backwards compatibility) there is an initial context assigned
|
||||
inside ssgInit(). In addition to the member functions of ssgContext,
|
||||
there are a number of equivelent global functions that are
|
||||
equivelent to ssgGetCurrentContext()->member_function(). These
|
||||
functions are deprecated for new code:
|
||||
<pre>
|
||||
|
||||
inline void ssgForceBasicState () ;
|
||||
inline void ssgGetCameraPosition ( sgVec3 pos ) ;
|
||||
inline void ssgOverrideTexture ( int on_off ) ;
|
||||
inline void ssgOverrideCullface ( int on_off ) ;
|
||||
inline void ssgGetNearFar ( float *n, float *f ) ;
|
||||
inline void ssgGetFOV ( float *w, float *h ) ;
|
||||
inline void ssgSetFOV ( float w, float h ) ;
|
||||
inline void ssgSetOrtho ( float w, float h ) ;
|
||||
inline void ssgSetNearFar ( float n, float f ) ;
|
||||
inline void ssgSetCamera ( sgMat4 mat ) ;
|
||||
inline void ssgSetCamera ( sgCoord *coord ) ;
|
||||
inline void ssgLoadProjectionMatrix () ;
|
||||
inline void ssgLoadProjectionMatrix ( sgFrustum *f ) ;
|
||||
inline void ssgGetProjectionMatrix ( sgMat4 dst ) ;
|
||||
inline void ssgGetModelviewMatrix ( sgMat4 dst ) ;
|
||||
inline void ssgLoadModelviewMatrix () ;
|
||||
inline void ssgLoadModelviewMatrix ( sgMat4 mat ) ;
|
||||
|
||||
</pre>
|
||||
|
||||
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"><a href="state.html"><= previous =</a></td>
|
||||
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
||||
<td width="33%" align="right"><a href="non_class.html">= next =></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
146
doc/ssg/ssgEntity.html
Normal file
@@ -0,0 +1,146 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H2><code>class ssgEntity</code> - A Node in the Tree.</H2>
|
||||
All nodes in the SSG scene graph are ssgEntities.
|
||||
<pre>
|
||||
|
||||
clas ssgEntity : public ssgBase
|
||||
{
|
||||
public:
|
||||
|
||||
ssgEntity (void) ;
|
||||
virtual ~ssgEntity (void) ;
|
||||
|
||||
int getTraversalMask () ;
|
||||
void setTraversalMask ( int t ) ;
|
||||
void setTraversalMaskBits ( int t ) ;
|
||||
void clrTraversalMaskBits ( int t ) ;
|
||||
|
||||
virtual void recalcBSphere (void) ;
|
||||
int isDirtyBSphere (void) ;
|
||||
void dirtyBSphere () ;
|
||||
sgSphere *getBSphere () ;
|
||||
|
||||
virtual int getNumKids (void) ;
|
||||
int getNumParents () ;
|
||||
ssgBranch *getParent ( int p ) ;
|
||||
ssgBranch *getNextParent () ;
|
||||
|
||||
virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ;
|
||||
virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ;
|
||||
virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
|
||||
<H3>The tree structure.</H3>
|
||||
Every entity has a list of parent entities and (conceptually), a list of
|
||||
child entities ("kids"). In practice, ssgRoot nodes never have parents
|
||||
and ssgLeaf nodes never have kids.
|
||||
<p>
|
||||
The structure of the scene graph permits the same node to be inserted
|
||||
into the graph in multiple locations. This is useful for saving
|
||||
space when the same object is needed many times in the scene.
|
||||
Hence, any given node may have more than one parent node.
|
||||
<p>
|
||||
You can traverse the list of parent nodes
|
||||
using <code>ssgEntity::getNumParents()</code> to find out the number
|
||||
of parents this node has and
|
||||
<code>ssgEntity::getParent(n)</code> to locate the n'th parent.
|
||||
<p>
|
||||
Alternatively, after calling getParent, you can call getNextParent
|
||||
to get the N+1'th parent node - it returns NULL when no more parents
|
||||
are available.
|
||||
<p>
|
||||
As a convenience for general tree-walking routines, there is a
|
||||
<code>ssgEntity::getNumKids()</code> call - which will always
|
||||
return zero on leaf nodes. You cannot actually get kid nodes unless
|
||||
the node is some kind of ssgBranch.
|
||||
|
||||
<H3>Traversals</H3>
|
||||
Much of the work done on an SSG scene graph entails 'traversing'
|
||||
the tree structure. This is done most commonly to display the
|
||||
scene using OpenGL - but is also done when doing intersection
|
||||
testing and other operations.
|
||||
<p>
|
||||
It's quite useful to be able to limit the traversal so that
|
||||
certain nodes do not get tested. This can save time - or
|
||||
prevent undesirable side-effects.
|
||||
<p>
|
||||
Each entity has a 'traveral mask' - which is a simple integer
|
||||
with one bit per kind of traversal. At present, there are
|
||||
three kinds of traversal:
|
||||
<pre>
|
||||
|
||||
SSGTRAV_CULL -- Culling to the field of view.
|
||||
SSGTRAV_ISECT -- General intersection testing.
|
||||
SSGTRAV_HOT -- Height-over-terrain testing.
|
||||
|
||||
</pre>
|
||||
You can directly set or get the traversal mask with <code>ssgEntity::setTraversalMask(m)</code>
|
||||
<code>ssgEntity::getTraversalMask()</code>. You can set an individual traversal bit using
|
||||
<code>ssgEntity::setTraversalMaskBits(m)</code> or clear one using
|
||||
<code>ssgEntity::clrTraversalMaskBits(m)</code>.
|
||||
|
||||
<H3>Bounding Sphere</H3>
|
||||
Quite a few graphics algorithms can be accellerated using a
|
||||
bounding sphere. The standard ssgEntity uses bounding
|
||||
spheres to do field-of-view and intersection testing.
|
||||
<p>
|
||||
Clearly one does not want to recompute the bounding sphere
|
||||
every frame - just some objects do change their size over
|
||||
time. Hence, the bounding sphere is lazily evaluated.
|
||||
<p>
|
||||
Whenever you do something to change the size or shape of an entity,
|
||||
you should call <code>ssgEntity::dirtyBSphere()</code>. This will
|
||||
mark this entity's sphere as invalid ("dirty") and also, walk
|
||||
backwards up the scene graph tree making all the nodes above
|
||||
this one dirty too. The next time SSG needs to know the bounding
|
||||
sphere size, it'll recompute it.
|
||||
<p>
|
||||
If you'd prefer for the bounding sphere recalculation to be
|
||||
done immediately, then you can call <code>ssgEntity::recalcBSphere()</code>
|
||||
and it will be done immediately. Branch nodes like ssgTransforms will
|
||||
automatically dirty their bounding spheres when necessary. Leaf nodes
|
||||
generally do not.
|
||||
<p>
|
||||
When anyone needs to know the bounding sphere size for a node,
|
||||
they'll call <code>ssgEntity::getBSphere()</code> - which will
|
||||
recaclulate the Bsphere if it needs to.
|
||||
|
||||
<H3>Culling and Drawing</H3>
|
||||
The actual tree-traversal, culling and rendering is handled by
|
||||
a virtual function <code>ssgEntity::cull()</code> - calling
|
||||
this on the root node in the scene graph causes the entire
|
||||
scene to be rendered in an efficient manner.
|
||||
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"><a href="ssgBase.html"><= previous =</a></td>
|
||||
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
||||
<td width="33%" align="right"><a href="ssgLeaf.html">= next =></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
305
doc/ssg/ssgLeaf.html
Normal file
@@ -0,0 +1,305 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H2><code>class ssgLeaf</code> - Leaf nodes.</h2>
|
||||
Leaf nodes are those that actually make OpenGL calls
|
||||
or take other 'rendering' actions - they contain
|
||||
all of the geometric information in the scene.
|
||||
<pre>
|
||||
|
||||
class ssgLeaf : public ssgEntity
|
||||
{
|
||||
public:
|
||||
int getExternalPropertyIndex ()
|
||||
int isTranslucent ()
|
||||
int hasState ()
|
||||
ssgState *getState ()
|
||||
void setState ( ssgState *st )
|
||||
|
||||
virtual float *getVertex ( int i )
|
||||
virtual float *getNormal ( int i )
|
||||
virtual float *getColour ( int i )
|
||||
virtual float *getTexCoord ( int i )
|
||||
|
||||
virtual int getNumTriangles() ;
|
||||
virtual void getTriangle ( int n, short *v1, short *v2, short *v3 )
|
||||
|
||||
virtual int getNumLines () ;
|
||||
virtual void getLine ( int n, short *v1, short *v2 ) ;
|
||||
|
||||
int getNumLines () ;
|
||||
void getLine ( int n, short *v1, short *v2 ) ;
|
||||
|
||||
virtual void transform ( sgMat4 m )
|
||||
|
||||
void setCullFace ( int cf )
|
||||
int getCullFace ()
|
||||
|
||||
void makeDList () ;
|
||||
void deleteDList () ;
|
||||
GLuint getDListIndex () ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
|
||||
<H3>Pre- and Post-Draw Callbacks.</H3>
|
||||
It's frequently useful to have an application function called
|
||||
just before and/or just after a leaf node is rendered.
|
||||
<pre>
|
||||
|
||||
typedef int (*ssgCallback)( ssgEntity * ) ;
|
||||
ssgCallback getCallback ( int which ) ;
|
||||
void setCallback ( int which, ssgCallback cb ) ;
|
||||
|
||||
</pre>
|
||||
(Where 'which' is either SSG_CALLBACK_PREDRAW for a function that's
|
||||
to be called before the node is drawn or SSG_CALLBACK_POSTDRAW for
|
||||
one that's called after rendering.) In both cases, the function will
|
||||
be passed a pointer to the leaf node that's about to be drawn, and
|
||||
(in the case of PREDRAW callbacks), may return FALSE to prevent the
|
||||
node from being drawn, or TRUE to have it draw normally.
|
||||
<H3>Display Lists</H3>
|
||||
A leaf node is normally rendered in 'immediate' mode in OpenGL,
|
||||
so that changes you make to the leaf will be reflected on the
|
||||
screen on the next occasion that it's drawn. However, on some
|
||||
graphics hardware, it's more efficient to create an OpenGL
|
||||
display list for each leaf node. This can be managed by
|
||||
calling <code>ssgLeaf::makeDList()</code>. If you want to
|
||||
make changes to the Leaf, you'll have to call makeDList again
|
||||
since OpenGL does not support the editing of display lists.
|
||||
<p>
|
||||
You can call <code>ssgLeaf::deleteDList()</code> to stop
|
||||
this leaf from being display listed from now on and to
|
||||
free up the display list memory.
|
||||
<code>ssgLeaf::getDListIndex()</code> returns the OpenGL
|
||||
display list handle - or zero if no display list exists
|
||||
for this leaf.
|
||||
<p>
|
||||
If you change a leaf node's geometry when it has an
|
||||
active display list without calling either deleteDList
|
||||
or makeDList again, then any subsequent operation
|
||||
involving rendering this node could fail.
|
||||
|
||||
<H3>Face Culling.</H3>
|
||||
By default, ssgLeaf nodes are back-face culled, you can change
|
||||
that for any given node using <code>ssgLeaf::setCullFace(cf)</code>
|
||||
where <code>cf</code> is TRUE to enable backface culling,
|
||||
FALSE to disable it. You can test the state of face culling
|
||||
using <code>ssgLeaf::getCullFace()</code>.
|
||||
<H3>State Management.</H3>
|
||||
OpenGL supports a wide selection of state information - things like
|
||||
texture, materials and such. All of this information is held in a
|
||||
separate SSG class hierarchy: 'ssgState'. Each leaf has a state
|
||||
which it sets up before drawing the geometry that the leaf contains.
|
||||
<p>
|
||||
Nodes may also be stateless - but that isn't useful for any
|
||||
of the existing SSG leaf node types.
|
||||
<p>
|
||||
You can set the state for a node using <code>ssgLeaf::setState(state)</code>
|
||||
and query it using <code>ssgLeaf::getState()</code>. You can ask if
|
||||
a node has state information attached using <code>ssgLeaf::hasState()</code>.
|
||||
<p>
|
||||
Since OpenGL does not render translucent object well when Z-buffering
|
||||
is enabled, it's often useful to know if an object is translucent.
|
||||
<code>ssgLeaf::isTranslucent()</code> handles that test.
|
||||
<p>
|
||||
It is often useful to tag ssgState's with external properties - and
|
||||
you can retrieve the property of a leaf's state using
|
||||
<code>ssgLeaf::getExternalPropertyIndex()</code>.
|
||||
<H3>Querying Geometry</H3>
|
||||
The actual storage format for geometry in classes derived from
|
||||
ssgLeaf varies from class to class. However, it's very useful
|
||||
to be able to query the geometry in an implementation-independent
|
||||
manner.
|
||||
<p>
|
||||
Although classes derived from ssgLeaf are entitled to store their
|
||||
geometry in any form, all of them are required to respond to
|
||||
queries about basic triangle primitives.
|
||||
<p>
|
||||
Firstly, you can get a count of the number of triangles in this
|
||||
leaf using <code>ssgLeaf::getNumTriangles()</code>. Each triangle
|
||||
has an index number for each vertex which can be queried using
|
||||
<code>ssgLeaf::getTriangle(n,&v1,&v2,&v3)</code> which copies
|
||||
the 'short' indices for the n'th triangle's three vertices into
|
||||
v1, v2 and v3.
|
||||
<p>
|
||||
Once you know the indices of a triangle's vertices, you can ask for
|
||||
more information about that vertex using
|
||||
<code>ssgLeaf::getVertex(i)</code>,
|
||||
<code>ssgLeaf::getNormal(i)</code>,
|
||||
<code>ssgLeaf::getColour(i)</code>, and
|
||||
<code>ssgLeaf::getTexCoord(i)</code>. These calls allow you to
|
||||
retrieve the i'th vertex, normal, colour or texture coordinate as
|
||||
a short floating point array. (3 elements for Vertex and Normal,
|
||||
4 elements for Colour (RGBA) and two elements for a texture coordinate.
|
||||
<p>
|
||||
Analogous to getting the triangles,
|
||||
you may use <code>ssgLeaf::getNumLines ()</code>
|
||||
and <code>ssgLeaf::getLine ( int n, short *v1, short *v2 ) ;</code>
|
||||
to get the number of lines and to get the n. line.
|
||||
|
||||
<p>
|
||||
You can transform all the vertices of a leaf each frame by placing
|
||||
an ssgTransform node above the leaf in the scene graph - but for
|
||||
transformations that never change, it's more efficient to pre-transform
|
||||
the vertices in the leaf node.
|
||||
<code>ssgLeaf::transform(matrix)</code> permenantly transforms all
|
||||
the vertices and normals of this leaf by multiplying them by the
|
||||
matrix. (In the case of the normals, the translation part of the
|
||||
matrix is ignored).
|
||||
<p>
|
||||
It's inadvisable to repeatedly transform a leaf using <code>transform</code>
|
||||
since roundoff error will be accumulated with bad consequences (eventually).
|
||||
In those cases, use an ssgTransform node.
|
||||
|
||||
<H2><code>class ssgVtxTable</code> - A Vertex-table leaf node.</H2>
|
||||
This class allows one to represent leaf geometry as arrays of vertex,
|
||||
normal, texture coordinate and colour data. As a derived class of
|
||||
ssgLeaf, Vertex Tables add a constructor function to take the
|
||||
pre-computed vertex data:
|
||||
<pre>
|
||||
|
||||
ssgVtxTable ( GLenum ty, ssgVertexArray *vl,
|
||||
ssgNormalArray *nl,
|
||||
ssgTexCoordArray *tl,
|
||||
ssgColourArray *cl ) ;
|
||||
|
||||
</pre>
|
||||
'ty' is an OpenGL primitive type (such as one might pass to glBegin):
|
||||
<pre>
|
||||
|
||||
GL_POLYGON
|
||||
GL_TRIANGLE_FAN
|
||||
GL_TRIANGLES
|
||||
GL_TRIANGLE_STRIP
|
||||
GL_QUAD_STRIP
|
||||
GL_QUADS
|
||||
|
||||
</pre>
|
||||
the remaining arguments are lists of (x,y,z) vertices, (nx,ny,nz)
|
||||
normals, (s,t) texture coordinates and (r,g,b,a) colours.
|
||||
<H2><code>class ssgVertexArray/ssgNormalArray/ssgTexCoordArray/ssgColourArray</code> - Vertex data storage classes.</H2>
|
||||
These four classes are used for storing vertex data for ssgVtxTable nodes.
|
||||
Each class implements an extensible array that grows as you add data to
|
||||
it.
|
||||
<pre>
|
||||
|
||||
ssg*Array::ssg*Array ( int init = 3 ) ;
|
||||
|
||||
</pre>
|
||||
When you construct the array, you may specify an initial size for it,
|
||||
the default is three elements. If you don't know how big the array
|
||||
is, don't worry about it - but if you do know, there are time and
|
||||
storage space advantages to telling the class the exact number.
|
||||
<pre>
|
||||
|
||||
void ssgVertexArray ::add ( sgVec3 data ) ;
|
||||
void ssgNormalArray ::add ( sgVec3 data ) ;
|
||||
void ssgTexCoordArray::add ( sgVec2 data ) ;
|
||||
void ssgColourArray ::add ( sgVec4 data ) ;
|
||||
|
||||
</pre>
|
||||
These functions tack another data element onto the end of the array.
|
||||
<pre>
|
||||
|
||||
float *ssg*Array::get ( int i ) ;
|
||||
|
||||
</pre>
|
||||
Returns the address of the i'th element of the array.
|
||||
<pre>
|
||||
|
||||
int ssg*Array::getNum () ;
|
||||
|
||||
</pre>
|
||||
Returns the number of data elements currently stored in the array.
|
||||
<pre>
|
||||
|
||||
void ssg*Array::removeAll () ;
|
||||
|
||||
</pre>
|
||||
Empties the array.
|
||||
<H2><code>class ssgTween</code> - A Vertex-table morphing node.</H2>
|
||||
This node is derived from ssgVtxTable. Where VtxTable can retain
|
||||
a set of arrays, one each for Vertex coordinates, Normals, Texture
|
||||
Coordinates and Colours, the ssgTween node can store an unlimited
|
||||
number of 'banks' of these arrays.
|
||||
<p>
|
||||
Hence, one constructs an ssgTween by specifying it's OpenGL primitive
|
||||
type:
|
||||
<pre>
|
||||
|
||||
ssgTween::ssgTween ( GLenum ty ) ;
|
||||
|
||||
</pre>
|
||||
And then create some number of 'banks' of data arrays by calling:
|
||||
<pre>
|
||||
|
||||
int ssgTween::newBank ( ssgVertexArray *vl,
|
||||
ssgNormalArray *nl,
|
||||
ssgTexCoordArray *tl,
|
||||
ssgColourArray *cl ) ;
|
||||
|
||||
</pre>
|
||||
...once for each bank. All other ssgVtxTable calls operate ONLY
|
||||
on the 'current bank' - which is either the most recent one you
|
||||
created with newBank - or you can go back to an older bank by
|
||||
calling:
|
||||
<pre>
|
||||
|
||||
void ssgTween::setBank ( int bankID ) ;
|
||||
int ssgTween::getBank () ;
|
||||
|
||||
</pre>
|
||||
(newBank returns the number of the bank it created in case you
|
||||
lose count!).
|
||||
<p>
|
||||
ssgTween's idea of the 'current bank' is reset to zero after
|
||||
rendering it...so be sure to always call setBank immediately
|
||||
before working on it's component arrays.
|
||||
<p>
|
||||
When the ssgTween node is rendered, it works cooperatively
|
||||
with whichever ssgTweenController node is above it in the
|
||||
scene graph. See the section on ssgTweenController for more
|
||||
details.
|
||||
<p>
|
||||
IMPORTANT NOTE: There must be an identical number of vertices,
|
||||
normals, etc in each bank. If you get that wrong, SSG will
|
||||
exit with an 'abort'. Note that there is a specific optimisation
|
||||
in ssgTween that avoids the computational cost of interpolating
|
||||
between two sets of vertex data if EITHER:
|
||||
<ul>
|
||||
<li>The ssgTweenController's selected bank number happens to
|
||||
be an integer.
|
||||
<li>The previous and next banks have the same ssg*Array pointer.
|
||||
Since one generally doesn't wish to interpolate normals, colours
|
||||
or texture coordinates, it's important to pay attention to this.
|
||||
</ul>
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"><a href="ssgEntity.html"><= previous =</a></td>
|
||||
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
||||
<td width="33%" align="right"><a href="branches.html">= next =></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
255
doc/ssg/state.html
Normal file
@@ -0,0 +1,255 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H2><code>class ssgState</code> - OpenGL state representation.</H2>
|
||||
Each leaf node will have some kind of ssgState node associated
|
||||
with it that contains all relevent OpenGL state information.
|
||||
<p>
|
||||
There can (in principal) be a number of different ways to represent
|
||||
OpenGL state - but all must be derived from an ssgState:
|
||||
<pre>
|
||||
|
||||
class ssgState : public ssgBase
|
||||
{
|
||||
int getExternalPropertyIndex () ;
|
||||
void setExternalPropertyIndex ( int i ) ;
|
||||
|
||||
ssgStateCallback getStateCallback ( int cb_type ) ;
|
||||
void setStateCallback ( int cb_type, ssgStateCallback cb ) ;
|
||||
|
||||
virtual void force () ;
|
||||
virtual void apply () ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
<H3>Callbacks.</H3>
|
||||
States are 'applied' immediately before the geometry they are attached
|
||||
to is rendered. Applying the state causes all of it's properties to
|
||||
be set up in OpenGL.
|
||||
<p>
|
||||
Each state has three optional callback function hooks. The application
|
||||
program can have a function called before the state is applied, after
|
||||
it is applied (but before the geometry is drawn) and another after the
|
||||
geometry is rendered - immediately before the next state is applied.
|
||||
<p>
|
||||
You can set those three callbacks with setStateCallback - passing
|
||||
either SSG_CALLBACK_PREAPPLY, SSG_CALLBACK_PREDRAW or SSG_CALLBACK_POSTDRAW
|
||||
as the first parameter and the address of your function as the second.
|
||||
<H3>External Properties.</H3>
|
||||
Each state entity can have an external property - which is a simple
|
||||
integer that can be set using <code>ssgState::setExternalPropertyIndex(i)</code>
|
||||
or queried using <code>ssgState::getExternalPropertyIndex()</code>.
|
||||
External properties are of use to certain sorts of applications programs,
|
||||
for example, a game might want to encode the set of OpenGL state information
|
||||
that represents Lava as something that is hot and Ice as something that
|
||||
is cold by encoding the temperature of the material in the External
|
||||
property field. Most applications will probably use this field as an
|
||||
index into a table of material properties inside the application itself.
|
||||
<H3>Applying a State.</H3>
|
||||
Whilst it's rare for an application to need to deal with an ssgState
|
||||
once it has been defined, there may be occasions when the application
|
||||
wishes to draw objects of it's own without using SSG's scene graph.
|
||||
This often is the case with on-screeen symbology.
|
||||
<p>
|
||||
In such cases, it is important to bear in mind that SSG changes the
|
||||
OpenGL state as little as possible - in order to save time. Hence,
|
||||
when a leaf node has just been drawn with one set of state information,
|
||||
and another leaf node is about to be drawn using another, SSG carefully
|
||||
compares the two states to see how they differ and arranges to make
|
||||
only the fewest possible OpenGL state change calls. If the application
|
||||
goes in "behind SSG's back" and changes state then SSG will be confused.
|
||||
<p>
|
||||
There are two ways to achive this. One is to use SSG state classes to
|
||||
change the state by calling <code>ssgState::apply()</code>. That call
|
||||
will ensure that OpenGL's state matches the desired state using the
|
||||
minimum of calls. However, if your application absolutely MUST make
|
||||
it's own state calls then you should call <code>ssgState::force()</code>
|
||||
to force all aspects of a specified state to be set in OpenGL so that
|
||||
SSG can be certain about how things are set up.
|
||||
<H2><code>class ssgSimpleState</code> - Simple State class.</H2>
|
||||
ssgSimpleState is currently the only concrete class derived from
|
||||
ssgState. It has so far proved adequate for all state management.
|
||||
<pre>
|
||||
class ssgSimpleState : ssgState
|
||||
{
|
||||
void disable ( GLenum mode ) ;
|
||||
void enable ( GLenum mode ) ;
|
||||
void set ( GLenum mode, int val ) { val ? enable(mode) : disable(mode) ; }
|
||||
|
||||
void setTexture ( char *fname, int wrapu = TRUE, int wrapv = TRUE )
|
||||
void setTexture ( ssgTexture *tex )
|
||||
void setTexture ( GLuint tex )
|
||||
void setColourMaterial ( GLenum which )
|
||||
void setMaterial ( GLenum which, float r, float g, float b, float a = 1.0f )
|
||||
void setMaterial ( GLenum which, sgVec4 rgba )
|
||||
void setShininess ( float sh )
|
||||
void setShadeModel ( GLenum model )
|
||||
void setAlphaClamp ( float clamp )
|
||||
} ;
|
||||
</pre>
|
||||
These calls mostly correspond to similarly named OpenGL functions.
|
||||
<H3>Enable and Disable calls:</H3>
|
||||
<code>ssgSimpleState:: disable ( mode )</code>,
|
||||
<code>ssgSimpleState:: enable ( mode )</code> and
|
||||
<code>ssgSimpleState:: set ( mode, val )</code> provide
|
||||
the same services as glEnable and glDisable ('set' is a convenience function
|
||||
that is a 'disable' if 'val' is FALSE, 'enable' otherwise). The 'mode'
|
||||
parameter uses tokens that are similarly named to those in OpenGL:
|
||||
<pre>
|
||||
|
||||
SSG_GL_TEXTURE_EN
|
||||
SSG_GL_CULL_FACE_EN
|
||||
SSG_GL_COLOR_MATERIAL_EN
|
||||
SSG_GL_BLEND_EN
|
||||
SSG_GL_ALPHA_TEST_EN
|
||||
SSG_GL_LIGHTING_EN
|
||||
|
||||
</pre>
|
||||
<H3>Texture states.</H3>
|
||||
There are three ways to attach a texture to an ssgSimpleState:
|
||||
<code>ssgSimpleState::setTexture ( fname, wrapu, wrapv )</code>,
|
||||
<code>ssgSimpleState::setTexture ( ssgtexture )</code>, and
|
||||
<code>ssgSimpleState::setTexture ( texture_handle )</code>.
|
||||
In the form that takes a filename, U-axis wrap and V-axis wrap flags, the
|
||||
texture is loaded from a texture file on disk (see ssgTexture
|
||||
below for details on how this is done). The map will be MIPmapped and set with
|
||||
a texture environment that is GL_LINEAR_MIPMAP_LINEAR and GL_MODULATE.
|
||||
<p>
|
||||
If you need something fancier, then declare an 'ssgTexture' class and
|
||||
pass that to the setTexture function. You can also load your own
|
||||
texture and pass the OpenGL glBindTexture handle to setTexture.
|
||||
<p> If you need the texture file name, first check that
|
||||
isEnabled ( GL_TEXTURE_2D ) returns true, then you may call
|
||||
getTextureFilename(). But you should still check the return value for NULL and for "".
|
||||
|
||||
<H3>Materials.</H3>
|
||||
These calls are all very similar to OpenGL calls - and take the same
|
||||
parameters:
|
||||
<code>ssgSimpleState::setColourMaterial(which)</code>
|
||||
<code>ssgSimpleState::setMaterial(which,r,g,b,a)</code>
|
||||
<code>ssgSimpleState::setMaterial(which,rgba)</code>
|
||||
<code>ssgSimpleState::setShininess(sh)</code>
|
||||
<code>ssgSimpleState::setShadeModel(model)</code>
|
||||
<code>ssgSimpleState::setAlphaClamp(clamp)</code>
|
||||
<H2><code>class ssgTexture</code> - Storing texture maps.</H2>
|
||||
An ssgTexture loads a texture map for you with the minimum possible
|
||||
fuss - but offers less flexibility than if you did so yourself.
|
||||
<p>
|
||||
The ssgTexture constructor function
|
||||
<code>ssgTexture::ssgTexture( char *fname,
|
||||
int wrapu = TRUE, int wrapv = TRUE )</code> does all the work,
|
||||
presuming that you require GL_LINEAR_MIPMAP_LINEAR filtering and a
|
||||
GL_MODULATE texture environment.
|
||||
<p>
|
||||
You can obtain the OpenGL glBindTexture handle for the texture
|
||||
using <code>ssgTexture::getHandle()</code>.
|
||||
<p>
|
||||
When ssgTexture loads a map from disk, it uses the filename
|
||||
extension to determine which image format the file is in.
|
||||
<p>
|
||||
Currently, only SGI format and <strong>uncompressed</strong>
|
||||
8 or 24 bit BMP images are supported - but more
|
||||
formats are planned for the future. Filenames ending with
|
||||
'.rgb', '.rgba', '.int', '.inta', '.bw' are assumed to be
|
||||
SGI formatted files, '.bmp' are in Microsoft's BMP format
|
||||
and '.png' are in Portable Network Graphics format.
|
||||
<p>
|
||||
If for any reason ssgTexture cannot load the requested file,
|
||||
it creates a 2x2 texel red and white chequerboard map to
|
||||
enable the program to continue running. This is often very
|
||||
useful for debugging and to enable program development to
|
||||
continue when texture maps are not yet painted.
|
||||
<H2><code>class ssgStateSelector</code> - Switchable State class.</H2>
|
||||
There are cases where you would like to be able to switch between a
|
||||
number of different states for a given leaf node.
|
||||
<pre>
|
||||
class ssgStateSelector : ssgSimpleState
|
||||
{
|
||||
ssgStateSelector ( int nstates ) ;
|
||||
|
||||
void selectStep ( unsigned int s ) ;
|
||||
int getSelectStep (void) ;
|
||||
ssgSimpleState *getCurrentStep (void) ;
|
||||
void setStep ( int i, ssgSimpleState *step ) ;
|
||||
ssgSimpleState *getStep ( int i ) ;
|
||||
} ;
|
||||
</pre>
|
||||
This class is used to switch between some number of <code>ssgSimpleStates</code>.
|
||||
You could (for example) draw the ground for your game as either
|
||||
grass or snow - depending on the season. Construct objects of this
|
||||
class with the number of alternative representations you will require
|
||||
as it's parameter, then create a number of <code>ssgSimpleState</code>s - passing
|
||||
them to <code>ssgStateSelector::setStep()</code>. You can then select which
|
||||
step you wish to render using <code>ssgStateSelector::selectStep()</code>.
|
||||
<p>
|
||||
<code>ssgStateSelector::getSelectStep()</code> returns the number of the currently
|
||||
selected step. <code>ssgStateSelector::getCurrentStep()</code> returns a pointer to
|
||||
the currently selected <code>ssgSimpleState</code>. <code>ssgStateSelector::getStep()</code>
|
||||
returns a pointer to the i'th <code>ssgSimpleState</code>.
|
||||
<p>
|
||||
Since <code>ssgStateSelector</code> is derived from <code>ssgSimpleState</code>,
|
||||
all the other <code>ssgSimpleState</code> calls work - and the effect is to
|
||||
operate on the currently selected <code>ssgSimpleState</code>.
|
||||
<p>
|
||||
Example:
|
||||
<pre>
|
||||
|
||||
ssgStateSelector *s = new ssgStateSelector ( 2 ) ;
|
||||
ssgSimpleState *grass = new ssgSimpleState () ;
|
||||
ssgSimpleState *snow = new ssgSimpleState () ;
|
||||
|
||||
...set up grass and snow states appropriately...
|
||||
|
||||
s -> setStep ( 0, grass ) ;
|
||||
s -> setStep ( 1, snow ) ;
|
||||
|
||||
leafnode1 -> setState ( s ) ;
|
||||
leafnode2 -> setState ( s ) ;
|
||||
leafnode3 -> setState ( s ) ;
|
||||
|
||||
...choose grass or snow...
|
||||
|
||||
if ( ! winter )
|
||||
s -> selectStep ( 0 ) ;
|
||||
else
|
||||
s -> selectStep ( 1 ) ;
|
||||
|
||||
...render the scene...
|
||||
|
||||
</pre>
|
||||
Notice that one selectStep call changes the material on all
|
||||
leaf nodes that use that ssgStateSelector.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="33%" align="left"><a href="branches.html"><= previous =</a></td>
|
||||
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
||||
<td width="33%" align="right"><a href="ssgContext.html">= next =></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
BIN
doc/ssgAux.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
886
doc/ssgAux/index.html
Normal file
@@ -0,0 +1,886 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>SSG Auxiliary Libraries.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<H1>SSG Auxiliary Libraries.</H1>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>
|
||||
by Steve Baker
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H2>Introduction</H2>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
PLIB/ssgAux is a suite of auxiliary libraries that build
|
||||
higher level classes on top of the basic SSG classes.
|
||||
<p>
|
||||
<ul>
|
||||
<li><A HREF="#ssgaShape">ssgaShape - Abstract Base Class</A>
|
||||
<li><A HREF="#ssgaCube">ssgaCube - Makes a cube.</A>
|
||||
<li><A HREF="#ssgaPatch">ssgaPatch - Makes a Bezier patch.</A>
|
||||
<li><A HREF="#ssgaTeapot">ssgaTeapot - Makes a Teapot.</A>
|
||||
<li><A HREF="#ssgaSphere">ssgaSphere - Makes a Sphere.</A>
|
||||
<li><A HREF="#ssgaCylinder">ssgaCylinder - Makes a Cylinder.</A>
|
||||
<li><A HREF="#ssgaWaveSystem">ssgaWaveSystem - Simulates Water Waves</A>
|
||||
<li><A HREF="#ssgaParticleSystem">ssgaParticleSystem - Implements a spray of particles</A>
|
||||
<li><A HREF="#ssgaFire">ssgaFire - Simulates Fire</A>
|
||||
<li><A HREF="#ssgaLensFlare">ssgaLensFlare - Simulates Lens Flare for drawing bright lights.</A>
|
||||
<li><A HREF="#ssgaSky">ssgaSky - Model a sky with sun, moon, clouds, stars & planets.</A>
|
||||
</ul>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<IMG SRC="snapshot.png" ALT="ssgAux screenshot" WIDTH=417 HEIGHT=309>
|
||||
<br>
|
||||
This image was created entirely from ssgAux primitives.
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<p>
|
||||
<H2>Conventions</H2>
|
||||
ssgAux is installed and named with the same
|
||||
conventions as the base PLIB libraries.
|
||||
<br>
|
||||
ie:
|
||||
<pre>
|
||||
/usr/include/plib/ssgAux.h
|
||||
/usr/lib/libplibssgaux.a
|
||||
</pre>
|
||||
<p>
|
||||
PLIB/ssgAux functions, classes and constants are all
|
||||
named with an 'ssga' or 'SSGA' prefix.
|
||||
<br>
|
||||
eg:
|
||||
<pre>
|
||||
class ssgaShape ;
|
||||
SSGA_TYPE_CUBE
|
||||
</pre>
|
||||
<A NAME="ssgaShape"></A>
|
||||
<H1>ssgaShape</H1>
|
||||
This is an abstract base class for many of the more
|
||||
complex classes in the ssgAux 'collection'. The idea
|
||||
is that ssgaShape's are really ssgBranch nodes that create
|
||||
their own child nodes - but they behave in such a way that
|
||||
you are never concerned with the nodes they create beneath
|
||||
themselves.
|
||||
<pre>
|
||||
|
||||
class ssgaShape : public ssgBranch
|
||||
{
|
||||
ssgaShape (void) ;
|
||||
ssgaShape ( int numtris ) ;
|
||||
|
||||
float *getCenter () { return center ; }
|
||||
float *getSize () { return size ; }
|
||||
int getNumTris () { return ntriangles ; }
|
||||
|
||||
void setColour ( sgVec4 c ) { sgCopyVec4 ( colour, c ) ; regenerate () ; }
|
||||
void setCenter ( sgVec3 c ) { sgCopyVec3 ( center, c ) ; regenerate () ; }
|
||||
void setSize ( sgVec3 s ) { sgCopyVec3 ( size , s ) ; regenerate () ; }
|
||||
void setSize ( float s ) { sgSetVec3 ( size,s,s,s) ; regenerate () ; }
|
||||
void setNumTris ( int ntri ) { ntriangles = ntri ; regenerate () ; }
|
||||
|
||||
void setKidState ( ssgState *s ) ;
|
||||
void setKidCallback ( int cb_type, ssgCallback cb ) ;
|
||||
|
||||
virtual void regenerate () = 0 ;
|
||||
}
|
||||
</pre>
|
||||
The constructor allows you to specify the approximate number of
|
||||
triangles you'd like the shape to consume. For some shapes, this
|
||||
will be ignored (eg the Cube has 12 triangles - no matter how many
|
||||
you ask for) - for others, it's honored only approximately (eg the
|
||||
Sphere can only generate certain specific numbers of triangles) -
|
||||
and for others, it may be honored exactly.
|
||||
<p>
|
||||
You can also set the colour of all the polygons and the ssgState and
|
||||
callbacks that are applied to all of the child nodes.
|
||||
<p>
|
||||
setCenter allows you to position the center point of the object in
|
||||
3D space - and setSize lets you determine the overall dimensions of
|
||||
the object (this too may also be approximate - the 'size' of a teapot
|
||||
is hard to specify in any useful way). The version of 'setSize' that
|
||||
takes an sgVec3 allow you to generate cuboids from cubes and sphereoids
|
||||
from spheres...but not all shapes allow this.
|
||||
<p>
|
||||
The 'regenerate' call allows the complete child structure of the object
|
||||
to be deleted and then recreated. This is occasionaly useful if (for
|
||||
example) you have walked down into the child structures and modified
|
||||
them - and you'd like the shape back into it's pristine conditions.
|
||||
<A NAME="ssgaCube"></A>
|
||||
<H1>ssgaCube</H1>
|
||||
<pre>
|
||||
|
||||
class ssgaCube : public ssgaShape
|
||||
{
|
||||
ssgaCube (void) ;
|
||||
ssgaCube ( int numtris ) ;
|
||||
virtual void regenerate () ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
This is the simplest of ssgaShapes - it defines nothing new over
|
||||
and above the standard ssgaShape.
|
||||
<A NAME="ssgaPatch"></A>
|
||||
<H1>ssgaPatch</H1>
|
||||
<pre>
|
||||
|
||||
class ssgaPatch : public ssgaShape
|
||||
{
|
||||
ssgaPatch (void) ;
|
||||
ssgaPatch ( int numtris ) ;
|
||||
|
||||
void setControlPoint ( int s, int t, sgVec3 xyz, sgVec2 uv, sgVec4 rgba ) ;
|
||||
void setControlPoint ( int s, int t,
|
||||
float x, float y, float z,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a ) ;
|
||||
void getControlPoint ( int s, int t, sgVec3 xyz, sgVec2 uv, sgVec4 rgba ) ;
|
||||
|
||||
virtual void regenerate () ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
This implements a basic spline patch - with a 4x4 grid of 'control points'
|
||||
that define its shape. 'setContolPoint' allows you to set the spatial
|
||||
position, the texture coordinate and the colour at any given (s,t) position.
|
||||
(s and t each must be in the range 0..3).
|
||||
<p>
|
||||
It's necessary to call the 'regenerate' function whenever you have added
|
||||
or changed one or more control points.
|
||||
|
||||
<A NAME="ssgaTeapot"></A>
|
||||
<H1>ssgaTeapot </H1>
|
||||
<pre>
|
||||
|
||||
class ssgaTeapot : public ssgaShape
|
||||
{
|
||||
ssgaTeapot (void) ;
|
||||
ssgaTeapot ( int numtris ) ;
|
||||
virtual void regenerate () ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
This creates the 'classic' Martin Newell teapot model.
|
||||
<A NAME="ssgaSphere"></A>
|
||||
<H1>ssgaSphere</H1>
|
||||
<pre>
|
||||
|
||||
class ssgaSphere : public ssgaShape
|
||||
{
|
||||
ssgaSphere (void) ;
|
||||
ssgaSphere ( int numtris ) ;
|
||||
|
||||
void setLatLongStyle ( int ll ) ;
|
||||
int isLatLongStyle () ;
|
||||
virtual void regenerate () ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
There are two ways to generate a sphere model - one is to produce a
|
||||
fairly uniform grid of triangles that are as nearly equilateral
|
||||
as possible. The alternative is to generate more nearly right-triangles
|
||||
in cylindrical strips that are stacked on top of each other with a
|
||||
circular disk at top and bottom.
|
||||
<p>
|
||||
The function 'setLatLongStyle(ll)' allows you to choose which you want,
|
||||
call regenerate after you change types!
|
||||
<A NAME="ssgaCylinder"></A>
|
||||
<H1>ssgaCylinder</H1>
|
||||
<pre>
|
||||
|
||||
class ssgaCylinder : public ssgaShape
|
||||
{
|
||||
ssgaCylinder (void) ;
|
||||
ssgaCylinder ( int numtris ) ;
|
||||
|
||||
void makeCapped ( int c ) ;
|
||||
int isCapped () ;
|
||||
virtual void regenerate () ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
Cylinders also come in two forms - capped and uncapped. Once again,
|
||||
if you change the capped versus uncapped status, call regenerate to
|
||||
make the new version.
|
||||
<A NAME="ssgaWaveSystem"></A>
|
||||
<H1>ssgaWaveSystem</H1>
|
||||
This class is for handling water waves.
|
||||
It generates a large polygonal mesh which it distorts in
|
||||
realtime to simulate water waves.
|
||||
<p>
|
||||
The simulation uses between one and sixteen "Wave Trains" - each
|
||||
using a class:
|
||||
<pre>
|
||||
|
||||
class ssgaWaveTrain
|
||||
{
|
||||
ssgaWaveTrain () ;
|
||||
|
||||
float getSpeed () ;
|
||||
float getLength () ;
|
||||
float getLambda () ;
|
||||
float getHeading () ;
|
||||
float getWaveHeight () ;
|
||||
|
||||
void setSpeed ( float s ) ;
|
||||
void setLength ( float l ) ;
|
||||
void setLambda ( float l ) ;
|
||||
void setHeading ( float h ) ;
|
||||
void setWaveHeight ( float h ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
So, you create a bunch of these trains (typically, two or three
|
||||
is plenty to generate 'interesting' motion).
|
||||
Each wave train has a direction in which the waves are travelling,
|
||||
a speed, a wave length (which also affects the shape of the wave),
|
||||
the height of the wave and a 'lambda' term (which controls how much
|
||||
the tops of the waves bend over).
|
||||
<p>
|
||||
Next, generate the ssgaWaveSystem:
|
||||
<pre>
|
||||
|
||||
class ssgaWaveSystem : public ssgaShape
|
||||
{
|
||||
ssgaWaveSystem ( int ntri ) ;
|
||||
|
||||
virtual void regenerate () ;
|
||||
|
||||
ssgaWSDepthCallback getDepthCallback () ;
|
||||
void setDepthCallback ( ssgaWSDepthCallback cb ) ;
|
||||
|
||||
ssgaWaveTrain *getWaveTrain ( int i ) ;
|
||||
void setWaveTrain ( int i, ssgaWaveTrain *t ) ;
|
||||
|
||||
float getWindSpeed () ;
|
||||
float getWindDirn () ;
|
||||
float getEdgeFlatten () ;
|
||||
float getTexScaleU () ;
|
||||
float getTexScaleV () ;
|
||||
|
||||
void setWindSpeed ( float speed ) ;
|
||||
void setWindDirn ( float dirn ) ;
|
||||
void setEdgeFlatten ( float dist ) ;
|
||||
void setTexScale ( float u, float v ) ;
|
||||
|
||||
void updateAnimation ( float t ) ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
The appearance of waves varies greatly with the depth of the
|
||||
water - and this simulation produces the correct effects. There
|
||||
is an optional user-callback that can be used to feed water depth
|
||||
values into the simulation. The wave system will likely call this
|
||||
function many thousands of times per frame - so make sure your
|
||||
depth function is very efficient. If you don't provide a depth
|
||||
function then the water will be assumed to be infinitely deep.
|
||||
<p>
|
||||
You can determine the number of polygons used to render
|
||||
the patch of waves, the size of the wave patch and the amount
|
||||
of texture repetition. The 'EdgeFlatten' setting determines
|
||||
to what distance from the edge of the patch the waves are
|
||||
gradually flattened out. This is useful because it allows
|
||||
you to keep all those expensive wave polygons close to the
|
||||
camera - and feather them out over range so that they blend
|
||||
gently into a larger flat ocean.
|
||||
<p>
|
||||
Designing waves by calling the ssgaWaveSystem API is quite
|
||||
difficult. You are advised to use the wave designer program
|
||||
in the PLIB examples package. This program lets you adjust
|
||||
wave parameters until it looks how you'd like - then hit the
|
||||
'Write C++ code' to write out a source code snippet that you
|
||||
can cut and paste into your program.
|
||||
<p>
|
||||
There is a 'README' in the 'water' source directory that
|
||||
explains how to use the program in a little more detail.
|
||||
That's all the wave system documentation I have time to write
|
||||
just now - sorry.
|
||||
<A NAME="ssgaParticleSystem"></A>
|
||||
<H1>ssgaParticleSystem</H1>
|
||||
This is a very flexible implementation of particle systems - it's not
|
||||
as efficient as you might want for thousands of particles - this is intended
|
||||
for high flexibility and relatively fewer numbers of particles.
|
||||
|
||||
<p>
|
||||
All of that flexibility is evident in the complex constructor function:
|
||||
<pre>
|
||||
|
||||
class ssgaParticleSystem : public ssgVtxArray
|
||||
{
|
||||
ssgaParticleSystem ( int max , /* Max Number of particles */
|
||||
int init, /* Number to launch initially */
|
||||
float add , /* Max number to create per sec */
|
||||
int turn_to_face, /* Turn to face camera? */
|
||||
float size, /* Size of particles */
|
||||
float bsphere_rad, /* Size of bounding sphere */
|
||||
ssgaParticleCreateFunc create, /* Initial create fn. */
|
||||
ssgaParticleUpdateFunc update = NULL, /* Update function */
|
||||
ssgaParticleDeleteFunc del = NULL /* Remove function */
|
||||
) ;
|
||||
|
||||
void setSize ( float sz ) ;
|
||||
float getSize () ;
|
||||
|
||||
update ( float dt ) ;
|
||||
|
||||
int getNumActiveParticles () ;
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
There are three callback functions - with the following types:
|
||||
<pre>
|
||||
|
||||
typedef void (* ssgaParticleCreateFunc) ( ssgaParticleSystem *ps,
|
||||
int index,
|
||||
ssgaParticle *p ) ;
|
||||
|
||||
typedef void (* ssgaParticleUpdateFunc) ( float deltaTime,
|
||||
ssgaParticleSystem *ps,
|
||||
int index,
|
||||
ssgaParticle *p ) ;
|
||||
|
||||
typedef void (* ssgaParticleDeleteFunc) ( ssgaParticleSystem *ps,
|
||||
int index,
|
||||
ssgaParticle *p ) ;
|
||||
|
||||
</pre>
|
||||
There is also a public class for a single particle:
|
||||
<pre>
|
||||
|
||||
class ssgaParticle
|
||||
{
|
||||
public:
|
||||
|
||||
sgVec4 col ;
|
||||
sgVec3 pos ;
|
||||
sgVec3 vel ;
|
||||
sgVec3 acc ;
|
||||
|
||||
float size ;
|
||||
float time_to_live ;
|
||||
void *userData ;
|
||||
|
||||
ssgaParticle () ;
|
||||
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
This is best explained with an example.
|
||||
Here is an example of a fountain model:
|
||||
<pre>
|
||||
|
||||
fountain = new ssgaParticleSystem ( 2000, /* Max Number of particles */
|
||||
2, /* Number to launch initially */
|
||||
200, /* Max number to create per sec */
|
||||
TRUE, /* Turn to face? */
|
||||
0.2, /* Size of particles */
|
||||
20.0, /* Size of bounding sphere */
|
||||
fountain_create, /* Initial create fn. */
|
||||
fountain_update /* Update function */ ) ;
|
||||
|
||||
</pre>
|
||||
This creates a system that has the capability to draw 2000 particles
|
||||
(each is a quadrilateral). Two particles are launched initially and 200
|
||||
more are added gradually every second. You can choose to have each particle
|
||||
turn to face the camera - or to be oriented in the X/Z plane, mine are set to
|
||||
turn-to-face. The particles are 0.2 OpenGL units across.
|
||||
<p>
|
||||
This fountain is a continuous effect - so the inital number of particles
|
||||
to launch is small - and the 'per second' creation rate determines the
|
||||
flow. If you wanted something more like an explosion, have a larger number
|
||||
of initial particles and none launched per-second after that.
|
||||
<p>
|
||||
One messiness is that we don't know how big the fountain may become over
|
||||
time - and it's VERY inefficient to recompute the bsphere every frame. Hence
|
||||
you have to tell the class what the maximum bounding sphere of the fountain
|
||||
is at the outset so we can field-of-view cull it - this <b>could</b> be a near
|
||||
infinite radius (MAX_FLOAT say) if you truly don't know how big it could
|
||||
get - but that's inefficient because all 2,000 particles must be sent to
|
||||
OpenGL even if the fountain is 20 miles away behind the camera - so do your
|
||||
best to come up with some kind of a reasonable guess.
|
||||
<p>
|
||||
fountain_create and fountain_update are user-defined callback functions,
|
||||
we could also have defined a 'fountain_delete' function - but many applications
|
||||
won't need this.
|
||||
<ul>
|
||||
<li>The 'create' callback is called every time the system needs to
|
||||
create a new particle.
|
||||
<li>The 'update' callback is called on every update cycle for every
|
||||
particle that's in flight.
|
||||
<li>The 'delete' callback is called when the system has decided
|
||||
that a particle has 'died'.
|
||||
</ul>
|
||||
You have to have a 'create' function - but the other two are optional.
|
||||
<p>
|
||||
These callbacks are passed the address of the particle system, the index
|
||||
number and address of the particle that's being created/updated/deleted -
|
||||
and (for the 'update' function only) - the amount of elapsed time since
|
||||
this particle was last updated.
|
||||
<p>
|
||||
The callbacks can set, read or change any or all aspects of the particle...
|
||||
it's colour, position, velocity, accelleration, size and 'time to live'
|
||||
(in seconds).
|
||||
There is also a user data pointer - so you can hang your own data onto
|
||||
each individual particle.
|
||||
<p>
|
||||
The particle system automatically moves each particle according to the usual
|
||||
laws of motion and decrements it's time-to-live - so in many cases,
|
||||
you can just set the initial velocity, the force due to
|
||||
gravity and a reasonable time to live - and let the particle system code
|
||||
do the rest.
|
||||
<p>
|
||||
My 'fountain_create' function looks like this:
|
||||
<pre>
|
||||
|
||||
void fountain_create ( ssgaParticleSystem *, int, ssgaParticle *p )
|
||||
{
|
||||
sgSetVec4 ( p -> col, 1, 1, 1, 1 ) ; /* initially white */
|
||||
sgSetVec3 ( p -> pos, 0, 0, 0 ) ; /* start off on the ground */
|
||||
sgSetVec3 ( p -> vel, (rand()%1000-500)/300.0f,
|
||||
(rand()%1000-500)/300.0f, 50.0f ) ;
|
||||
/* Shoot up and out */
|
||||
sgSetVec3 ( p -> acc, 0, 0, -9.8f ) ; /* Gravity */
|
||||
p -> time_to_live = 5 ; /* Droplets evaporate after 5 seconds */
|
||||
}
|
||||
|
||||
</pre>
|
||||
It populates the particle with an initial colour, position, velocity and
|
||||
accelleration and gives it a 'time to live' of five seconds. The velocity
|
||||
is randomised a bit to make a nicer looking fountain.
|
||||
<p>
|
||||
You can do all sorts of fancy things to the colour, position, velocity and
|
||||
accelleration in your 'update' function.
|
||||
<pre>
|
||||
|
||||
void fountain_update ( ssgaParticle *p )
|
||||
{
|
||||
if ( p -> pos [ 2 ] < 0 )
|
||||
p -> time_to_live = -1 ;
|
||||
|
||||
p -> col [ 2 ] = (p -> time_to_live > 2) ? 1 : (p -> time_to_live/2.0f) ;
|
||||
}
|
||||
|
||||
</pre>
|
||||
...this one just erases particles that go below zero altitude (by
|
||||
setting their time-to-live variable to -1) and makes them go a pretty
|
||||
shade of yellow for the last two seconds before they die.
|
||||
<p>
|
||||
The 'delete' function is principally useful for freeing up any user-data
|
||||
you allocated in the 'create' function or during 'update's. Don't
|
||||
delete the particle though - the particle system recycles it to avoid
|
||||
doing too much dynamic memory allocation.
|
||||
<p>
|
||||
All that remains is to call the ssgaParticleSystem::update function
|
||||
every frame with a parameter that tells the system how much time has
|
||||
elapsed since the last call. This allows you to easily speed up, slow
|
||||
down or pause the particles (or even run them backwards if you want).
|
||||
<p>
|
||||
I call this every frame:
|
||||
<pre>
|
||||
|
||||
void updateFountain ()
|
||||
{
|
||||
static ulClock ck ;
|
||||
|
||||
ck . update () ;
|
||||
|
||||
if ( fountain != NULL )
|
||||
fountain -> update ( ck.getDeltaTime () ) ;
|
||||
}
|
||||
|
||||
</pre>
|
||||
This function could also check the number of particles currently in flight
|
||||
and delete the fountain when there are none left - that might be useful
|
||||
for an explosion or something where you'd want to save CPU time by not
|
||||
running the explosion particle system when all the pieces have landed
|
||||
and 'gone away'.
|
||||
<p>
|
||||
The size of each particle is the size field of the individual particle
|
||||
MULTIPLIED by the number you pass into the size parameter of the
|
||||
ssgaParticleSystem constructor (or set with setSize()). This allows you
|
||||
to cheaply set the particle size for all the particles at once - or to
|
||||
tweak the size of each one in turn. The number in the particle structure
|
||||
defaults to 1.0 so you can ignore it and just set the size in the
|
||||
particle system overall.
|
||||
<p>
|
||||
ssgaParticleSystem is derived from ssgVtxArray - so you can apply textures and
|
||||
other state things using the usual ssgVtxArray::setState(ssgSimpleState*)
|
||||
call. I applied a texture with a fuzzy alpha-blended circle.
|
||||
<p>
|
||||
While debugging this, I got a bug which caused a picture of Tux to be
|
||||
applied instead of the droplet texture - it was absolutely hilarious
|
||||
to see 2000 tiny penguins shooting up in a fountain and falling gently
|
||||
to earth!
|
||||
<A NAME="ssgaFire"></A>
|
||||
<H1>ssgaFire</H1>
|
||||
This class is actually a highly specialised particle system.
|
||||
You have to construct it quite carefully in order to get a nice
|
||||
looking fire:
|
||||
<pre>
|
||||
|
||||
class ssgaFire : public ssgaParticleSystem
|
||||
{
|
||||
ssgaFire ( int num_tris,
|
||||
float radius = 1.0f,
|
||||
float height = 5.0f,
|
||||
float speed = 2.0f ) ;
|
||||
|
||||
virtual ~ssgaFire () ;
|
||||
|
||||
virtual void update ( float t ) ;
|
||||
|
||||
void setUpwardSpeed ( float spd )
|
||||
void setHeight ( float hgt )
|
||||
void setRadius ( float rad )
|
||||
void setHotColour ( sgVec4 col )
|
||||
} ;
|
||||
|
||||
</pre>
|
||||
In the constructor, you set the number of triangles you wish to
|
||||
generate, the radius and height of the approximately cylindrical
|
||||
fire and the speed at which the flames head up towards the sky.
|
||||
<p>
|
||||
The number of polygons you use tends to be rather critical - too
|
||||
many and your fire will look too 'smooth' and will be mostly
|
||||
white-hot. Too few and it'll look like a number of detached
|
||||
reddish blobs floating upwards. For the default radius, between
|
||||
100 and 200 triangles seems to look good - for a 10 meter patch
|
||||
of fire, you may need as many as 2000 triangles to make it look
|
||||
effective. All three parameters (speed, height and radius) can
|
||||
be manipulated in realtime - but since the number of polygons
|
||||
is fixed, there is a limit to the amount of realtime tweaking
|
||||
you can do without making it look silly.
|
||||
<p>
|
||||
The 'setHotColour' function allows you to set the colour
|
||||
of the hottest flames (at the base of the fire). Since many
|
||||
layers of polygons add up to form the colour, you'll tend to
|
||||
want to use a primary colour with about 10% of one or two of
|
||||
the other primaries. The default colour is (1.0, 0.2, 0.1, 1.0)
|
||||
which produces red flames with yellow and white in the hotter
|
||||
regions.
|
||||
<p>
|
||||
<A NAME="ssgaLensFlare"></A>
|
||||
<H1>ssgaLensFlare</H1>
|
||||
When you view the sun (or some other very bright light source) through
|
||||
the imperfect lens of a camera, you get a row of bright circles and
|
||||
rings in a line from the light source, through the center of the lens.
|
||||
This is called a 'lens flare' and it can be very effective in computer
|
||||
graphics in depicting a light source that's brighter than the computer
|
||||
screen can display. It almost makes you want to squint because of
|
||||
the brightness.
|
||||
<p>
|
||||
The ssgaLensFlare object is a special kind of ssgaShape that can be
|
||||
positioned beneath the same transform
|
||||
as the source of the light - and it 'just works'. You don't need
|
||||
to set any parameters - just add it into the SSG scene graph in the
|
||||
right place.
|
||||
<p>
|
||||
eg:
|
||||
<pre>
|
||||
|
||||
ssgTransform *myTransform ;
|
||||
ssgBranch *myLightSource ;
|
||||
|
||||
/* Set up myTransform and myLightsource */
|
||||
|
||||
...
|
||||
|
||||
myTransform -> addKid ( myLightSource ) ;
|
||||
myTransform -> addKid ( new ssgaLensFlare ) ;
|
||||
|
||||
</pre>
|
||||
It contains a (hard-coded) 256x128 texture map which is compiled
|
||||
into the code and shared between however many lens flares there
|
||||
are in the scene.
|
||||
<p>
|
||||
<A NAME="ssgaSky"></A>
|
||||
<H1>ssgaSky</H1>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD width="40%" valign="top">
|
||||
The ssgaSky class models a blended sky dome, with methods to add celestial
|
||||
bodies, for example a haloed sun or a textured moon, and methods to add
|
||||
clouds, stars and planets.
|
||||
<p>
|
||||
<b>WARNING</b> - Solaris C/C++ compilers (from Sun Microsystems Inc) have
|
||||
some nasty '#define's for the word 'SUN' and 'sun'. If you are writing
|
||||
portable software, you might want to pick an alternative word! PLIB uses 'Sol',
|
||||
the formal astronomical name for the star that happens to be our sun.
|
||||
<p>
|
||||
The sky implements various time of day lighting effects, it plays well
|
||||
with fog and visibility effects, and implements scudded cloud fly-through
|
||||
effects. Additionally, you can wire in the output of the SimGear
|
||||
<a href="http://www.simgear.org/doxygen/classSGEphemeris.html">SGEphemeris</a>
|
||||
class to accurately position all the objects in the sky.
|
||||
<p>
|
||||
This sky dome code was based on the <a href="http://www.simgear.org/">SimGear</a>
|
||||
sky code, written by Curtis Olson, which is used in
|
||||
<a href="http://www.flightgear.org/">FlightGear</a>.
|
||||
The code was moved into PLIB for easier access, STL was removed and 'flat
|
||||
earth' methods added. The main reason the code was moved here was to allow
|
||||
the PLIB community to add their own extensions (not relevant to FlightGear),
|
||||
to build for example, 'un-realistic' sky domes, with green skies, purple
|
||||
clouds or multiple suns. This has not yet fully been achieved, but hopefully
|
||||
when someone finds the time or has the need, these features will be added.
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<IMG SRC="ssgaSky.png" ALT="ssgaSky screenshots" WIDTH=400 HEIGHT=300>
|
||||
<br>
|
||||
ssgaSky screenshots
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<pre>
|
||||
class ssgaSky
|
||||
{
|
||||
public:
|
||||
|
||||
ssgaSky( void );
|
||||
~ssgaSky( void );
|
||||
|
||||
void build( double h_radius, double v_radius,
|
||||
int nplanets, sgdVec3 *planet_data,
|
||||
int nstars, sgdVec3 *star_data);
|
||||
|
||||
ssgaCelestialBody* addBody( const char *body_tex_path, const char *halo_tex_path, double size, double dist, bool sol = false );
|
||||
ssgaCelestialBody* addBody( ssgSimpleState *orb_state, ssgSimpleState *halo_state, double size, double dist, bool sol = false );
|
||||
ssgaCelestialBody* getBody(int i) { return bodies.get(i); }
|
||||
int getBodyCount() { return bodies.getNum(); }
|
||||
|
||||
ssgaCloudLayer* addCloud( const char *cloud_tex_path, float span, float elevation, float thickness, float transition );
|
||||
ssgaCloudLayer* addCloud( ssgSimpleState *cloud_state, float span, float elevation, float thickness, float transition );
|
||||
ssgaCloudLayer* getCloud(int i) { return clouds.get(i); }
|
||||
int getCloudCount() { return clouds.getNum(); }
|
||||
|
||||
bool repositionFlat( sgVec3 view_pos, double spin, double dt );
|
||||
bool reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up,
|
||||
double lon, double lat, double alt, double spin, double gst, double dt );
|
||||
|
||||
bool repaint( sgVec4 sky_color, sgVec4 fog_color, sgVec4 cloud_color, double sol_angle,
|
||||
int nplanets, sgdVec3 *planet_data,
|
||||
int nstars, sgdVec3 *star_data );
|
||||
|
||||
void modifyVisibility( float alt, float time_factor );
|
||||
|
||||
void preDraw();
|
||||
void postDraw( float alt );
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
float getVisibility();
|
||||
void setVisibility( float v );
|
||||
} ;
|
||||
</pre>
|
||||
<H2>Building the sky</H2>
|
||||
Once you have created an instance of ssgaSky you must call the
|
||||
build() method. The arguments you pass to the build() method
|
||||
allow you to specify the size of your sky dome, a number of planets,
|
||||
and a multitude of stars. For the planets and stars you pass in
|
||||
an array of right ascensions, declinations, magnitudes, and the
|
||||
distance from the view point.
|
||||
<H2>Celestial Bodies</H2>
|
||||
Celestial bodies (eg. sun, moon or even mars if you like) can be
|
||||
added or modified individually. To add a body use the addBody()
|
||||
method. The arguments allow you to specify the body texture, the
|
||||
halo texture, the size of the body, the body distance (usually the
|
||||
sky dome size) and a boolean flag to indicate if the body should
|
||||
be used as a reference to 'spin' the dome based on the bodies rotation
|
||||
for correct sunrise and sunset effects (nb. the sun reference is only used
|
||||
by repositionFlat() so the user does not need to calculate the spin
|
||||
parameter). There is an additional form of this method that allows
|
||||
you to specify your own ssgSimpleState for drawing the body and halo
|
||||
texture.
|
||||
<p>
|
||||
Body accessor methods are available to:
|
||||
<ul>
|
||||
<li> set body right ascension and declination
|
||||
<li> get body position and color
|
||||
</ul>
|
||||
note: body angle and rotation are calculated internally (by
|
||||
ssgaSky::repositionFlat() only) for sunrise and sunset effects.
|
||||
<pre>
|
||||
class ssgaCelestialBody
|
||||
{
|
||||
...
|
||||
void getPosition ( sgCoord* p );
|
||||
|
||||
void setAngle ( double angle );
|
||||
double getAngle ();
|
||||
|
||||
void setRotation ( double rotation );
|
||||
double getRotation ();
|
||||
|
||||
void setRightAscension ( double ra );
|
||||
double getRightAscension ();
|
||||
|
||||
void setDeclination ( double decl );
|
||||
double getDeclination ();
|
||||
|
||||
void setDist ( double dist );
|
||||
double getDist ();
|
||||
|
||||
float *getColor();
|
||||
} ;
|
||||
</pre>
|
||||
<H2>Cloud Layers</H2>
|
||||
Cloud layers can be added or modified individually. To add a cloud
|
||||
layer use the addCloud() method. The arguments allow you to specify
|
||||
cloud texture, the size of the cloud object, base height above sea
|
||||
level, layer thickness and a transition zone for entering/leaving
|
||||
the cloud layer. There is an additional form of this method that
|
||||
allows you to specify your own ssgSimpleState for drawing the cloud
|
||||
layer texture.
|
||||
<p>
|
||||
Cloud accessor methods are available to:
|
||||
<ul>
|
||||
<li> enable/disable clouds
|
||||
<li> set elevation above sea level
|
||||
<li> set thickness and transition - used to simulate cloud 'puffs'
|
||||
<li> set speed and direction - used to simulate cloud movement
|
||||
</ul>
|
||||
<pre>
|
||||
class ssgaCloudLayer
|
||||
{
|
||||
...
|
||||
void enable();
|
||||
void disable();
|
||||
bool isEnabled();
|
||||
|
||||
float getElevation ();
|
||||
void setElevation ( float elevation );
|
||||
|
||||
float getThickness ();
|
||||
void setThickness ( float thickness );
|
||||
|
||||
float getTransition ();
|
||||
void setTransition ( float transition );
|
||||
|
||||
float getSpeed ();
|
||||
void setSpeed ( float val );
|
||||
|
||||
float getDirection ();
|
||||
void setDirection ( float val );
|
||||
} ;
|
||||
</pre>
|
||||
<H2>Repainting the Sky</H2>
|
||||
As the sun circles the globe, you can call the repaint() method to
|
||||
re-color the sky objects to simulate sunrise and sunset effects,
|
||||
visibility, and other lighting changes. The arguments allow you
|
||||
to specify a base sky color (for the top of the dome), a fog color
|
||||
(for the horizon), a cloud color (for blending clouds with the fog
|
||||
color), the sun angle with the horizon (for sunrise/sunset effects),
|
||||
and new star and planet data so that we can optionally change the
|
||||
magnitude of these (for day/night transitions).
|
||||
<H2>Positioning Sky Objects</H2>
|
||||
As time progresses and as you move across the surface of the earth,
|
||||
the apparent position of the objects and the various lighting effects
|
||||
can change. At this point you may wish to call celestial body
|
||||
setRightAscension() and setDeclination() methods to update the
|
||||
position of your bodies (SimGear
|
||||
<a href="http://www.simgear.org/doxygen/classSGEphemeris.html">SGEphemeris</a>
|
||||
can be used if you wish to place bodies correctly).
|
||||
<p>
|
||||
Once you have specified the positions of all the sky objects, you must
|
||||
call the repositionFlat() or reposition() method to allow you to specify
|
||||
your view position.
|
||||
<p>
|
||||
The repositionFlat() arguments allow you to specify view position for
|
||||
a 'flat earth' model. A 'spin' angle can be specified for orienting
|
||||
the sky with the sun position so sunset and sunrise effects look correct.
|
||||
If you specified a body to be the sun reference on addBody() you do not
|
||||
need to specify the 'spin' angle. You may specify the amount of elapsed
|
||||
time since the sky was last updated (used to animate cloud movement).
|
||||
<p>
|
||||
The reposition() arguments allow you to specify your view position in
|
||||
world Cartesian coordinates, the zero elevation position in world
|
||||
Cartesian coordinates (your longitude, your latitude, sea level),
|
||||
the 'up' vector in world Cartesian coordinates, current longitude,
|
||||
latitude, and altitude. A 'spin' angle can be specified for
|
||||
orienting the sky with the sun position so sunset and sunrise
|
||||
effects look correct. You must specify GMT side real time. You may
|
||||
specify the amount of elapsed time since the sky was last updated
|
||||
(used to animate cloud movement).
|
||||
<H2>Rendering the Sky</H2>
|
||||
The sky is designed to be rendered in two stages. The first stage
|
||||
renders the parts that form your back drop - the sky dome, the
|
||||
stars, the planets and the celestial bodies. These should be
|
||||
rendered before the rest of your scene by calling the preDraw()
|
||||
method. The second stage renders the clouds which are likely to be
|
||||
translucent and should be drawn after your scene has been rendered.
|
||||
Use the postDraw() method to draw the second stage of the sky.
|
||||
<p>
|
||||
A typical application might do the following:
|
||||
<pre>
|
||||
thesky->preDraw();
|
||||
ssgCullAndDraw ( myscene ) ;
|
||||
thesky->postDraw( my_altitude );
|
||||
</pre>
|
||||
The current altitude in meters is passed to the postDraw()
|
||||
method so the clouds layers can be rendered correctly from
|
||||
most distant to closest.
|
||||
<H2>Visibility Effects</H2>
|
||||
Visibility and fog is important for correctly rendering the sky.
|
||||
You can inform ssgaSky of the current visibility by calling
|
||||
the setVisibility() method.
|
||||
<p>
|
||||
When transitioning through clouds, it is nice to pull in the
|
||||
fog as you get close to the cloud layer to hide the fact that
|
||||
the clouds are drawn as a flat polygon. As you get nearer to
|
||||
the cloud layer it is also nice to temporarily pull in the
|
||||
visibility to simulate the effects of flying in and out of
|
||||
the puffy edge of the cloud. These effects can all be
|
||||
accomplished by calling the modifyVisibility() method. The
|
||||
arguments allow you to specify your current altitude
|
||||
(which is then compared to the altitudes of the various
|
||||
cloud layers). You can also specify a time factor which
|
||||
should be the length in seconds since the last time you
|
||||
called modifyVisibility(). The time_factor value allows the
|
||||
puffy cloud effect to be calculated correctly.
|
||||
<p>
|
||||
The modifyVisibility() method alters the ssgaSky's internal
|
||||
idea of visibility, so you should subsequently call
|
||||
getVisibility() to get the actual modified visibility.
|
||||
You should then make the appropriate glFog() calls to
|
||||
setup fog properly for your scene.
|
||||
<H2>Accessor Methods</H2>
|
||||
Once an instance of ssgaSky has been successfully
|
||||
initialized, there are a couple accessor methods you
|
||||
can use such as getBodyCount() to return the number
|
||||
of celestial bodies, getBody(i) to return body number
|
||||
i, getCloudCount() to return the number
|
||||
of cloud layers, getCloud(i) to return cloud
|
||||
layer number i, getVisibility() to return the actual
|
||||
visibility as modified by the sky/cloud model.
|
||||
<p>
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
BIN
doc/ssgAux/snapshot.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
doc/ssgAux/ssgaSky.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
doc/torcs_logo.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
doc/tux_aqfh.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
doc/tuxfleet_logo.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
doc/tuxkart_logo.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
626
doc/util/index.html
Normal file
@@ -0,0 +1,626 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="keywords" content="UL, PLIB, OpenGL, utility, library, portable, Baker, Steve, ulDir, ulClock, ulDynamicLibrary, ulList, ulLinkedList, ulHashTable, ulPropertySet, ulSleep, ulMilliSecondSleep, ulFindFile, ulFileExists, ulIsAbsolutePathName, ulGetCWD, ulMakePath, ulSetErrorCallback, ulGetErrorCallback, ulGetError, ulClearError, ulStrEqual, ulStrNEqual">
|
||||
<META name="description" content="The PLIB Utility Library is targeted towards hiding common operating system functions behind a thin layer that makes them portable and provides some useful helper classes and routines.">
|
||||
<TITLE>The Utility Library.</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="../marble.png">
|
||||
|
||||
<H1>The PLIB general Utility Library.</H1>
|
||||
By Sebastian Ude
|
||||
<H2>Introduction</H2>
|
||||
The 'UL' utility library is primarily targeted towards hiding common
|
||||
operating system functions behind a thin layer that makes them portable.
|
||||
Additionally, it provides some helper classes or routines that were
|
||||
usually written to support certain parts of the
|
||||
<a href="../index.html">PLIB</a> library, but at some point we felt that
|
||||
they could be useful for user applications as well.
|
||||
<p>
|
||||
UL is a part of <a href="../index.html">PLIB</a>.
|
||||
|
||||
<h2>Contents:</h2>
|
||||
<ul>
|
||||
<li><a href="#miscFunc">Misc. routines</a>
|
||||
<li><a href="#fileHandling">File handling</a>
|
||||
<li><a href="#dirHandling">Directory handling</a>
|
||||
<li><a href="#dataStorage">Data storage</a>
|
||||
<li><a href="#errorHandling">Error handling</a>
|
||||
<li><a href="#miscClasses">Misc. classes</a>
|
||||
<li><a href="#endianHandling">Endian handling</a>
|
||||
</ul>
|
||||
|
||||
<h2>Quick reference:</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td><h3>Classes:</h3>
|
||||
<td colspan=2><h3>Non-class functions:</h3>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li><a href="#ulDir">ulDir</a>
|
||||
<li><a href="#ulClock">ulClock</a>
|
||||
<li><a href="#ulDynamicLibrary">ulDynamicLibrary</a>
|
||||
<li><a href="#ulList">ulList</a>
|
||||
<li><a href="#ulLinkedList">ulLinkedList</a>
|
||||
<li><a href="#ulHashTable">ulHashTable</a>
|
||||
<li><a href="#ulPropertySet">ulPropertySet</a>
|
||||
</ul>
|
||||
|
||||
<td>
|
||||
<ul>
|
||||
<li><a href="#ulSleep">ulSleep</a>, <a href="#ulMilliSecondSleep">ulMilliSecondSleep</a>
|
||||
<li><a href="#ulFindFile">ulFindFile</a>
|
||||
<li><a href="#ulFileExists">ulFileExists</a>
|
||||
<li><a href="#ulIsAbsolutePathName">ulIsAbsolutePathName</a>
|
||||
<li><a href="#ulGetCWD">ulGetCWD</a>
|
||||
<li><a href="#ulMakePath">ulMakePath</a>
|
||||
<li><a href="#ulSetErrorCallback">ulSetErrorCallback</a>, <a href="#ulGetErrorCallback">ulGetErrorCallback</a>
|
||||
</ul>
|
||||
|
||||
<td valign="top">
|
||||
<ul>
|
||||
<li><a href="#ulGetError">ulGetError</a>, <a href="#ulClearError">ulClearError</a>
|
||||
<li><a href="#ulStrEqual">ulStrEqual</a>, <a href="#ulStrNEqual">ulStrNEqual</a>
|
||||
</ul>
|
||||
</table>
|
||||
|
||||
<h2><a name="miscFunc">Misc. routines</a></h2>
|
||||
|
||||
<h3><a name="ulSleep">ulSleep</a></h3>
|
||||
<pre><i>
|
||||
void ulSleep ( int seconds ) ;
|
||||
</i></pre>
|
||||
Now comes a typical example of what the UL library does. If you need to
|
||||
'sleep' for, say, 3 seconds, then under Linux/UNIX, you'd need to call:
|
||||
<pre><i>
|
||||
sleep ( 3 ) ;
|
||||
</i></pre>
|
||||
But under MS-Windows, you have to say:
|
||||
<pre><i>
|
||||
Sleep ( 3000 ) ;
|
||||
</i></pre>
|
||||
In order to avoid writing non-portable code, you can instead call:
|
||||
<pre><i>
|
||||
ulSleep ( 3 ) ;
|
||||
</i></pre>
|
||||
...under either operating system.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulMilliSecondSleep">ulMilliSecondSleep</a></h3>
|
||||
<pre><i>
|
||||
void ulMilliSecondSleep ( int milliseconds ) ;
|
||||
</i></pre>
|
||||
Same as <a href="#ulSleep">ulSleep</a>, except that it sleeps (as you
|
||||
may have guessed) a certain number of milliseconds instead of seconds.
|
||||
|
||||
<h2><a name="fileHandling">File handling</a></h2>
|
||||
|
||||
<h3><a name="ulFindFile">ulFindFile</a></h3>
|
||||
<pre><i>
|
||||
void ulFindFile ( char *filenameOutput, const char *path, const char * tfnameInput, const char *sAPOM ) ;
|
||||
</i></pre>
|
||||
Basically, this utility function adds tfnameInput to the path and puts this
|
||||
into the buffer filenameOutput.
|
||||
<p>
|
||||
It handles special chars in path:
|
||||
<ul>
|
||||
<li>";;" is replaced by ";"
|
||||
<li>"$$" is replaced by "$"
|
||||
<li>"$(APOM)" is replaced by sAPOM
|
||||
</ul>
|
||||
If there are ";" in path, the path-variable is interpreted as several paths
|
||||
"segments", delimited by ";". The first file found by this function is
|
||||
returned. It looks from left to right. A segment may end in $(...). ulFindFile
|
||||
will then look in in this path and recursively in all the sub-paths.
|
||||
<p>
|
||||
Some examples:
|
||||
<p>
|
||||
To load *.MDl-models, it is very nice to set the texture path to
|
||||
"$(APOM);$(APOM)/texture;$(APOM)/../texture". This consists of three segments
|
||||
and tells ulFindFile to look in the path of the model, in a subpath texture
|
||||
and in a path texture "besides" the path of the model. Some *.mdl-models are
|
||||
shipped in a directory which contains a "texture"-directory, a
|
||||
"Model"-directory and others. In this case you find the texture in
|
||||
"$(APOM)/../texture".
|
||||
<p>
|
||||
Another example: You have all your textures in a directory-structure under
|
||||
/roomplan:
|
||||
<pre>
|
||||
textures --+-- Wallpapers
|
||||
|
|
||||
+-- Wood --+-- Oak
|
||||
| |
|
||||
| +-- pine
|
||||
...
|
||||
</pre>
|
||||
Then you should simply use the following texture path:
|
||||
"/roomplan/$(...)"
|
||||
|
||||
<p>
|
||||
<h3><a name="ulFileExists">ulFileExists</a></h3>
|
||||
<pre><i>
|
||||
bool ulFileExists ( const char *fileName ) ;
|
||||
</i></pre>
|
||||
Returns "true" if a file with the name 'fileName' exists, or "false" if
|
||||
it does not.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulIsAbsolutePathName">ulIsAbsolutePathName</a></h3>
|
||||
<pre><i>
|
||||
int ulIsAbsolutePathName ( const char *pathname ) ;
|
||||
</i></pre>
|
||||
Returns '1' if 'pathname' is an absolute pathname or '0' if it is an
|
||||
relative one.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulGetCWD">ulGetCWD</a></h3>
|
||||
<pre><i>
|
||||
char * ulGetCWD ( char *result, int maxlength ) ;
|
||||
</i></pre>
|
||||
Stores the current working directory in 'result', which has enough space
|
||||
for 'maxlength' characters, including the trailing '\0'. On success,
|
||||
'result' is returned.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulMakePath">ulMakePath</a></h3>
|
||||
<pre><i>
|
||||
char * ulMakePath ( char *path, const char *dir, const char *fname ) ;
|
||||
</i></pre>
|
||||
Concatenates the strings 'dir' and 'fname', puts the system's slash character
|
||||
inbetween and stores stores the result in 'path'. Be sure that the buffer
|
||||
'path' is large enough to store 'strlen ( dir ) + strlen ( fname ) + 2'
|
||||
(slash and trailing '\0') characters.
|
||||
|
||||
<h2><a name="dirHandling">Directory handling</a></h2>
|
||||
|
||||
<h3><a name="ulDir">struct ulDir</a></h3>
|
||||
This structure provides a portable way to read directories. To allocate and
|
||||
initialize a new ulDir structure, call:
|
||||
<pre><i>
|
||||
ulDir * ulOpenDir ( const char* dirname ) ;
|
||||
</i></pre>
|
||||
This function returns a pointer to a newly allocated ulDir structure on
|
||||
success or a NULL pointer if the specified directory could not be read.
|
||||
<p>
|
||||
After you have constructed an ulDir structure, the directory content can
|
||||
be read with subsequent calls to:
|
||||
<pre><i>
|
||||
struct ulDirEnt
|
||||
{
|
||||
char d_name [ UL_NAME_MAX+1 ] ;
|
||||
bool d_isdir ;
|
||||
} ;
|
||||
ulDirEnt * ulReadDir ( ulDir *dir ) ;
|
||||
</i></pre>
|
||||
This function returns a pointer to a ulDirEnt structure which resides in
|
||||
the corresponding ulDir structure and which has the above form. The "d_isdir"
|
||||
flag indicates if a directory entry is another directory. If the end of the
|
||||
directory has been reached, the function returns NULL.
|
||||
<p>
|
||||
To free an ulDir object and to close the associated directory stream,
|
||||
please call:
|
||||
<pre><i>
|
||||
void ulCloseDir ( ulDir *dir ) ;
|
||||
</i></pre>
|
||||
|
||||
<h2><a name="dataStorage">Data storage</a></h2>
|
||||
|
||||
<h3><a name="ulList">class ulList</a></h3>
|
||||
<pre><i>
|
||||
ulList::ulList ( int init_max = 1 ) ;
|
||||
</i></pre>
|
||||
This class stores a list of generic (void*) pointers using an
|
||||
automatically-growing array. Since the process of resizing the internal
|
||||
array is rather expensive, it is important that one picks a reasonable default
|
||||
array size (<i>init_max</i>) when constructing an ulList object if performance
|
||||
matters. Remember that a too large size means that some memory is wasted (but
|
||||
memory is cheap nowadays), while a too small one means that expensive array
|
||||
resize operations will be necessary later.
|
||||
<p>
|
||||
If you have absolutely no clue about how many entities will be stored,
|
||||
you should probably look at the <a href="#ulLinkedList">linked list class</a>
|
||||
below, which has it's own disadvantages, though.
|
||||
<p>
|
||||
Once you have constructed an ulList (hopefully with a good initial size),
|
||||
you can insert an element using one of the following methods:
|
||||
<pre><i>
|
||||
void ulList::addEntity ( void *entity ) ;
|
||||
void ulList::addBefore ( int n, void *entity ) ;
|
||||
</i></pre>
|
||||
While the first one simply adds the new entity to the tail of the list,
|
||||
the second one lets you specify an exact position (0 is the first element).
|
||||
Note that due to it's array implementation, inserting an entity at the head
|
||||
or the middle of the ulList requires that the following entities are all
|
||||
shifted one array slot to the right, which can be a rather expensive
|
||||
operation.
|
||||
<p>
|
||||
These functions automatically check whether there is room for one more element
|
||||
and double the internal array's size if necessary. However, as said
|
||||
previously, resizing the array is a rather expensive process, so it is not
|
||||
recommended that you rely too much on this behavior. Instead, pick a good
|
||||
initial array size.
|
||||
<p>
|
||||
Note that ulList allows you to have multiple entities with the same data
|
||||
value in the list. Please also note that ulList does not make it's own copy
|
||||
of the data pointed to by 'entity'. It is up to you to take care of that the
|
||||
memory region that 'entity' points to holds something useful as long as the
|
||||
ulList exists. Be especially careful with addresses of variables that have a
|
||||
limited lifetime.
|
||||
<p>
|
||||
To retrieve an entity, call:
|
||||
<pre><i>
|
||||
void * ulList::getEntity ( unsigned int n ) ;
|
||||
</i></pre>
|
||||
Where 'n' is the position of the entity in the list. If 'n' is not a valid
|
||||
index, NULL is returned. Once you have called this function, you can use
|
||||
subsequent calls to
|
||||
<pre><i>
|
||||
void * ulList::getNextEntity ( void ) ;
|
||||
</i></pre>
|
||||
in order to retrieve the following entities in the list. If there are no more
|
||||
entities, this function will return NULL.
|
||||
<p>
|
||||
To remove an entity, call one of:
|
||||
<pre><i>
|
||||
void ulList::removeEntity ( unsigned int n ) ;
|
||||
void ulList::removeEntity ( void *entity ) ;
|
||||
</i></pre>
|
||||
Where the second function removes the <b>first</b> entity with the specified
|
||||
data value in case there are multiple ones.
|
||||
<p>
|
||||
To replace the value of an entity, call one of:
|
||||
<pre><i>
|
||||
void ulList::replaceEntity ( unsigned int n, void *new_entity ) ;
|
||||
void ulList::replaceEntity ( void *old_entity, void *new_entity ) ;
|
||||
</i></pre>
|
||||
Where the second function will replace the value of the <b>first</b> entity
|
||||
with the specified old data value in case there are multiple ones.
|
||||
<p>
|
||||
And finally, you can retrieve the number of entities stored in the list
|
||||
(that's <b>not</b> necessarily the internal array's size), remove all
|
||||
entities or retrieve the position of an entity by specifying it's data
|
||||
value:
|
||||
<pre><i>
|
||||
void ulList::getNumEntities ( void ) const ;
|
||||
void ulList::removeAllEntities () ;
|
||||
int ulList::searchForEntity ( void *entity ) const ;
|
||||
</i></pre>
|
||||
Where the latter returns a negative value if no entity with the specified
|
||||
value was found in the list, and otherwise the position of the <b>first</b>
|
||||
entity with the specified data value.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulLinkedList">class ulLinkedList</a></h3>
|
||||
<pre><i>
|
||||
ulLinkedList::ulLinkedList () ;
|
||||
</i></pre>
|
||||
The ulLinkedList class stores generic (void*) pointers using a linked list
|
||||
of nodes where each node maintains a pointer to the next node.
|
||||
<p>
|
||||
This technique has some advantages compared to an array implementation of a
|
||||
list like <a href="#ulList">ulList</a>.
|
||||
<ul>
|
||||
<li>
|
||||
No wasted memory. When storing data using arrays (as
|
||||
<a href="#ulList">ulList</a> does), it is a common practice to choose an array
|
||||
size that seems "large enough". Most of the time the number of entities stored
|
||||
will be smaller than the available array slots, so some memory space is wasted.
|
||||
With a linked list, we allocate single nodes. No memory is wasted (except a
|
||||
few bytes for each node's pointer to the next node).
|
||||
|
||||
<li>
|
||||
Resizing an array is an expensive operation, since usually the whole array
|
||||
content has to be copied from the old to the new memory location. We do not
|
||||
have this problem with linked lists.
|
||||
|
||||
<li>
|
||||
In contrast to arrays, it is a cheap operation to insert or remove entities
|
||||
to / from the head or middle of a linked list. While with an array, the
|
||||
following entities must all be shifted one slot to the left or right, we
|
||||
simply need to (re)connect a few pointers with a linked list.
|
||||
</ul>
|
||||
There are some disadvantages, though:
|
||||
<ul>
|
||||
<li>
|
||||
In contrast to an array, there is no cheap way to locate the n-th entity in a
|
||||
linked list. With an array, you simply have to add the desired position
|
||||
multiplied with the size of an element to the array's base address and
|
||||
look at the content of the memory at this location - a very simple operation.
|
||||
With a linked list, however, we need to iterate over all nodes 'n' times,
|
||||
so locating the 1000th node is a rather expensive operation.
|
||||
|
||||
<li>
|
||||
One may argue that insertion operations are more expensive with linked lists
|
||||
than with arrays, since we allocate single nodes from the heap in contrast
|
||||
to an array, where the whole list is one huge allocated block of memory.
|
||||
Although allocation from the heap is indeed rather expensive, this is not
|
||||
true when it comes to insertions to the middle of a list, these are usually
|
||||
<b>way</b> more expensive with arrays. Furthermore, a list implemented using
|
||||
an array such as <a href="#ulList">ulList</a> may make resizes of the array
|
||||
necessary on insertions, which are again rather expensive.
|
||||
</ul>
|
||||
Decide yourself if a list implemented as an array such as
|
||||
<a href="#ulList">ulList</a> or a linked list implementation like this one fits
|
||||
your needs better.
|
||||
<p>
|
||||
Once you have constructed a ulLinkedList object, you can insert a node using
|
||||
one of:
|
||||
<pre><i>
|
||||
void ulLinkedList::appendNode ( void *data ) ;
|
||||
void ulLinkedList::prependNode ( void *data ) ;
|
||||
void ulLinkedList::insertNode ( void *data, int pos ) ;
|
||||
</i></pre>
|
||||
While "appendNode" adds the new node at the tail of the list, "prependNode"
|
||||
will place the new node at the head of the list, and "insertNode" allows
|
||||
you to specify the desired position ('0' is the first node) yourself; 'pos'
|
||||
must be either '0' or a number between '0' and the number of nodes minus one.
|
||||
"prependNode" is equal to calling "insertNode" with pos == 0.
|
||||
<p>
|
||||
Note that ulLinkedList allows you to have two nodes with the same data in
|
||||
the list. Also note that just as <a href="#ulList">ulList</a>, ulLinkedList
|
||||
does not make it's own copy of the memory pointed to by 'data', so make sure
|
||||
that the corresponding memory location holds something useful as long as the
|
||||
list exists.
|
||||
<p>
|
||||
To retrieve the number of nodes in the list, call:
|
||||
<pre><i>
|
||||
int ulLinkedList::getNumNodes ( void ) const ;
|
||||
</i></pre>
|
||||
<p>
|
||||
To retrieve the data of the node at a certain position in the list, call:
|
||||
<pre><i>
|
||||
void * ulLinkedList::getNodeData ( int pos ) const ;
|
||||
</i></pre>
|
||||
Where 'pos' must be a number between '0' and the number of nodes minus one,
|
||||
again.
|
||||
<p>
|
||||
If you need to retrieve the position of a node in the list by specifying it's
|
||||
data value, call:
|
||||
<pre><i>
|
||||
int ulLinkedList::getNodePosition ( void *data ) const ;
|
||||
</i></pre>
|
||||
If there is more than one node whose data value is 'data' in the list, this
|
||||
function will return the position of the <b>first</b> one. If there is no
|
||||
node with the specified data value in the list, this function will return a
|
||||
negative number to indicate failure.
|
||||
<p>
|
||||
Checking if the return value of "getNodePosition" is non-negative is also
|
||||
the recommended way to determine whether there exists at least one node with
|
||||
a certain data value in a list.
|
||||
<p>
|
||||
To remove a node from the list, call one of:
|
||||
<pre><i>
|
||||
bool ulLinkedList::removeNode ( void *data ) ;
|
||||
void * ulLinkedList::removeNode ( int pos ) ;
|
||||
</i></pre>
|
||||
Where the first function returns 'true' if the node was sucessfully removed or
|
||||
'false' if it could not find a node whose value is 'data'. In case there is
|
||||
more than one node whose data value is 'data', it will remove the <b>first</b>
|
||||
one. With the second function, 'pos' has to be a number between '0' and the
|
||||
number of nodes minus one. It's return value is the removed node's data
|
||||
value.
|
||||
<p>
|
||||
To iterate over the list (starting from the head) and to have a custom
|
||||
function being called for each node's data pointer, call:
|
||||
<pre><i>
|
||||
typedef bool (*ulIterateFunc)( void *data, void *user_data ) ;
|
||||
void * ulLinkedList::forEach ( ulIterateFunc fn, void *user_data = NULL ) const ;
|
||||
</i></pre>
|
||||
The iteration process will stop if your ulIterateFunc returns 'false', in
|
||||
which case "forEach" returns the data value of the node at which the iteration
|
||||
stopped, or if the tail of the list has been reached, in which case "forEach"
|
||||
returns NULL. The user_data pointer will be passed to your ulIterateFunc as
|
||||
the second argument.
|
||||
<p>
|
||||
ulLinkedList allows you to maintain a sorted list as an option. To set up
|
||||
a sorted list, simply be sure to insert all nodes using the sorted insertion
|
||||
function as soon as there is at least one node in the list. It's prototype is:
|
||||
<pre><i>
|
||||
typedef int (*ulCompareFunc)( const void *data1, const void *data2 ) ;
|
||||
int ulList::insertSorted ( void *data, ulCompareFunc comparefn ) ;
|
||||
</i></pre>
|
||||
Where 'comparefn' is your custom comparison function that takes two
|
||||
data pointers, compares them and returns a memcmp / strcmp-like result:
|
||||
<ul>
|
||||
<li>
|
||||
A number <b>less than zero</b> if "data1" is "smaller" than "data2", that
|
||||
means if "data1" had to be inserted <b>before</b> "data2" in the list.
|
||||
|
||||
<li>
|
||||
A number <b>equal to zero</b> if "data1" is equal to "data2", that means if
|
||||
"data" had to be inserted immediately before or after "data2" in the list.
|
||||
|
||||
<li>
|
||||
A number <b>greater than zero</b> if "data1" is "greater" than "data2",
|
||||
that means if "data" had to be inserted <b>after</b> "data2" in the list.
|
||||
</ul>
|
||||
The return value of "insertSorted" is the position of the new node in the list
|
||||
on success, or a negative value if you tried to do a sorted insertion on a
|
||||
non-sorted list, that is a list which contains more than one node of which
|
||||
at least one was not inserted using the sorted insertion function. In the
|
||||
latter case, the new node would not have been inserted to the list.
|
||||
<p>
|
||||
To determine whether a list is sorted or not, call the following function:
|
||||
<pre><i>
|
||||
bool ulLinkedList::isSorted ( void ) const ;
|
||||
</i></pre>
|
||||
Note that with a linked list, you <b>must not</b> modify the criteria of a
|
||||
node's data that is used for sorting without removing the node from the list
|
||||
and re-inserting it.
|
||||
<p>
|
||||
Finally, you can empty a list (remove all nodes) by calling:
|
||||
<pre><i>
|
||||
typedef bool (*ulIterateFunc)( const void *data ) ;
|
||||
void ulList::empty ( ulIterateFunc destroyfn = NULL, void *user_data = NULL ) ;
|
||||
</i></pre>
|
||||
Where "destroyfn" is an optionally specified function that will be called
|
||||
with each destroyed node's data pointer as the first and with user_data as
|
||||
the second argument. This is for example useful if the list entries are
|
||||
pointers to dynamically allocated objects that have to be freed on destruction
|
||||
of the list. The return value of the specified function is ignored.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulHashTable">ulHashTable</a></h3>
|
||||
Not yet.
|
||||
|
||||
<h2><a name="errorHandling">Error handling</a></h2>
|
||||
|
||||
<h3><a name="ulSetErrorCallback">ulSetErrorCallback</a></h3>
|
||||
<pre><i>
|
||||
typedef void (*ulErrorCallback) ( enum ulSeverity severity, char* msg ) ;
|
||||
void ulSetErrorCallback ( ulErrorCallback cb ) ;
|
||||
</i></pre>
|
||||
<a href="../index.html">PLIB</a> has an internal error handling system
|
||||
that the subsystems use to report debug, warning or error messages.
|
||||
An application can set up an error callback that PLIB will call whenever such
|
||||
a message occurs in addition to printing the message on the user's terminal.
|
||||
<p>
|
||||
ulSeverety indicates the importance of an message and is currently defined
|
||||
the following way:
|
||||
<pre><i>
|
||||
enum ulSeverity
|
||||
{
|
||||
UL_DEBUG,
|
||||
UL_WARNING,
|
||||
UL_FATAL
|
||||
} ;
|
||||
</i></pre>
|
||||
Where
|
||||
<ul>
|
||||
<li>UL_DEBUG are unimportant debug messages that can usually safely be ignored
|
||||
<li>UL_WARNING are important warning messages that should not be ignored
|
||||
<li>UL_FATAL are fatal errors that PLIB can not recover from
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<h3><a name="ulGetErrorCallback">ulGetErrorCallback</a></h3>
|
||||
<pre><i>
|
||||
typedef void (*ulErrorCallback) ( enum ulSeverity severity, char* msg ) ;
|
||||
ulErrorCallback ulGetErrorCallback ( void ) ;
|
||||
</i></pre>
|
||||
Returns the current <a href="#ulSetErrorCallback">error callback</a> (if
|
||||
any, else NULL is returned).
|
||||
|
||||
<p>
|
||||
<h3><a name="ulGetError">ulGetError</a></h3>
|
||||
<pre><i>
|
||||
char * ulGetError ( void ) ;
|
||||
</i></pre>
|
||||
Returns a pointer to the error buffer, that is, the last error message or an
|
||||
empty string if there were not any error messages or if the error buffer has
|
||||
just been <a href="#ulClearError">cleared</a>.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulClearError">ulClearError</a></h3>
|
||||
<pre><i>
|
||||
void ulClearError ( void ) ;
|
||||
</i></pre>
|
||||
Clears the <a href="#ulGetError">error buffer</a>.
|
||||
|
||||
<h2><a name="miscClasses">Misc. classes</a></h2>
|
||||
|
||||
<h3><a name="ulDynamicLibrary">class ulDynamicLibrary</a></h3>
|
||||
<pre><i>
|
||||
ulDynamicLibrary::ulDynamicLibrary ( const char *libname ) ;
|
||||
</i></pre>
|
||||
This class provides a portable way to load a dynamic library and to retrieve
|
||||
the memory address of a specific function afterwards. When constructing an
|
||||
ulDynamicLibrary object, you have to specify the name of the dynamic library
|
||||
you want to operate on <b>without</b> the platform-specific file extension
|
||||
for dynamic libraries.
|
||||
<p>
|
||||
Afterwards, you can retrieve the memory address where a function / symbol of
|
||||
the library has been loaded by calling:
|
||||
<pre><i>
|
||||
void * ulDynamicLibrary::getFuncAddress ( const char *funcname ) :
|
||||
</i></pre>
|
||||
This function returns NULL if the specified symbol was not found.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulClock">ulClock</a></h3>
|
||||
<pre><i>
|
||||
ulClock::ulClock () ;
|
||||
</i></pre>
|
||||
No further documentation yet.
|
||||
|
||||
<h3><a name="ulPropertySet">ulPropertySet</a></h3>
|
||||
Not yet.
|
||||
|
||||
<h2><a name="stringHandling">String handling</a></h2>
|
||||
|
||||
<h3><a name="ulStrEqual">ulStrEqual</a></h3>
|
||||
<pre><i>
|
||||
int ulStrEqual ( const char *s1, const char *s2 ) ;
|
||||
</i></pre>
|
||||
This function provides a portable way to compare two strings while ignoring
|
||||
the case of the characters. We need it since half of the machines on the
|
||||
planet provide strcasecmp and the other half stricmp for this purpose.
|
||||
<p>
|
||||
In contrast to the libc string comparison routines, this routine returns '1'
|
||||
if the strings are <b>equal</b> and '0' if they are <b>not</b>.
|
||||
|
||||
<p>
|
||||
<h3><a name="ulStrNEqual">ulStrNEqual</a></h3>
|
||||
<pre><i>
|
||||
int ulStrNEqual ( const char *s1, const char *s2, int len ) ;
|
||||
</i></pre>
|
||||
Same as ulStrEqual, except that it only compares the first 'len' characters
|
||||
of the strings.
|
||||
|
||||
<p>
|
||||
<h2><a name="endianHandling">Endian handling</a></h2>
|
||||
<pre><i>
|
||||
bool ulIsLittleEndian ( void ) ;
|
||||
bool ulIsBigEndian ( void ) ;
|
||||
|
||||
unsigned short ulEndianLittle16 ( unsigned short x ) ;
|
||||
unsigned int ulEndianLittle32 ( unsigned int x ) ;
|
||||
float ulEndianLittleFloat ( float x ) ;
|
||||
|
||||
unsigned short ulEndianBig16 ( unsigned short x ) ;
|
||||
unsigned int ulEndianBig32 ( unsigned int x ) ;
|
||||
float ulEndianBigFloat ( float x ) ;
|
||||
|
||||
void ulEndianLittleArray16 ( unsigned short *x, int length ) ;
|
||||
void ulEndianLittleArray32 ( unsigned int *x, int length ) ;
|
||||
void ulEndianLittleArrayFloat ( float *x, int length ) ;
|
||||
|
||||
void ulEndianBigArray16 ( unsigned short *x, int length ) ;
|
||||
void ulEndianBigArray32 ( unsigned int *x, int length ) ;
|
||||
void ulEndianBigArrayFloat ( float *x, int length ) ;
|
||||
|
||||
unsigned short ulEndianReadLittle16 ( FILE *f ) ;
|
||||
unsigned int ulEndianReadLittle32 ( FILE *f ) ;
|
||||
float ulEndianReadLittleFloat ( FILE *f ) ;
|
||||
|
||||
unsigned short ulEndianReadBig16 ( FILE *f ) ;
|
||||
unsigned int ulEndianReadBig32 ( FILE *f ) ;
|
||||
float ulEndianReadBigFloat ( FILE *f ) ;
|
||||
|
||||
size_t ulEndianWriteLittle16 ( FILE *f, unsigned short x ) ;
|
||||
size_t ulEndianWriteLittle32 ( FILE *f, unsigned int x ) ;
|
||||
size_t ulEndianWriteLittleFloat ( FILE *f, float x ) ;
|
||||
|
||||
size_t ulEndianWriteBig16 ( FILE *f, unsigned short x ) ;
|
||||
size_t ulEndianWriteBig32 ( FILE *f, unsigned int x ) ;
|
||||
size_t ulEndianWriteBigFloat ( FILE *f, float x ) ;
|
||||
</i></pre>
|
||||
No further documentation yet.
|
||||
|
||||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
||||
<td>
|
||||
<ADDRESS>
|
||||
Sebastian Ude <<A HREF="mailto:ude@handshake.de">ude@handshake.de</A>>
|
||||
</ADDRESS>
|
||||
</table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
BIN
doc/valid-html40.png
Normal file
|
After Width: | Height: | Size: 799 B |
196
doc/whats_inside.html
Normal file
@@ -0,0 +1,196 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<TITLE>PLIB: What's In PLIB</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
||||
bgcolor="#005000" background="marble.png">
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<IMG SRC="plib_logo.png" ALT="PLIB Logo" width=256 height=245>
|
||||
<br>
|
||||
</TD>
|
||||
<TD>
|
||||
<center>
|
||||
<H1>
|
||||
<FONT SIZE=9>S</FONT><FONT SIZE=5>TEVE'S</FONT>
|
||||
<FONT SIZE=9>P</FONT><FONT SIZE=5>ORTABLE</FONT>
|
||||
<FONT SIZE=9>G</FONT><FONT SIZE=5>AME</FONT>
|
||||
<FONT SIZE=9>L</FONT><FONT SIZE=5>IBRARY.</FONT>
|
||||
</H1>
|
||||
</center>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
And Lo, the Lion and the Sheep shall lie down together - but the Sheep won't
|
||||
get much Sleep.
|
||||
<br>
|
||||
-- Woody Allen
|
||||
</ul>
|
||||
<center>
|
||||
<A href="http://sf.net">
|
||||
<IMG src="http://sf.net/sflogo.php?group_id=382&type=1" width="88" height="31" border="0" ALT="Sourceforge Logo"></A>
|
||||
</center>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD valign=top align=left>
|
||||
<A HREF="index.html"><IMG SRC="home.png" ALT="HOME" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="whats_inside.html"><IMG SRC="whats_inside.png" ALT="WHAT'S INSIDE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="license.html"><IMG SRC="license.png" ALT="LICENSE" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="contacts.html"><IMG SRC="contacts.png" ALT="CONTACTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="requirements.html"><IMG SRC="requirements.png" ALT="REQUIREMENTS" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="gallery.html"><IMG SRC="gallery.png" ALT="GALLERY" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="download.html"><IMG SRC="download.png" ALT="DOWNLOAD & INSTALL" BORDER="0" width=150 height=50></A><br>
|
||||
<A HREF="examples.html"><IMG SRC="examples.png" ALT="EXAMPLES" BORDER="0" width=150 height=50></A><br>
|
||||
|
||||
<A HREF="sg/index.html"><IMG SRC="SG.png" ALT="SG" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="ssg/index.html"><IMG SRC="SSG.png" ALT="SSG" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="ssgAux/index.html"><IMG SRC="ssgAux.png" ALT="SSGAUX" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="fnt/index.html"><IMG SRC="FNT.png" ALT="FNT" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pui/index.html"><IMG SRC="PUI.png" ALT="PUI" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="psl/index.html"><IMG SRC="PSL.png" ALT="PSL" BORDER="0" width=75 height=25></A>
|
||||
|
||||
<A HREF="util/index.html"><IMG SRC="UL.png" ALT="UL" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="js/index.html"><IMG SRC="JS.png" ALT="JS" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="net/index.html"><IMG SRC="NET.png" ALT="NET" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="sl/index.html"><IMG SRC="SL.png" ALT="SL" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
<A HREF="pw/index.html"><IMG SRC="PW.png" ALT="PW" BORDER="0" width=75 height=25></A>
|
||||
<A HREF="puAux/index.html"><IMG SRC="puAux.png" ALT="PUAUX" BORDER="0" width=75 height=25></A><br>
|
||||
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H2>What's Inside PLIB?</H2>
|
||||
PLIB is comprised of a number of semi-autonomous libraries
|
||||
that you can pretty much mix and match - using as much or
|
||||
as little PLIB as you need. The components libraries are:
|
||||
<p>
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD><A HREF="pui/index.html">Picoscopic User Interface Library (PUI)</A></TD>
|
||||
<TD>A fully portable set of GUI widgets that need OpenGL and C++
|
||||
to operate. Useful for games because rendering these widgets is
|
||||
performed very quickly by your 3D hardware.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="sl/index.html">Sound Library (SL)</A></TD>
|
||||
<TD>A fully portable Audio driver suited to C++, GLUT
|
||||
and realtime applications that need low latency. Includes
|
||||
a simple 'MOD' music loader/player.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="sg/index.html">Standard Geometry Library(SG)</A></TD>
|
||||
<TD>A set of matrix and vector math functions that was
|
||||
specifically written to simplify the writing of efficient OpenGL
|
||||
programs. You need to include this code into any SSG applications.
|
||||
Widely used within PLIB itself.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="ssg/index.html">Simple Scene Graph Library (SSG)</A></TD>
|
||||
<TD>A scene graph library layered on top of OpenGL. Also contains code to load and save lots of 3D file formats.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="puAux/index.html">PUI Auxiliary Library (PUAUX)</A></TD>
|
||||
<TD>Additional functionality layered onto PUI - not every PUI program
|
||||
will need these but they can perhaps save you some effort.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="ssgAux/index.html">SSG Auxiliary Library (SSGA)</A></TD>
|
||||
<TD>Additional functionality layered onto SSG - not every SSG program
|
||||
will need these but they can perhaps save you some effort.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="js/index.html">Joystick wrappers (JS)</A></TD>
|
||||
<TD>Supports more Joysticks with more axes and buttons than GLUT.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="fnt/index.html">Fonts'n'Text Library (FNT)</A></TD>
|
||||
<TD>Supports text output in OpenGL using texture mapped fonts.
|
||||
These are much faster to render than GLUT's fonts.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="util/index.html">Utility Library (UL)</A></TD>
|
||||
<TD>A simple portability library to hide basic operating system
|
||||
incompatibilities. Widely used within PLIB itself.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="net/index.html">Pegasus Network Library (NET)</A></TD>
|
||||
<TD>Pegasus is a C++ library for assist you in adding
|
||||
networking to your games.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="psl/index.html">PLIB Scripting Language (PSL)</A></TD>
|
||||
<TD>A very lightweight, stackless C-like scripting language.</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><A HREF="pw/index.html">PLIB Windowing Library (PW)</A></TD>
|
||||
<TD>A lightweight windowing library. This is a very basic
|
||||
library - it only supports a single, double-buffered RGB
|
||||
OpenGL window - with support for keyboard and mouse.
|
||||
Simple though it is, it's usually plenty for OpenGL games
|
||||
and other simple OpenGL applications.</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<p>
|
||||
<H2> Goodies: Samples and Demo's </H2>
|
||||
There are quite a few example programs that each show off
|
||||
one aspect of PLIB's use. We also distribute a set of demonstration
|
||||
programs. These tend to be more complete and usable applications - some
|
||||
games, some tools. These also show off PLIB's features - but in a
|
||||
more holistic way than the example programs.
|
||||
|
||||
<H2>Documentation.</H2>
|
||||
All documentation is available online (click on the package name
|
||||
in the section above) and distributed with PLIB in HTML.
|
||||
<p>
|
||||
There are some interdependencies between the PLIB components - all
|
||||
need the common utility library - many need the standard geometry
|
||||
library for matix operations:
|
||||
<TABLE>
|
||||
<TR>
|
||||
<TD>
|
||||
<ul>
|
||||
<li>PW is independent
|
||||
<li>UL is independent
|
||||
<li>JS depends only on UL
|
||||
<li>SL depends only on UL
|
||||
<li>SG depends only on UL
|
||||
<li>NET depends only on UL
|
||||
</ul>
|
||||
</TD>
|
||||
<TD>
|
||||
<ul>
|
||||
<li>FNT depends on UL and SG
|
||||
<li>SSG depends on UL and SG
|
||||
<li>SSGAUX depends on UL, SG and SSG
|
||||
<li>PUI depends on UL, SG and FNT
|
||||
<li>PUAUX depends on UL, SG, FNT and PUI
|
||||
<li>PSL depends on UL, SG and SSG
|
||||
</ul>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<hr>
|
||||
<ADDRESS>
|
||||
<A HREF="http://www.sjbaker.org">
|
||||
Steve J. Baker.</A>
|
||||
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
doc/whats_inside.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |